summaryrefslogtreecommitdiffstats
path: root/WebCore/platform
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-05 14:34:32 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-05 14:34:32 -0800
commit635860845790a19bf50bbc51ba8fb66a96dde068 (patch)
treeef6ad9ff73a5b57f65249d4232a202fa77e6a140 /WebCore/platform
parent8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (diff)
downloadexternal_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.zip
external_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.tar.gz
external_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.tar.bz2
auto import from //depot/cupcake/@136594
Diffstat (limited to 'WebCore/platform')
-rw-r--r--WebCore/platform/Arena.cpp38
-rw-r--r--WebCore/platform/Arena.h4
-rw-r--r--WebCore/platform/ContextMenu.cpp47
-rw-r--r--WebCore/platform/ContextMenu.h5
-rw-r--r--WebCore/platform/ContextMenuItem.h20
-rw-r--r--WebCore/platform/CookieJar.h16
-rw-r--r--WebCore/platform/DeprecatedPtrListImpl.cpp2
-rw-r--r--WebCore/platform/DeprecatedValueList.h151
-rw-r--r--WebCore/platform/DeprecatedValueListImpl.cpp407
-rw-r--r--WebCore/platform/DeprecatedValueListImpl.h189
-rw-r--r--WebCore/platform/FileSystem.h4
-rw-r--r--WebCore/platform/HostWindow.h6
-rw-r--r--WebCore/platform/KURL.cpp160
-rw-r--r--WebCore/platform/KURL.h126
-rw-r--r--WebCore/platform/LinkHash.cpp210
-rw-r--r--WebCore/platform/LinkHash.h67
-rw-r--r--WebCore/platform/LocalizedStrings.h1
-rw-r--r--WebCore/platform/MIMETypeRegistry.cpp14
-rw-r--r--WebCore/platform/NotImplemented.h2
-rw-r--r--WebCore/platform/PurgeableBuffer.h76
-rw-r--r--WebCore/platform/ScrollView.cpp112
-rw-r--r--WebCore/platform/ScrollView.h27
-rw-r--r--WebCore/platform/Scrollbar.cpp13
-rw-r--r--WebCore/platform/ScrollbarClient.h3
-rw-r--r--WebCore/platform/ScrollbarTheme.h2
-rw-r--r--WebCore/platform/ScrollbarThemeComposite.cpp2
-rw-r--r--WebCore/platform/ScrollbarThemeComposite.h3
-rw-r--r--WebCore/platform/SharedBuffer.cpp28
-rw-r--r--WebCore/platform/SharedBuffer.h17
-rw-r--r--WebCore/platform/SystemTime.h7
-rw-r--r--WebCore/platform/Theme.cpp4
-rw-r--r--WebCore/platform/Theme.h14
-rw-r--r--WebCore/platform/ThemeTypes.h5
-rw-r--r--WebCore/platform/ThreadGlobalData.cpp98
-rw-r--r--WebCore/platform/ThreadGlobalData.h75
-rw-r--r--WebCore/platform/Timer.cpp46
-rw-r--r--WebCore/platform/Timer.h4
-rw-r--r--WebCore/platform/Widget.h2
-rw-r--r--WebCore/platform/android/FileChooserAndroid.cpp5
-rw-r--r--WebCore/platform/android/FileSystemAndroid.cpp31
-rw-r--r--WebCore/platform/android/SharedTimerAndroid.cpp4
-rw-r--r--WebCore/platform/android/SoundAndroid.cpp36
-rw-r--r--WebCore/platform/android/SystemTimeAndroid.cpp28
-rw-r--r--WebCore/platform/android/TemporaryLinkStubs.cpp49
-rw-r--r--WebCore/platform/animation/Animation.cpp126
-rw-r--r--WebCore/platform/animation/Animation.h146
-rw-r--r--WebCore/platform/animation/AnimationList.cpp57
-rw-r--r--WebCore/platform/animation/AnimationList.h60
-rw-r--r--WebCore/platform/animation/TimingFunction.h74
-rw-r--r--WebCore/platform/cf/SharedBufferCF.cpp2
-rw-r--r--WebCore/platform/chromium/ChromiumBridge.h177
-rw-r--r--WebCore/platform/chromium/ChromiumDataObject.cpp58
-rw-r--r--WebCore/platform/chromium/ChromiumDataObject.h73
-rw-r--r--WebCore/platform/chromium/ClipboardChromium.cpp346
-rw-r--r--WebCore/platform/chromium/ClipboardChromium.h84
-rw-r--r--WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp67
-rw-r--r--WebCore/platform/chromium/ClipboardUtilitiesChromium.h43
-rw-r--r--WebCore/platform/chromium/ContextMenuChromium.cpp92
-rw-r--r--WebCore/platform/chromium/ContextMenuItemChromium.cpp109
-rw-r--r--WebCore/platform/chromium/CursorChromium.cpp317
-rw-r--r--WebCore/platform/chromium/DragDataChromium.cpp153
-rw-r--r--WebCore/platform/chromium/DragDataRef.h42
-rw-r--r--WebCore/platform/chromium/DragImageChromium.cpp73
-rw-r--r--WebCore/platform/chromium/DragImageRef.h40
-rw-r--r--WebCore/platform/chromium/FileChooserChromium.cpp (renamed from WebCore/platform/DeprecatedPtrQueue.h)33
-rw-r--r--WebCore/platform/chromium/FileSystemChromium.cpp87
-rw-r--r--WebCore/platform/chromium/FileSystemChromiumLinux.cpp41
-rw-r--r--WebCore/platform/chromium/FileSystemChromiumMac.mm44
-rw-r--r--WebCore/platform/chromium/FileSystemChromiumWin.cpp44
-rw-r--r--WebCore/platform/chromium/FramelessScrollView.cpp87
-rw-r--r--WebCore/platform/chromium/FramelessScrollView.h87
-rw-r--r--WebCore/platform/chromium/FramelessScrollViewClient.h45
-rw-r--r--WebCore/platform/chromium/KeyCodeConversion.h40
-rw-r--r--WebCore/platform/chromium/KeyCodeConversionGtk.cpp364
-rw-r--r--WebCore/platform/chromium/KeyboardCodes.h40
-rw-r--r--WebCore/platform/chromium/KeyboardCodesPosix.h545
-rw-r--r--WebCore/platform/chromium/KeyboardCodesWin.h551
-rw-r--r--WebCore/platform/chromium/Language.cpp47
-rw-r--r--WebCore/platform/chromium/LinkHashChromium.cpp48
-rw-r--r--WebCore/platform/chromium/MimeTypeRegistryChromium.cpp147
-rw-r--r--WebCore/platform/chromium/PasteboardChromium.cpp174
-rw-r--r--WebCore/platform/chromium/PasteboardPrivate.h48
-rw-r--r--WebCore/platform/chromium/PlatformCursor.h109
-rw-r--r--WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp83
-rw-r--r--WebCore/platform/chromium/PlatformScreenChromium.cpp64
-rw-r--r--WebCore/platform/chromium/PlatformWidget.h40
-rw-r--r--WebCore/platform/chromium/PopupMenuChromium.cpp1181
-rw-r--r--WebCore/platform/chromium/PopupMenuChromium.h125
-rw-r--r--WebCore/platform/chromium/PopupMenuPrivate.h46
-rw-r--r--WebCore/platform/chromium/SSLKeyGeneratorChromium.cpp52
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromium.cpp200
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromium.h83
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp148
-rw-r--r--WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp207
-rw-r--r--WebCore/platform/chromium/SearchPopupMenuChromium.cpp59
-rw-r--r--WebCore/platform/chromium/SharedTimerChromium.cpp (renamed from WebCore/platform/gtk/SystemTimeLinux.cpp)26
-rw-r--r--WebCore/platform/chromium/SoundChromiumPosix.cpp43
-rw-r--r--WebCore/platform/chromium/SoundChromiumWin.cpp (renamed from WebCore/platform/wx/SystemTimeWx.cpp)14
-rw-r--r--WebCore/platform/chromium/SystemTimeChromium.cpp52
-rw-r--r--WebCore/platform/chromium/TemporaryLinkStubs.cpp54
-rw-r--r--WebCore/platform/chromium/WidgetChromium.cpp85
-rw-r--r--WebCore/platform/chromium/WindowsVersion.cpp52
-rw-r--r--WebCore/platform/chromium/WindowsVersion.h40
-rw-r--r--WebCore/platform/graphics/BitmapImage.cpp171
-rw-r--r--WebCore/platform/graphics/BitmapImage.h40
-rw-r--r--WebCore/platform/graphics/Color.cpp15
-rw-r--r--WebCore/platform/graphics/FloatPoint.cpp4
-rw-r--r--WebCore/platform/graphics/FloatPoint.h11
-rw-r--r--WebCore/platform/graphics/FloatPoint3D.cpp46
-rw-r--r--WebCore/platform/graphics/FloatPoint3D.h15
-rw-r--r--WebCore/platform/graphics/FloatQuad.cpp60
-rw-r--r--WebCore/platform/graphics/FloatQuad.h138
-rw-r--r--WebCore/platform/graphics/FloatRect.cpp12
-rw-r--r--WebCore/platform/graphics/FloatRect.h4
-rw-r--r--WebCore/platform/graphics/FloatSize.h7
-rw-r--r--WebCore/platform/graphics/Font.cpp390
-rw-r--r--WebCore/platform/graphics/Font.h77
-rw-r--r--WebCore/platform/graphics/FontCache.cpp24
-rw-r--r--WebCore/platform/graphics/FontCache.h42
-rw-r--r--WebCore/platform/graphics/FontFallbackList.cpp18
-rw-r--r--WebCore/platform/graphics/FontFastPath.cpp367
-rw-r--r--WebCore/platform/graphics/GeneratedImage.cpp2
-rw-r--r--WebCore/platform/graphics/GeneratedImage.h5
-rw-r--r--WebCore/platform/graphics/GlyphBuffer.h14
-rw-r--r--WebCore/platform/graphics/GraphicsContext.cpp47
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h45
-rw-r--r--WebCore/platform/graphics/GraphicsContextPrivate.h11
-rw-r--r--WebCore/platform/graphics/Image.cpp29
-rw-r--r--WebCore/platform/graphics/Image.h23
-rw-r--r--WebCore/platform/graphics/ImageBuffer.h7
-rw-r--r--WebCore/platform/graphics/ImageObserver.h3
-rw-r--r--WebCore/platform/graphics/ImageSource.h41
-rw-r--r--WebCore/platform/graphics/IntSize.h6
-rw-r--r--WebCore/platform/graphics/MediaPlayer.h3
-rw-r--r--WebCore/platform/graphics/Path.h20
-rw-r--r--WebCore/platform/graphics/Pattern.h4
-rw-r--r--WebCore/platform/graphics/SegmentedFontData.cpp17
-rw-r--r--WebCore/platform/graphics/SegmentedFontData.h12
-rw-r--r--WebCore/platform/graphics/SimpleFontData.cpp26
-rw-r--r--WebCore/platform/graphics/SimpleFontData.h9
-rw-r--r--WebCore/platform/graphics/StrokeStyleApplier.h38
-rw-r--r--WebCore/platform/graphics/android/FontCacheAndroid.cpp2
-rw-r--r--WebCore/platform/graphics/android/GraphicsContextAndroid.cpp52
-rw-r--r--WebCore/platform/graphics/android/ImageAndroid.cpp11
-rw-r--r--WebCore/platform/graphics/android/ImageBufferAndroid.cpp7
-rw-r--r--WebCore/platform/graphics/android/ImageSourceAndroid.cpp8
-rw-r--r--WebCore/platform/graphics/android/PathAndroid.cpp52
-rw-r--r--WebCore/platform/graphics/android/PatternAndroid.cpp2
-rw-r--r--WebCore/platform/graphics/android/TransformationMatrixAndroid.cpp (renamed from WebCore/platform/graphics/android/AffineTransformAndroid.cpp)162
-rw-r--r--WebCore/platform/graphics/android/android_graphics.cpp2
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp69
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h4
-rw-r--r--WebCore/platform/graphics/cairo/ImageBufferCairo.cpp4
-rw-r--r--WebCore/platform/graphics/cairo/ImageCairo.cpp14
-rw-r--r--WebCore/platform/graphics/cairo/ImageSourceCairo.cpp20
-rw-r--r--WebCore/platform/graphics/cairo/PathCairo.cpp125
-rw-r--r--WebCore/platform/graphics/cairo/PatternCairo.cpp7
-rw-r--r--WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp (renamed from WebCore/platform/graphics/cairo/AffineTransformCairo.cpp)68
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp140
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h6
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp4
-rw-r--r--WebCore/platform/graphics/cg/ImageCG.cpp19
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp23
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.h41
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCGMac.mm48
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCGWin.cpp84
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.h7
-rw-r--r--WebCore/platform/graphics/cg/PathCG.cpp80
-rw-r--r--WebCore/platform/graphics/cg/PatternCG.cpp6
-rw-r--r--WebCore/platform/graphics/cg/TransformationMatrixCG.cpp (renamed from WebCore/platform/graphics/cg/AffineTransformCG.cpp)68
-rw-r--r--WebCore/platform/graphics/chromium/ColorChromium.cpp62
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp602
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheLinux.cpp179
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp327
-rw-r--r--WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp232
-rw-r--r--WebCore/platform/graphics/chromium/FontCustomPlatformData.h70
-rw-r--r--WebCore/platform/graphics/chromium/FontLinux.cpp111
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformData.h40
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp156
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h129
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp139
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.h112
-rw-r--r--WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp352
-rw-r--r--WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h96
-rw-r--r--WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp248
-rw-r--r--WebCore/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp72
-rw-r--r--WebCore/platform/graphics/chromium/IconChromiumLinux.cpp66
-rw-r--r--WebCore/platform/graphics/chromium/IconChromiumMac.cpp60
-rw-r--r--WebCore/platform/graphics/chromium/IconChromiumWin.cpp87
-rw-r--r--WebCore/platform/graphics/chromium/ImageBufferData.h50
-rw-r--r--WebCore/platform/graphics/chromium/ImageChromiumMac.mm58
-rw-r--r--WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h101
-rw-r--r--WebCore/platform/graphics/chromium/PlatformIcon.h42
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp171
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp162
-rw-r--r--WebCore/platform/graphics/chromium/ThemeHelperChromiumWin.cpp104
-rw-r--r--WebCore/platform/graphics/chromium/ThemeHelperChromiumWin.h98
-rw-r--r--WebCore/platform/graphics/chromium/UniscribeHelper.cpp902
-rw-r--r--WebCore/platform/graphics/chromium/UniscribeHelper.h400
-rw-r--r--WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp138
-rw-r--r--WebCore/platform/graphics/chromium/UniscribeHelperTextRun.h96
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp1
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp15
-rw-r--r--WebCore/platform/graphics/mac/ColorMac.h1
-rw-r--r--WebCore/platform/graphics/mac/ColorMac.mm20
-rw-r--r--WebCore/platform/graphics/mac/CoreTextController.cpp6
-rw-r--r--WebCore/platform/graphics/mac/FontCacheMac.mm13
-rw-r--r--WebCore/platform/graphics/mac/FontCustomPlatformData.cpp2
-rw-r--r--WebCore/platform/graphics/mac/FontMacATSUI.mm5
-rw-r--r--WebCore/platform/graphics/mac/FontPlatformDataMac.mm4
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContextMac.mm54
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm31
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm11
-rw-r--r--WebCore/platform/graphics/qt/FontCacheQt.cpp22
-rw-r--r--WebCore/platform/graphics/qt/FontCustomPlatformData.cpp19
-rw-r--r--WebCore/platform/graphics/qt/FontCustomPlatformData.h3
-rw-r--r--WebCore/platform/graphics/qt/FontFallbackListQt.cpp106
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformData.h22
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformDataQt.cpp78
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp550
-rw-r--r--WebCore/platform/graphics/qt/FontQt43.cpp356
-rw-r--r--WebCore/platform/graphics/qt/GlyphPageTreeNodeQt.cpp7
-rw-r--r--WebCore/platform/graphics/qt/GradientQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp106
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp30
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.h19
-rw-r--r--WebCore/platform/graphics/qt/ImageQt.cpp16
-rw-r--r--WebCore/platform/graphics/qt/ImageSourceQt.cpp45
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp62
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h11
-rw-r--r--WebCore/platform/graphics/qt/PathQt.cpp54
-rw-r--r--WebCore/platform/graphics/qt/PatternQt.cpp4
-rw-r--r--WebCore/platform/graphics/qt/SimpleFontDataQt.cpp35
-rw-r--r--WebCore/platform/graphics/qt/StillImageQt.h2
-rw-r--r--WebCore/platform/graphics/qt/TransformationMatrixQt.cpp (renamed from WebCore/platform/graphics/qt/AffineTransformQt.cpp)66
-rw-r--r--WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h86
-rw-r--r--WebCore/platform/graphics/skia/FloatPointSkia.cpp51
-rw-r--r--WebCore/platform/graphics/skia/FloatRectSkia.cpp50
-rw-r--r--WebCore/platform/graphics/skia/GradientSkia.cpp164
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextPlatformPrivate.h55
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp1122
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp210
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp462
-rw-r--r--WebCore/platform/graphics/skia/ImageSourceSkia.cpp247
-rw-r--r--WebCore/platform/graphics/skia/ImageSourceSkia.h60
-rw-r--r--WebCore/platform/graphics/skia/IntPointSkia.cpp56
-rw-r--r--WebCore/platform/graphics/skia/IntRectSkia.cpp57
-rw-r--r--WebCore/platform/graphics/skia/NativeImageSkia.cpp109
-rw-r--r--WebCore/platform/graphics/skia/NativeImageSkia.h104
-rw-r--r--WebCore/platform/graphics/skia/PathSkia.cpp316
-rw-r--r--WebCore/platform/graphics/skia/PatternSkia.cpp77
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.cpp427
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.h173
-rw-r--r--WebCore/platform/graphics/skia/PlatformGraphics.h37
-rw-r--r--WebCore/platform/graphics/skia/SkiaFontWin.cpp218
-rw-r--r--WebCore/platform/graphics/skia/SkiaFontWin.h54
-rw-r--r--WebCore/platform/graphics/skia/SkiaUtils.cpp199
-rw-r--r--WebCore/platform/graphics/skia/SkiaUtils.h82
-rw-r--r--WebCore/platform/graphics/skia/TransformationMatrixSkia.cpp222
-rw-r--r--WebCore/platform/graphics/transforms/IdentityTransformOperation.h67
-rw-r--r--WebCore/platform/graphics/transforms/MatrixTransformOperation.cpp50
-rw-r--r--WebCore/platform/graphics/transforms/MatrixTransformOperation.h82
-rw-r--r--WebCore/platform/graphics/transforms/RotateTransformOperation.cpp40
-rw-r--r--WebCore/platform/graphics/transforms/RotateTransformOperation.h74
-rw-r--r--WebCore/platform/graphics/transforms/ScaleTransformOperation.cpp41
-rw-r--r--WebCore/platform/graphics/transforms/ScaleTransformOperation.h74
-rw-r--r--WebCore/platform/graphics/transforms/SkewTransformOperation.cpp41
-rw-r--r--WebCore/platform/graphics/transforms/SkewTransformOperation.h74
-rw-r--r--WebCore/platform/graphics/transforms/TransformOperation.h64
-rw-r--r--WebCore/platform/graphics/transforms/TransformOperations.cpp49
-rw-r--r--WebCore/platform/graphics/transforms/TransformOperations.h59
-rw-r--r--WebCore/platform/graphics/transforms/TransformationMatrix.cpp (renamed from WebCore/platform/graphics/AffineTransform.cpp)51
-rw-r--r--WebCore/platform/graphics/transforms/TransformationMatrix.h (renamed from WebCore/platform/graphics/AffineTransform.h)82
-rw-r--r--WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp41
-rw-r--r--WebCore/platform/graphics/transforms/TranslateTransformOperation.h75
-rw-r--r--WebCore/platform/graphics/win/FontCGWin.cpp24
-rw-r--r--WebCore/platform/graphics/win/FontCacheWin.cpp2
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformData.cpp10
-rw-r--r--WebCore/platform/graphics/win/FontPlatformData.h1
-rw-r--r--WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp8
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCGWin.cpp18
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp4
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextWin.cpp2
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp7
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.cpp10
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.h4
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataWin.cpp4
-rw-r--r--WebCore/platform/graphics/wx/FontPlatformData.h4
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp18
-rw-r--r--WebCore/platform/graphics/wx/ImageSourceWx.cpp24
-rw-r--r--WebCore/platform/graphics/wx/ImageWx.cpp60
-rw-r--r--WebCore/platform/graphics/wx/PathWx.cpp113
-rw-r--r--WebCore/platform/graphics/wx/TransformationMatrixWx.cpp (renamed from WebCore/platform/graphics/wx/AffineTransformWx.cpp)126
-rw-r--r--WebCore/platform/gtk/FileSystemGtk.cpp1
-rw-r--r--WebCore/platform/gtk/GeolocationServiceGtk.cpp61
-rw-r--r--WebCore/platform/gtk/GeolocationServiceGtk.h41
-rw-r--r--WebCore/platform/gtk/KeyEventGtk.cpp30
-rw-r--r--WebCore/platform/gtk/MIMETypeRegistryGtk.cpp3
-rw-r--r--WebCore/platform/gtk/MouseEventGtk.cpp5
-rw-r--r--WebCore/platform/gtk/PlatformScreenGtk.cpp16
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.cpp17
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.h2
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.cpp19
-rw-r--r--WebCore/platform/gtk/ScrollbarGtk.h3
-rw-r--r--WebCore/platform/gtk/SharedTimerGtk.cpp2
-rw-r--r--WebCore/platform/gtk/TemporaryLinkStubs.cpp2
-rw-r--r--WebCore/platform/gtk/WheelEventGtk.cpp4
-rw-r--r--WebCore/platform/gtk/gtk2drawing.c41
-rw-r--r--WebCore/platform/gtk/gtkdrawing.h2
-rw-r--r--WebCore/platform/image-decoders/ImageDecoder.h22
-rw-r--r--WebCore/platform/image-decoders/bmp/BMPImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp55
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.h4
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageReader.h4
-rw-r--r--WebCore/platform/image-decoders/ico/ICOImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/skia/BMPImageDecoder.cpp82
-rw-r--r--WebCore/platform/image-decoders/skia/BMPImageDecoder.h54
-rw-r--r--WebCore/platform/image-decoders/skia/BMPImageReader.cpp835
-rw-r--r--WebCore/platform/image-decoders/skia/BMPImageReader.h327
-rw-r--r--WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp470
-rw-r--r--WebCore/platform/image-decoders/skia/GIFImageDecoder.h93
-rw-r--r--WebCore/platform/image-decoders/skia/GIFImageReader.cpp951
-rw-r--r--WebCore/platform/image-decoders/skia/GIFImageReader.h215
-rw-r--r--WebCore/platform/image-decoders/skia/ICOImageDecoder.cpp230
-rw-r--r--WebCore/platform/image-decoders/skia/ICOImageDecoder.h118
-rw-r--r--WebCore/platform/image-decoders/skia/ImageDecoder.h333
-rw-r--r--WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp512
-rw-r--r--WebCore/platform/image-decoders/skia/JPEGImageDecoder.h (renamed from WebCore/platform/qt/SharedTimerQt.h)81
-rw-r--r--WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp412
-rw-r--r--WebCore/platform/image-decoders/skia/PNGImageDecoder.h68
-rw-r--r--WebCore/platform/image-decoders/skia/XBMImageDecoder.cpp280
-rw-r--r--WebCore/platform/image-decoders/skia/XBMImageDecoder.h82
-rw-r--r--WebCore/platform/image-decoders/xbm/XBMImageDecoder.h2
-rw-r--r--WebCore/platform/mac/ClipboardMac.mm3
-rw-r--r--WebCore/platform/mac/CookieJar.mm64
-rw-r--r--WebCore/platform/mac/CursorMac.mm71
-rw-r--r--WebCore/platform/mac/DragDataMac.mm2
-rw-r--r--WebCore/platform/mac/DragImageMac.mm32
-rw-r--r--WebCore/platform/mac/LocalizedStringsMac.mm8
-rw-r--r--WebCore/platform/mac/MIMETypeRegistryMac.mm10
-rw-r--r--WebCore/platform/mac/PasteboardMac.mm35
-rw-r--r--WebCore/platform/mac/PlatformMouseEventMac.mm19
-rw-r--r--WebCore/platform/mac/PurgeableBufferMac.cpp164
-rw-r--r--WebCore/platform/mac/ScrollViewMac.mm13
-rw-r--r--WebCore/platform/mac/ScrollbarThemeMac.mm13
-rw-r--r--WebCore/platform/mac/SharedBufferMac.mm10
-rw-r--r--WebCore/platform/mac/SharedTimerMac.mm10
-rw-r--r--WebCore/platform/mac/SystemTimeMac.cpp5
-rw-r--r--WebCore/platform/mac/ThemeMac.mm3
-rw-r--r--WebCore/platform/mac/ThreadCheck.mm3
-rw-r--r--WebCore/platform/mac/WebCoreKeyGenerator.m9
-rw-r--r--WebCore/platform/mac/WebCoreNSStringExtras.h12
-rw-r--r--WebCore/platform/mac/WebCoreNSStringExtras.mm57
-rw-r--r--WebCore/platform/mac/WebCoreObjCExtras.mm10
-rw-r--r--WebCore/platform/mac/WebCoreSystemInterface.h15
-rw-r--r--WebCore/platform/mac/WebCoreSystemInterface.mm13
-rw-r--r--WebCore/platform/mac/WebFontCache.mm10
-rw-r--r--WebCore/platform/mac/WidgetMac.mm18
-rw-r--r--WebCore/platform/network/AuthenticationChallengeBase.h2
-rw-r--r--WebCore/platform/network/FormData.cpp23
-rw-r--r--WebCore/platform/network/FormData.h1
-rw-r--r--WebCore/platform/network/FormDataBuilder.cpp238
-rw-r--r--WebCore/platform/network/FormDataBuilder.h77
-rw-r--r--WebCore/platform/network/HTTPHeaderMap.cpp63
-rw-r--r--WebCore/platform/network/HTTPHeaderMap.h16
-rw-r--r--WebCore/platform/network/NetworkStateNotifier.cpp6
-rw-r--r--WebCore/platform/network/NetworkStateNotifier.h1
-rw-r--r--WebCore/platform/network/ResourceErrorBase.h2
-rw-r--r--WebCore/platform/network/ResourceHandle.h5
-rw-r--r--WebCore/platform/network/ResourceHandleClient.h7
-rw-r--r--WebCore/platform/network/ResourceHandleInternal.h2
-rw-r--r--WebCore/platform/network/ResourceRequestBase.cpp75
-rw-r--r--WebCore/platform/network/ResourceRequestBase.h33
-rw-r--r--WebCore/platform/network/ResourceResponseBase.cpp197
-rw-r--r--WebCore/platform/network/ResourceResponseBase.h61
-rw-r--r--WebCore/platform/network/cf/DNSCFNet.cpp2
-rw-r--r--WebCore/platform/network/cf/ResourceHandleCFNet.cpp97
-rw-r--r--WebCore/platform/network/cf/ResourceRequestCFNet.cpp58
-rw-r--r--WebCore/platform/network/chromium/AuthenticationChallenge.h54
-rw-r--r--WebCore/platform/network/chromium/AuthenticationChallengeChromium.cpp41
-rw-r--r--WebCore/platform/network/chromium/CookieJarChromium.cpp57
-rw-r--r--WebCore/platform/network/chromium/DNSChromium.cpp38
-rw-r--r--WebCore/platform/network/chromium/NetworkStateNotifierChromium.cpp50
-rw-r--r--WebCore/platform/network/chromium/NetworkStateNotifierPrivate.h40
-rw-r--r--WebCore/platform/network/chromium/ResourceError.h51
-rw-r--r--WebCore/platform/network/chromium/ResourceRequest.h128
-rw-r--r--WebCore/platform/network/chromium/ResourceResponse.h81
-rw-r--r--WebCore/platform/network/curl/ResourceHandleCurl.cpp1
-rw-r--r--WebCore/platform/network/curl/ResourceHandleManager.cpp27
-rw-r--r--WebCore/platform/network/mac/FormDataStreamMac.mm13
-rw-r--r--WebCore/platform/network/mac/NetworkStateNotifierMac.cpp10
-rw-r--r--WebCore/platform/network/mac/ResourceHandleMac.mm104
-rw-r--r--WebCore/platform/network/mac/ResourceRequestMac.mm48
-rw-r--r--WebCore/platform/network/mac/ResourceResponseMac.mm3
-rw-r--r--WebCore/platform/network/soup/CookieJarSoup.cpp17
-rw-r--r--WebCore/platform/network/soup/CookieJarSoup.h (renamed from WebCore/platform/qt/SystemTimeQt.cpp)25
-rw-r--r--WebCore/platform/network/soup/ResourceHandleSoup.cpp110
-rw-r--r--WebCore/platform/network/win/CookieJarCFNetWin.cpp76
-rw-r--r--WebCore/platform/network/win/NetworkStateNotifierWin.cpp1
-rw-r--r--WebCore/platform/posix/FileSystemPOSIX.cpp31
-rw-r--r--WebCore/platform/qt/ClipboardQt.cpp2
-rw-r--r--WebCore/platform/qt/CookieJarQt.cpp16
-rw-r--r--WebCore/platform/qt/FileChooserQt.cpp22
-rw-r--r--WebCore/platform/qt/FileSystemQt.cpp4
-rw-r--r--WebCore/platform/qt/KeyboardCodes.h8
-rw-r--r--WebCore/platform/qt/Localizations.cpp5
-rw-r--r--WebCore/platform/qt/LoggingQt.cpp8
-rw-r--r--WebCore/platform/qt/MIMETypeRegistryQt.cpp3
-rw-r--r--WebCore/platform/qt/PlatformMouseEventQt.cpp4
-rw-r--r--WebCore/platform/qt/PlatformScreenQt.cpp11
-rw-r--r--WebCore/platform/qt/QWebPopup.cpp2
-rw-r--r--WebCore/platform/qt/RenderThemeQt.cpp33
-rw-r--r--WebCore/platform/qt/RenderThemeQt.h6
-rw-r--r--WebCore/platform/qt/ScrollbarQt.cpp3
-rw-r--r--WebCore/platform/qt/ScrollbarThemeQt.cpp13
-rw-r--r--WebCore/platform/qt/SharedTimerQt.cpp88
-rw-r--r--WebCore/platform/qt/TemporaryLinkStubs.cpp17
-rw-r--r--WebCore/platform/qt/WebCoreResources.qrc5
-rw-r--r--WebCore/platform/qt/WheelEventQt.cpp4
-rw-r--r--WebCore/platform/qt/WidgetQt.cpp4
-rw-r--r--WebCore/platform/qt/html4-adjustments-qt.css96
-rw-r--r--WebCore/platform/text/AtomicString.cpp62
-rw-r--r--WebCore/platform/text/AtomicString.h8
-rw-r--r--WebCore/platform/text/PlatformString.h38
-rw-r--r--WebCore/platform/text/RegularExpression.cpp122
-rw-r--r--WebCore/platform/text/RegularExpression.h14
-rw-r--r--WebCore/platform/text/String.cpp32
-rw-r--r--WebCore/platform/text/StringHash.h18
-rw-r--r--WebCore/platform/text/StringImpl.cpp55
-rw-r--r--WebCore/platform/text/StringImpl.h16
-rw-r--r--WebCore/platform/text/TextCodecICU.cpp58
-rw-r--r--WebCore/platform/text/TextCodecICU.h10
-rw-r--r--WebCore/platform/text/TextCodecUTF16.cpp7
-rw-r--r--WebCore/platform/text/TextEncoding.cpp36
-rw-r--r--WebCore/platform/text/TextEncoding.h23
-rw-r--r--WebCore/platform/text/TextEncodingRegistry.cpp34
-rw-r--r--WebCore/platform/text/TextStream.cpp5
-rw-r--r--WebCore/platform/text/TextStream.h1
-rw-r--r--WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp (renamed from WebCore/platform/gtk/SystemTimeGtk.cpp)18
-rw-r--r--WebCore/platform/text/mac/ShapeArabic.c7
-rw-r--r--WebCore/platform/text/mac/StringImplMac.mm2
-rw-r--r--WebCore/platform/text/mac/TextCodecMac.cpp32
-rw-r--r--WebCore/platform/text/mac/TextCodecMac.h8
-rw-r--r--WebCore/platform/win/COMPtr.h2
-rw-r--r--WebCore/platform/win/ClipboardWin.cpp11
-rw-r--r--WebCore/platform/win/ContextMenuItemWin.cpp5
-rw-r--r--WebCore/platform/win/DragImageCGWin.cpp5
-rw-r--r--WebCore/platform/win/DragImageCairoWin.cpp155
-rw-r--r--WebCore/platform/win/LoggingWin.cpp100
-rw-r--r--WebCore/platform/win/MIMETypeRegistryWin.cpp20
-rw-r--r--WebCore/platform/win/PopupMenuWin.cpp8
-rw-r--r--WebCore/platform/win/SharedTimerWin.cpp36
-rw-r--r--WebCore/platform/win/SystemTimeWin.cpp13
-rw-r--r--WebCore/platform/win/TemporaryLinkStubs.cpp4
-rw-r--r--WebCore/platform/win/WebCoreTextRenderer.cpp6
-rw-r--r--WebCore/platform/wx/ContextMenuItemWx.cpp108
-rw-r--r--WebCore/platform/wx/ContextMenuWx.cpp112
-rw-r--r--WebCore/platform/wx/LocalizedStringsWx.cpp75
-rw-r--r--WebCore/platform/wx/MimeTypeRegistryWx.cpp1
-rw-r--r--WebCore/platform/wx/MouseEventWx.cpp4
-rw-r--r--WebCore/platform/wx/PasteboardWx.cpp22
-rw-r--r--WebCore/platform/wx/RenderThemeWx.cpp23
-rw-r--r--WebCore/platform/wx/ScrollViewWx.cpp10
-rw-r--r--WebCore/platform/wx/SharedTimerWx.cpp2
-rw-r--r--WebCore/platform/wx/wxcode/gtk/non-kerned-drawing.cpp1
467 files changed, 31468 insertions, 4036 deletions
diff --git a/WebCore/platform/Arena.cpp b/WebCore/platform/Arena.cpp
index 90f850f..2cc8eba 100644
--- a/WebCore/platform/Arena.cpp
+++ b/WebCore/platform/Arena.cpp
@@ -90,8 +90,7 @@ static int CeilingLog2(unsigned int i) {
return log2;
}
-void InitArenaPool(ArenaPool *pool, const char *name,
- unsigned int size, unsigned int align)
+void InitArenaPool(ArenaPool* pool, const char*, unsigned size, unsigned align)
{
if (align == 0)
align = ARENA_DEFAULT_ALIGN;
@@ -196,16 +195,6 @@ void* ArenaAllocate(ArenaPool *pool, unsigned int nb)
}
} /* --- end ArenaAllocate() --- */
-void* ArenaGrow(ArenaPool *pool, void *p, unsigned int size, unsigned int incr)
-{
- void *newp;
-
- ARENA_ALLOCATE(newp, pool, size + incr);
- if (newp)
- memcpy(newp, p, size);
- return newp;
-}
-
/*
* Free tail arenas linked after head, which may not be the true list head.
* Reset pool->current to point to head in case it pointed at a tail arena.
@@ -256,19 +245,6 @@ static void FreeArenaList(ArenaPool *pool, Arena *head, bool reallyFree)
pool->current = head;
}
-void ArenaRelease(ArenaPool *pool, char *mark)
-{
- Arena *a;
-
- for (a = pool->first.next; a; a = a->next) {
- if (UPTRDIFF(mark, a->base) < UPTRDIFF(a->avail, a->base)) {
- a->avail = (uword)ARENA_ALIGN(pool, mark);
- FreeArenaList(pool, a, false);
- return;
- }
- }
-}
-
void FreeArenaPool(ArenaPool *pool)
{
FreeArenaList(pool, &pool->first, false);
@@ -279,4 +255,16 @@ void FinishArenaPool(ArenaPool *pool)
FreeArenaList(pool, &pool->first, true);
}
+#ifdef ANDROID_INSTRUMENT
+size_t ReportPoolSize(const ArenaPool* pool)
+{
+ size_t total = 0;
+ for (const Arena *a = &pool->first; a; a = a->next)
+ total += (a->limit - a->base);
+ for (const Arena *fa = arena_freelist; fa; fa = fa->next )
+ total += (fa->limit - fa->base);
+ return total;
+}
+#endif
+
}
diff --git a/WebCore/platform/Arena.h b/WebCore/platform/Arena.h
index b6f6931..4c9ecf4 100644
--- a/WebCore/platform/Arena.h
+++ b/WebCore/platform/Arena.h
@@ -125,6 +125,10 @@ void* ArenaAllocate(ArenaPool *pool, unsigned int nb);
fastFree(a); \
(a) = 0;
+#ifdef ANDROID_INSTRUMENT
+size_t ReportPoolSize(const ArenaPool* pool);
+#endif
+
}
#endif
diff --git a/WebCore/platform/ContextMenu.cpp b/WebCore/platform/ContextMenu.cpp
index a9c64df..f086b63 100644
--- a/WebCore/platform/ContextMenu.cpp
+++ b/WebCore/platform/ContextMenu.cpp
@@ -43,6 +43,7 @@
#include "Page.h"
#include "ResourceRequest.h"
#include "SelectionController.h"
+#include "Settings.h"
#include "TextIterator.h"
#include <memory>
@@ -171,6 +172,21 @@ static void createAndAppendWritingDirectionSubMenu(const HitTestResult& result,
writingDirectionMenuItem.setSubMenu(&writingDirectionMenu);
}
+
+static void createAndAppendTextDirectionSubMenu(const HitTestResult& result, ContextMenuItem& textDirectionMenuItem)
+{
+ ContextMenu textDirectionMenu(result);
+
+ ContextMenuItem defaultItem(ActionType, ContextMenuItemTagTextDirectionDefault, contextMenuItemTagDefaultDirection());
+ ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagTextDirectionLeftToRight, contextMenuItemTagLeftToRight());
+ ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagTextDirectionRightToLeft, contextMenuItemTagRightToLeft());
+
+ textDirectionMenu.appendItem(defaultItem);
+ textDirectionMenu.appendItem(ltr);
+ textDirectionMenu.appendItem(rtl);
+
+ textDirectionMenuItem.setSubMenu(&textDirectionMenu);
+}
#endif
static bool selectionContainsPossibleWord(Frame* frame)
@@ -408,6 +424,18 @@ void ContextMenu::populate()
contextMenuItemTagWritingDirectionMenu());
createAndAppendWritingDirectionSubMenu(m_hitTestResult, WritingDirectionMenuItem);
appendItem(WritingDirectionMenuItem);
+ if (Page* page = frame->page()) {
+ if (Settings* settings = page->settings()) {
+ bool includeTextDirectionSubmenu = settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAlwaysIncluded
+ || settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAutomaticallyIncluded && frame->editor()->hasBidiSelection();
+ if (includeTextDirectionSubmenu) {
+ ContextMenuItem TextDirectionMenuItem(SubmenuType, ContextMenuItemTagTextDirectionMenu,
+ contextMenuItemTagTextDirectionMenu());
+ createAndAppendTextDirectionSubMenu(m_hitTestResult, TextDirectionMenuItem);
+ appendItem(TextDirectionMenuItem);
+ }
+ }
+ }
#endif
}
}
@@ -465,6 +493,24 @@ void ContextMenu::checkOrEnableIfNeeded(ContextMenuItem& item) const
shouldEnable = true;
break;
}
+ case ContextMenuItemTagTextDirectionDefault: {
+ Editor::Command command = frame->editor()->command("MakeTextWritingDirectionNatural");
+ shouldCheck = command.state() == TrueTriState;
+ shouldEnable = command.isEnabled();
+ break;
+ }
+ case ContextMenuItemTagTextDirectionLeftToRight: {
+ Editor::Command command = frame->editor()->command("MakeTextWritingDirectionLeftToRight");
+ shouldCheck = command.state() == TrueTriState;
+ shouldEnable = command.isEnabled();
+ break;
+ }
+ case ContextMenuItemTagTextDirectionRightToLeft: {
+ Editor::Command command = frame->editor()->command("MakeTextWritingDirectionRightToLeft");
+ shouldCheck = command.state() == TrueTriState;
+ shouldEnable = command.isEnabled();
+ break;
+ }
case ContextMenuItemTagCopy:
shouldEnable = frame->editor()->canDHTMLCopy() || frame->editor()->canCopy();
break;
@@ -595,6 +641,7 @@ void ContextMenu::checkOrEnableIfNeeded(ContextMenuItem& item) const
case ContextMenuItemTagStartSpeaking:
case ContextMenuItemTagStopSpeaking:
case ContextMenuItemTagWritingDirectionMenu:
+ case ContextMenuItemTagTextDirectionMenu:
case ContextMenuItemTagPDFSinglePageScrolling:
case ContextMenuItemTagPDFFacingPagesScrolling:
case ContextMenuItemTagInspectElement:
diff --git a/WebCore/platform/ContextMenu.h b/WebCore/platform/ContextMenu.h
index e10c762..9418ff5 100644
--- a/WebCore/platform/ContextMenu.h
+++ b/WebCore/platform/ContextMenu.h
@@ -69,10 +69,11 @@ class MenuEventProxy;
void setPlatformDescription(PlatformMenuDescription);
PlatformMenuDescription releasePlatformDescription();
-
+#if PLATFORM(WX)
+ static ContextMenuItem* itemWithId(int);
+#endif
private:
HitTestResult m_hitTestResult;
-
#if PLATFORM(MAC)
// Keep this in sync with the PlatformMenuDescription typedef
RetainPtr<NSMutableArray> m_platformDescription;
diff --git a/WebCore/platform/ContextMenuItem.h b/WebCore/platform/ContextMenuItem.h
index 5fb2681..52c4d1b 100644
--- a/WebCore/platform/ContextMenuItem.h
+++ b/WebCore/platform/ContextMenuItem.h
@@ -120,6 +120,10 @@ namespace WebCore {
ContextMenuItemTagPDFSinglePageScrolling,
ContextMenuItemTagPDFFacingPagesScrolling,
ContextMenuItemTagInspectElement,
+ ContextMenuItemTagTextDirectionMenu, // Text Direction sub-menu
+ ContextMenuItemTagTextDirectionDefault,
+ ContextMenuItemTagTextDirectionLeftToRight,
+ ContextMenuItemTagTextDirectionRightToLeft,
ContextMenuItemBaseApplicationTag = 10000
};
@@ -170,7 +174,21 @@ namespace WebCore {
#elif defined ANDROID
typedef void* PlatformMenuItemDescription;
#elif PLATFORM(WX)
- typedef wxMenuItem* PlatformMenuItemDescription;
+ struct PlatformMenuItemDescription {
+ PlatformMenuItemDescription()
+ : type(ActionType),
+ action(ContextMenuItemTagNoAction),
+ checked(false),
+ enabled(true)
+ {}
+
+ ContextMenuItemType type;
+ ContextMenuAction action;
+ String title;
+ wxMenu * subMenu;
+ bool checked;
+ bool enabled;
+ };
#else
typedef void* PlatformMenuItemDescription;
#endif
diff --git a/WebCore/platform/CookieJar.h b/WebCore/platform/CookieJar.h
index 22627f2..178ee79 100644
--- a/WebCore/platform/CookieJar.h
+++ b/WebCore/platform/CookieJar.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,22 +26,16 @@
#ifndef CookieJar_h
#define CookieJar_h
-#if USE(SOUP)
-#include <libsoup/soup.h>
-#endif
-
namespace WebCore {
class KURL;
class String;
class Document;
- String cookies(const Document* document, const KURL&);
- void setCookies(Document* document, const KURL&, const KURL& policyBaseURL, const String&);
- bool cookiesEnabled(const Document* document);
-#if USE(SOUP)
- SoupCookieJar* getCookieJar(void);
-#endif
+ String cookies(const Document*, const KURL&);
+ void setCookies(Document*, const KURL&, const KURL& policyBaseURL, const String&);
+ bool cookiesEnabled(const Document*);
+
}
#endif
diff --git a/WebCore/platform/DeprecatedPtrListImpl.cpp b/WebCore/platform/DeprecatedPtrListImpl.cpp
index b3badc2..6d6112e 100644
--- a/WebCore/platform/DeprecatedPtrListImpl.cpp
+++ b/WebCore/platform/DeprecatedPtrListImpl.cpp
@@ -143,7 +143,7 @@ bool DeprecatedPtrListImpl::insert(unsigned n, const void *item)
return false;
}
- DeprecatedListNode *node = new DeprecatedListNode((void *)item);
+ DeprecatedListNode *node = new DeprecatedListNode(const_cast<void*>(item));
if (n == 0) {
// inserting at head
diff --git a/WebCore/platform/DeprecatedValueList.h b/WebCore/platform/DeprecatedValueList.h
deleted file mode 100644
index 8c00b4b..0000000
--- a/WebCore/platform/DeprecatedValueList.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2004 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.
- */
-
-#ifndef DeprecatedValueList_h
-#define DeprecatedValueList_h
-
-#include "DeprecatedValueListImpl.h"
-
-namespace WebCore {
-
-template <class T> class DeprecatedValueList;
-template <class T> class DeprecatedValueListConstIterator;
-
-template<class T> class DeprecatedValueListNode : private DeprecatedValueListImplNode {
-public:
- DeprecatedValueListNode(const T &val) : value(val) { }
- T value;
- friend class DeprecatedValueList<T>;
-};
-
-template<class T> class DeprecatedValueListIterator {
-public:
- DeprecatedValueListIterator() { }
-
- T& operator*() const { return ((DeprecatedValueListNode<T> *)impl.node())->value; }
-
- DeprecatedValueListIterator &operator++() { ++impl; return *this; }
- DeprecatedValueListIterator &operator--() { --impl; return *this; }
- DeprecatedValueListIterator operator++(int) { return impl++; }
-
- bool operator==(const DeprecatedValueListIterator &other) { return impl == other.impl; }
- bool operator!=(const DeprecatedValueListIterator &other) { return impl != other.impl; }
-
-private:
- DeprecatedValueListIterator(const DeprecatedValueListImplIterator &pImp) : impl(pImp) { }
-
- DeprecatedValueListImplIterator impl;
-
- friend class DeprecatedValueList<T>;
- friend class DeprecatedValueListConstIterator<T>;
-};
-
-template<class T> class DeprecatedValueListConstIterator {
-public:
- DeprecatedValueListConstIterator() { }
- DeprecatedValueListConstIterator(const DeprecatedValueListIterator<T> &it) : impl(it.impl) { }
-
- const T& operator*() const { return ((const DeprecatedValueListNode<T> *)impl.node())->value; }
-
- DeprecatedValueListConstIterator &operator++() { ++impl; return *this; }
- DeprecatedValueListConstIterator &operator--() { --impl; return *this; }
- DeprecatedValueListConstIterator operator++(int) { return impl++; }
-
- bool operator==(const DeprecatedValueListConstIterator &other) { return impl == other.impl; }
- bool operator!=(const DeprecatedValueListConstIterator &other) { return impl != other.impl; }
-
-private:
- DeprecatedValueListConstIterator(const DeprecatedValueListImplIterator &pImp) : impl(pImp) { }
-
- DeprecatedValueListImplIterator impl;
-
- friend class DeprecatedValueList<T>;
-};
-
-template<class T> bool operator==(const DeprecatedValueList<T> &a, const DeprecatedValueList<T> &b);
-
-template <class T> class DeprecatedValueList {
-public:
- typedef DeprecatedValueListIterator<T> Iterator;
- typedef DeprecatedValueListIterator<T> iterator;
- typedef DeprecatedValueListConstIterator<T> ConstIterator;
- typedef DeprecatedValueListConstIterator<T> const_iterator;
-
- DeprecatedValueList() : impl(deleteNode, copyNode) { }
-
- void clear() { impl.clear(); }
- unsigned count() const { return impl.count(); }
- bool isEmpty() const { return impl.isEmpty(); }
-
- Iterator append(const T &val) { return impl.appendNode(new DeprecatedValueListNode<T>(val)); }
- Iterator prepend(const T &val) { return impl.prependNode(new DeprecatedValueListNode<T>(val)); }
- void remove(const T &val) { DeprecatedValueListNode<T> node(val); impl.removeEqualNodes(&node, nodesEqual); }
- unsigned contains(const T &val) const { DeprecatedValueListNode<T> node(val); return impl.containsEqualNodes(&node, nodesEqual); }
- Iterator find(const T &val) const { DeprecatedValueListNode<T> node(val); return impl.findEqualNode(&node, nodesEqual); }
-
- Iterator insert(Iterator iter, const T& val) { return impl.insert(iter.impl, new DeprecatedValueListNode<T>(val)); }
- Iterator remove(Iterator iter) { return impl.removeIterator(iter.impl); }
- Iterator fromLast() { return impl.fromLast(); }
-
- T& first() { return static_cast<DeprecatedValueListNode<T> *>(impl.firstNode())->value; }
- const T& first() const { return static_cast<DeprecatedValueListNode<T> *>(impl.firstNode())->value; }
- T& last() { return static_cast<DeprecatedValueListNode<T> *>(impl.lastNode())->value; }
- const T& last() const { return static_cast<DeprecatedValueListNode<T> *>(impl.lastNode())->value; }
-
- Iterator begin() { return impl.begin(); }
- Iterator end() { return impl.end(); }
-
- ConstIterator begin() const { return impl.begin(); }
- ConstIterator end() const { return impl.end(); }
- ConstIterator constBegin() const { return impl.begin(); }
- ConstIterator constEnd() const { return impl.end(); }
- ConstIterator fromLast() const { return impl.fromLast(); }
-
- T& operator[] (unsigned index) { return ((DeprecatedValueListNode<T> *)impl.nodeAt(index))->value; }
- const T& operator[] (unsigned index) const { return ((const DeprecatedValueListNode<T> *)impl.nodeAt(index))->value; }
- DeprecatedValueList &operator+=(const T &value) { impl.appendNode(new DeprecatedValueListNode<T>(value)); return *this; }
- DeprecatedValueList &operator<<(const T &value) { impl.appendNode(new DeprecatedValueListNode<T>(value)); return *this; }
-
- friend bool operator==<>(const DeprecatedValueList<T> &, const DeprecatedValueList<T> &);
-
-private:
- DeprecatedValueListImpl impl;
-
- static void deleteNode(DeprecatedValueListImplNode *node) { delete (DeprecatedValueListNode<T> *)node; }
- static bool nodesEqual(const DeprecatedValueListImplNode *a, const DeprecatedValueListImplNode *b)
- { return ((DeprecatedValueListNode<T> *)a)->value == ((DeprecatedValueListNode<T> *)b)->value; }
- static DeprecatedValueListImplNode *copyNode(DeprecatedValueListImplNode *node)
- { return new DeprecatedValueListNode<T>(((DeprecatedValueListNode<T> *)node)->value); }
-};
-
-template<class T>
-inline bool operator==(const DeprecatedValueList<T> &a, const DeprecatedValueList<T> &b)
-{
- return a.impl.isEqual(b.impl, DeprecatedValueList<T>::nodesEqual);
-}
-
-}
-
-#endif
diff --git a/WebCore/platform/DeprecatedValueListImpl.cpp b/WebCore/platform/DeprecatedValueListImpl.cpp
deleted file mode 100644
index dc8c660..0000000
--- a/WebCore/platform/DeprecatedValueListImpl.cpp
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE 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 "DeprecatedValueListImpl.h"
-
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-#include <stdlib.h>
-
-namespace WebCore {
-
-class DeprecatedValueListImpl::Private : public RefCounted<DeprecatedValueListImpl::Private> {
-public:
- Private(void (*deleteFunc)(DeprecatedValueListImplNode *), DeprecatedValueListImplNode *(*copyFunc)(DeprecatedValueListImplNode *));
- Private(const Private &other);
-
- ~Private();
-
- void copyList(DeprecatedValueListImplNode *l, DeprecatedValueListImplNode *&head, DeprecatedValueListImplNode *&tail) const;
- void deleteList(DeprecatedValueListImplNode *l);
-
- DeprecatedValueListImplNode *head;
- DeprecatedValueListImplNode *tail;
-
- void (*deleteNode)(DeprecatedValueListImplNode *);
- DeprecatedValueListImplNode *(*copyNode)(DeprecatedValueListImplNode *);
- unsigned count;
-};
-
-inline DeprecatedValueListImpl::Private::Private(void (*deleteFunc)(DeprecatedValueListImplNode*),
- DeprecatedValueListImplNode* (*copyFunc)(DeprecatedValueListImplNode*))
- : head(NULL)
- , tail(NULL)
- , deleteNode(deleteFunc)
- , copyNode(copyFunc)
- , count(0)
-{
-}
-
-inline DeprecatedValueListImpl::Private::Private(const Private &other)
- : RefCounted<Private>()
- , deleteNode(other.deleteNode)
- , copyNode(other.copyNode)
- , count(other.count)
-{
- other.copyList(other.head, head, tail);
-}
-
-inline DeprecatedValueListImpl::Private::~Private()
-{
- deleteList(head);
-}
-
-void DeprecatedValueListImpl::Private::copyList(DeprecatedValueListImplNode *l, DeprecatedValueListImplNode *&head, DeprecatedValueListImplNode *&tail) const
-{
- DeprecatedValueListImplNode *prev = NULL;
- DeprecatedValueListImplNode *node = l;
-
- head = NULL;
-
- while (node != NULL) {
- DeprecatedValueListImplNode *copy = copyNode(node);
- if (prev == NULL) {
- head = copy;
- } else {
- prev->next = copy;
- }
-
- copy->prev = prev;
- copy->next = NULL;
-
- prev = copy;
- node = node->next;
- }
-
- tail = prev;
-}
-
-void DeprecatedValueListImpl::Private::deleteList(DeprecatedValueListImplNode *l)
-{
- DeprecatedValueListImplNode *p = l;
-
- while (p != NULL) {
- DeprecatedValueListImplNode *next = p->next;
- deleteNode(p);
- p = next;
- }
-}
-
-DeprecatedValueListImpl::DeprecatedValueListImpl(void (*deleteFunc)(DeprecatedValueListImplNode *), DeprecatedValueListImplNode *(*copyFunc)(DeprecatedValueListImplNode *)) :
- d(adoptRef(new Private(deleteFunc, copyFunc)))
-{
-}
-
-DeprecatedValueListImpl::DeprecatedValueListImpl(const DeprecatedValueListImpl &other) :
- d(other.d)
-{
-}
-
-DeprecatedValueListImpl::~DeprecatedValueListImpl()
-{
-}
-
-void DeprecatedValueListImpl::clear()
-{
- if (d->head) {
- copyOnWrite();
- d->deleteList(d->head);
- d->head = NULL;
- d->tail = NULL;
- d->count = 0;
- }
-}
-
-unsigned DeprecatedValueListImpl::count() const
-{
- return d->count;
-}
-
-bool DeprecatedValueListImpl::isEmpty() const
-{
- return d->count == 0;
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::appendNode(DeprecatedValueListImplNode *node)
-{
- copyOnWrite();
-
- node->next = NULL;
- node->prev = d->tail;
- d->tail = node;
-
- if (d->head == NULL) {
- d->head = node;
- } else {
- node->prev->next = node;
- }
-
- d->count++;
-
- return node;
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::prependNode(DeprecatedValueListImplNode *node)
-{
- copyOnWrite();
-
- node->next = d->head;
- node->prev = NULL;
- d->head = node;
-
- if (d->tail == NULL) {
- d->tail = node;
- } else {
- node->next->prev = node;
- }
-
- d->count++;
-
- return node;
-}
-
-void DeprecatedValueListImpl::removeEqualNodes(DeprecatedValueListImplNode *node, bool (*equalFunc)(const DeprecatedValueListImplNode *, const DeprecatedValueListImplNode *))
-{
- copyOnWrite();
-
- DeprecatedValueListImplNode *next;
- for (DeprecatedValueListImplNode *p = d->head; p != NULL; p = next) {
- next = p->next;
- if (equalFunc(node, p)) {
- if (p->next != NULL) {
- p->next->prev = p->prev;
- } else {
- d->tail = p->prev;
- }
-
- if (p->prev != NULL) {
- p->prev->next = p->next;
- } else {
- d->head = p->next;
- }
-
- d->deleteNode(p);
-
- d->count--;
- }
- }
-}
-
-unsigned DeprecatedValueListImpl::containsEqualNodes(DeprecatedValueListImplNode *node, bool (*equalFunc)(const DeprecatedValueListImplNode *, const DeprecatedValueListImplNode *)) const
-{
- unsigned contains = 0;
-
- for (DeprecatedValueListImplNode *p = d->head; p != NULL; p = p->next) {
- if (equalFunc(node, p)) {
- ++contains;
- }
- }
-
- return contains;
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::findEqualNode(DeprecatedValueListImplNode *node, bool (*equalFunc)(const DeprecatedValueListImplNode *, const DeprecatedValueListImplNode *)) const
-{
- DeprecatedValueListImplIterator it = begin();
- DeprecatedValueListImplIterator endIt = end();
- while (it != endIt) {
- if (equalFunc(node, it.node())) {
- break;
- }
- it++;
- }
- return it;
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::insert(const DeprecatedValueListImplIterator &iterator, DeprecatedValueListImplNode *node)
-{
- copyOnWrite();
-
- DeprecatedValueListImplNode *next = iterator.nodeImpl;
-
- if (next == NULL)
- return appendNode(node);
-
- if (next == d->head)
- return prependNode(node);
-
- DeprecatedValueListImplNode *prev = next->prev;
-
- node->next = next;
- node->prev = prev;
- next->prev = node;
- prev->next = node;
-
- d->count++;
-
- return node;
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::removeIterator(DeprecatedValueListImplIterator &iterator)
-{
- copyOnWrite();
-
- if (iterator.nodeImpl == NULL) {
- return iterator;
- }
-
- DeprecatedValueListImplNode *next = iterator.nodeImpl->next;
-
- // detach node
- if (iterator.nodeImpl->next != NULL) {
- iterator.nodeImpl->next->prev = iterator.nodeImpl->prev;
- } else {
- d->tail = iterator.nodeImpl->prev;
- }
- if (iterator.nodeImpl->prev != NULL) {
- iterator.nodeImpl->prev->next = iterator.nodeImpl->next;
- } else {
- d->head = iterator.nodeImpl->next;
- }
-
- d->deleteNode(iterator.nodeImpl);
- d->count--;
-
- return DeprecatedValueListImplIterator(next);
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::fromLast()
-{
- copyOnWrite();
- return DeprecatedValueListImplIterator(lastNode());
-}
-
-DeprecatedValueListImplNode *DeprecatedValueListImpl::firstNode()
-{
- copyOnWrite();
- return ((const DeprecatedValueListImpl *)this)->firstNode();
-}
-
-DeprecatedValueListImplNode *DeprecatedValueListImpl::lastNode()
-{
- copyOnWrite();
- return ((const DeprecatedValueListImpl *)this)->lastNode();
-}
-
-DeprecatedValueListImplNode *DeprecatedValueListImpl::firstNode() const
-{
- return d->head;
-}
-
-DeprecatedValueListImplNode *DeprecatedValueListImpl::lastNode() const
-{
- return d->tail;
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::begin()
-{
- copyOnWrite();
- return ((const DeprecatedValueListImpl *)this)->begin();
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::end()
-{
- copyOnWrite();
- return ((const DeprecatedValueListImpl *)this)->end();
-}
-
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::begin() const
-{
- return DeprecatedValueListImplIterator(firstNode());
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::end() const
-{
- return DeprecatedValueListImplIterator(NULL);
-}
-
-DeprecatedValueListImplIterator DeprecatedValueListImpl::fromLast() const
-{
- return DeprecatedValueListImplIterator(lastNode());
-}
-
-DeprecatedValueListImplNode *DeprecatedValueListImpl::nodeAt(unsigned index)
-{
- copyOnWrite();
-
- if (d->count <= index) {
- return NULL;
- }
-
- DeprecatedValueListImplNode *p = d->head;
-
- for (unsigned i = 0; i < index; i++) {
- p = p->next;
- }
-
- return p;
-}
-
-DeprecatedValueListImplNode *DeprecatedValueListImpl::nodeAt(unsigned index) const
-{
- if (d->count <= index) {
- return NULL;
- }
-
- DeprecatedValueListImplNode *p = d->head;
-
- for (unsigned i = 0; i < index; i++) {
- p = p->next;
- }
-
- return p;
-}
-
-DeprecatedValueListImpl& DeprecatedValueListImpl::operator=(const DeprecatedValueListImpl &other)
-{
- DeprecatedValueListImpl tmp(other);
- RefPtr<Private> tmpD = tmp.d;
-
- tmp.d = d;
- d = tmpD;
-
- return *this;
-}
-
-void DeprecatedValueListImpl::copyOnWrite()
-{
- if (!d->hasOneRef())
- d = adoptRef(new Private(*d));
-}
-
-bool DeprecatedValueListImpl::isEqual(const DeprecatedValueListImpl &other, bool (*equalFunc)(const DeprecatedValueListImplNode *, const DeprecatedValueListImplNode *)) const
-{
- DeprecatedValueListImplNode *p, *q;
- for (p = d->head, q = other.d->head; p && q; p = p->next, q = q->next) {
- if (!equalFunc(p, q)) {
- return false;
- }
- }
- return !p && !q;
-}
-
-}
diff --git a/WebCore/platform/DeprecatedValueListImpl.h b/WebCore/platform/DeprecatedValueListImpl.h
deleted file mode 100644
index 108f008..0000000
--- a/WebCore/platform/DeprecatedValueListImpl.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2003 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.
- */
-
-#ifndef DeprecatedValueListImpl_h
-#define DeprecatedValueListImpl_h
-
-#include <wtf/RefPtr.h>
-
-namespace WebCore {
-
-class DeprecatedValueListImplNode;
-
-class DeprecatedValueListImplIterator
-{
-public:
- DeprecatedValueListImplIterator();
-
- bool operator==(const DeprecatedValueListImplIterator &other);
- bool operator!=(const DeprecatedValueListImplIterator &other);
-
- DeprecatedValueListImplNode *node();
- const DeprecatedValueListImplNode *node() const;
-
- DeprecatedValueListImplIterator& operator++();
- DeprecatedValueListImplIterator operator++(int);
- DeprecatedValueListImplIterator& operator--();
-
-private:
- DeprecatedValueListImplIterator(const DeprecatedValueListImplNode *n);
-
- DeprecatedValueListImplNode *nodeImpl;
-
- friend class DeprecatedValueListImpl;
-};
-
-class DeprecatedValueListImpl
-{
-public:
- DeprecatedValueListImpl(void (*deleteFunc)(DeprecatedValueListImplNode *), DeprecatedValueListImplNode *(*copyNode)(DeprecatedValueListImplNode *));
- ~DeprecatedValueListImpl();
-
- DeprecatedValueListImpl(const DeprecatedValueListImpl&);
- DeprecatedValueListImpl& operator=(const DeprecatedValueListImpl&);
-
- void clear();
- unsigned count() const;
- bool isEmpty() const;
-
- DeprecatedValueListImplIterator appendNode(DeprecatedValueListImplNode *node);
- DeprecatedValueListImplIterator prependNode(DeprecatedValueListImplNode *node);
- void removeEqualNodes(DeprecatedValueListImplNode *node, bool (*equalFunc)(const DeprecatedValueListImplNode *, const DeprecatedValueListImplNode *));
- unsigned containsEqualNodes(DeprecatedValueListImplNode *node, bool (*equalFunc)(const DeprecatedValueListImplNode *, const DeprecatedValueListImplNode *)) const;
-
- DeprecatedValueListImplIterator findEqualNode(DeprecatedValueListImplNode *node, bool (*equalFunc)(const DeprecatedValueListImplNode *, const DeprecatedValueListImplNode *)) const;
-
- DeprecatedValueListImplIterator insert(const DeprecatedValueListImplIterator &iterator, DeprecatedValueListImplNode* node);
- DeprecatedValueListImplIterator removeIterator(DeprecatedValueListImplIterator &iterator);
- DeprecatedValueListImplIterator fromLast();
-
- DeprecatedValueListImplNode *firstNode();
- DeprecatedValueListImplNode *lastNode();
-
- DeprecatedValueListImplNode *firstNode() const;
- DeprecatedValueListImplNode *lastNode() const;
-
- DeprecatedValueListImplIterator begin();
- DeprecatedValueListImplIterator end();
-
- DeprecatedValueListImplIterator begin() const;
- DeprecatedValueListImplIterator end() const;
- DeprecatedValueListImplIterator fromLast() const;
-
- DeprecatedValueListImplNode *nodeAt(unsigned index);
- DeprecatedValueListImplNode *nodeAt(unsigned index) const;
-
- bool isEqual(const DeprecatedValueListImpl &other, bool (*equalFunc)(const DeprecatedValueListImplNode *, const DeprecatedValueListImplNode *)) const;
-
-private:
- void copyOnWrite();
-
- class Private;
-
- RefPtr<Private> d;
-
- friend class DeprecatedValueListImplNode;
-};
-
-class DeprecatedValueListImplNode
-{
-protected:
- DeprecatedValueListImplNode();
-
-private:
- DeprecatedValueListImplNode *prev;
- DeprecatedValueListImplNode *next;
-
- friend class DeprecatedValueListImpl;
- friend class DeprecatedValueListImplIterator;
- friend class DeprecatedValueListImpl::Private;
-};
-
-inline DeprecatedValueListImplIterator::DeprecatedValueListImplIterator() :
- nodeImpl(NULL)
-{
-}
-
-inline bool DeprecatedValueListImplIterator::operator==(const DeprecatedValueListImplIterator &other)
-{
- return nodeImpl == other.nodeImpl;
-}
-
-inline bool DeprecatedValueListImplIterator::operator!=(const DeprecatedValueListImplIterator &other)
-{
- return nodeImpl != other.nodeImpl;
-}
-
-inline DeprecatedValueListImplNode *DeprecatedValueListImplIterator::node()
-{
- return nodeImpl;
-}
-
-inline const DeprecatedValueListImplNode *DeprecatedValueListImplIterator::node() const
-{
- return nodeImpl;
-}
-
-inline DeprecatedValueListImplIterator& DeprecatedValueListImplIterator::operator++()
-{
- if (nodeImpl != NULL) {
- nodeImpl = nodeImpl->next;
- }
- return *this;
-}
-
-inline DeprecatedValueListImplIterator DeprecatedValueListImplIterator::operator++(int)
-{
- DeprecatedValueListImplIterator tmp(*this);
-
- if (nodeImpl != NULL) {
- nodeImpl = nodeImpl->next;
- }
-
- return tmp;
-}
-
-inline DeprecatedValueListImplIterator& DeprecatedValueListImplIterator::operator--()
-{
- if (nodeImpl != NULL) {
- nodeImpl = nodeImpl->prev;
- }
- return *this;
-}
-
-inline DeprecatedValueListImplIterator::DeprecatedValueListImplIterator(const DeprecatedValueListImplNode *n) :
- nodeImpl((DeprecatedValueListImplNode *)n)
-{
-}
-
-inline DeprecatedValueListImplNode::DeprecatedValueListImplNode() :
- prev(NULL),
- next(NULL)
-{
-}
-
-}
-
-#endif
diff --git a/WebCore/platform/FileSystem.h b/WebCore/platform/FileSystem.h
index a3d5d2d..66dbc20 100644
--- a/WebCore/platform/FileSystem.h
+++ b/WebCore/platform/FileSystem.h
@@ -97,10 +97,10 @@ const PlatformFileHandle invalidPlatformFileHandle = 0;
#if defined(Q_WS_MAC)
typedef CFBundleRef PlatformModule;
typedef unsigned PlatformModuleVersion;
-#elif defined(Q_WS_X11) || defined(Q_WS_QWS)
+#elif defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_S60)
typedef QLibrary* PlatformModule;
typedef unsigned PlatformModuleVersion;
-#elif defined(Q_OS_WIN32)
+#elif defined(Q_OS_WIN)
typedef HMODULE PlatformModule;
struct PlatformModuleVersion {
unsigned leastSig;
diff --git a/WebCore/platform/HostWindow.h b/WebCore/platform/HostWindow.h
index 761e3d7..7007ac5 100644
--- a/WebCore/platform/HostWindow.h
+++ b/WebCore/platform/HostWindow.h
@@ -52,9 +52,13 @@ public:
// Methods for doing coordinate conversions to and from screen coordinates.
virtual IntPoint screenToWindow(const IntPoint&) const = 0;
virtual IntRect windowToScreen(const IntRect&) const = 0;
-
+
// Method for retrieving the native window.
virtual PlatformWidget platformWindow() const = 0;
+
+ // For scrolling a rect into view recursively. Useful in the cases where a WebView is embedded inside some containing
+ // platform-specific ScrollView.
+ virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const = 0;
};
} // namespace WebCore
diff --git a/WebCore/platform/KURL.cpp b/WebCore/platform/KURL.cpp
index 1f33297..6fcb9b9 100644
--- a/WebCore/platform/KURL.cpp
+++ b/WebCore/platform/KURL.cpp
@@ -24,11 +24,15 @@
*/
#include "config.h"
+
+#if !USE(GOOGLEURL)
+
#include "KURL.h"
#include "CString.h"
#include "PlatformString.h"
#include "TextEncoding.h"
+#include <wtf/StdLibExtras.h>
#if USE(ICU_UNICODE)
#include <unicode/uidna.h>
@@ -239,6 +243,14 @@ static void copyASCII(const UChar* src, int length, char* dest)
dest[i] = static_cast<char>(src[i]);
}
+static void appendASCII(const String& base, const char* rel, size_t len, CharBuffer& buffer)
+{
+ buffer.resize(base.length() + len + 1);
+ copyASCII(base.characters(), base.length(), buffer.data());
+ memcpy(buffer.data() + base.length(), rel, len);
+ buffer[buffer.size() - 1] = '\0';
+}
+
// FIXME: Move to PlatformString.h eventually.
// Returns the index of the first index in string |s| of any of the characters
// in |toFind|. |toFind| should be a null-terminated string, all characters up
@@ -255,6 +267,20 @@ static int findFirstOf(const UChar* s, int sLen, int startPos, const char* toFin
return -1;
}
+#ifndef NDEBUG
+static void checkEncodedString(const String& url)
+{
+ for (unsigned i = 0; i < url.length(); ++i)
+ ASSERT(!(url[i] & ~0x7F));
+
+ ASSERT(!url.length() || isSchemeFirstChar(url[0]));
+}
+#else
+static inline void checkEncodedString(const String&)
+{
+}
+#endif
+
inline bool KURL::protocolIs(const String& string, const char* protocol)
{
return WebCore::protocolIs(string, protocol);
@@ -277,39 +303,16 @@ void KURL::invalidate()
KURL::KURL(const char* url)
{
- if (!url || url[0] != '/') {
- parse(url, 0);
- return;
- }
-
- size_t urlLength = strlen(url) + 1;
- CharBuffer buffer(urlLength + 5); // 5 for "file:".
- buffer[0] = 'f';
- buffer[1] = 'i';
- buffer[2] = 'l';
- buffer[3] = 'e';
- buffer[4] = ':';
- memcpy(&buffer[5], url, urlLength);
- parse(buffer.data(), 0);
+ parse(url, 0);
+ ASSERT(url == m_string);
}
KURL::KURL(const String& url)
{
- if (url[0] != '/') {
- parse(url);
- return;
- }
-
- CharBuffer buffer(url.length() + 6); // 5 for "file:", 1 for terminator.
- buffer[0] = 'f';
- buffer[1] = 'i';
- buffer[2] = 'l';
- buffer[3] = 'e';
- buffer[4] = ':';
- copyASCII(url.characters(), url.length(), &buffer[5]);
- buffer[url.length() + 5] = '\0'; // Need null terminator.
+ checkEncodedString(url);
- parse(buffer.data(), 0);
+ parse(url);
+ ASSERT(url == m_string);
}
KURL::KURL(const KURL& base, const String& relative)
@@ -319,7 +322,11 @@ KURL::KURL(const KURL& base, const String& relative)
KURL::KURL(const KURL& base, const String& relative, const TextEncoding& encoding)
{
- init(base, relative, encoding);
+ // For UTF-{7,16,32}, we want to use UTF-8 for the query part as
+ // we do when submitting a form. A form with GET method
+ // has its contents added to a URL as query params and it makes sense
+ // to be consistent.
+ init(base, relative, encoding.encodingForFormSubmission());
}
void KURL::init(const KURL& base, const String& relative, const TextEncoding& encoding)
@@ -391,15 +398,18 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
}
}
+ CharBuffer parseBuffer;
+
if (absolute) {
parse(str, originalString);
} else {
// If the base is empty or opaque (e.g. data: or javascript:), then the URL is invalid
// unless the relative URL is a single fragment.
if (!base.isHierarchical()) {
- if (str[0] == '#')
- parse(base.m_string.left(base.m_queryEnd) + (allASCII ? String(str) : String::fromUTF8(str)));
- else {
+ if (str[0] == '#') {
+ appendASCII(base.m_string.left(base.m_queryEnd), str, len, parseBuffer);
+ parse(parseBuffer.data(), 0);
+ } else {
m_string = relative;
invalidate();
}
@@ -412,22 +422,28 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
// reference to the same document
*this = base;
break;
- case '#':
+ case '#': {
// must be fragment-only reference
- parse(base.m_string.left(base.m_queryEnd) + (allASCII ? String(str) : String::fromUTF8(str)));
+ appendASCII(base.m_string.left(base.m_queryEnd), str, len, parseBuffer);
+ parse(parseBuffer.data(), 0);
break;
- case '?':
+ }
+ case '?': {
// query-only reference, special case needed for non-URL results
- parse(base.m_string.left(base.m_pathEnd) + (allASCII ? String(str) : String::fromUTF8(str)));
+ appendASCII(base.m_string.left(base.m_pathEnd), str, len, parseBuffer);
+ parse(parseBuffer.data(), 0);
break;
+ }
case '/':
// must be net-path or absolute-path reference
if (str[1] == '/') {
// net-path
- parse(base.m_string.left(base.m_schemeEnd + 1) + (allASCII ? String(str) : String::fromUTF8(str)));
+ appendASCII(base.m_string.left(base.m_schemeEnd + 1), str, len, parseBuffer);
+ parse(parseBuffer.data(), 0);
} else {
// abs-path
- parse(base.m_string.left(base.m_portEnd) + (allASCII ? String(str) : String::fromUTF8(str)));
+ appendASCII(base.m_string.left(base.m_portEnd), str, len, parseBuffer);
+ parse(parseBuffer.data(), 0);
}
break;
default:
@@ -435,16 +451,15 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
// must be relative-path reference
// Base part plus relative part plus one possible slash added in between plus terminating \0 byte.
- CharBuffer buffer(base.m_pathEnd + 1 + len + 1);
+ parseBuffer.resize(base.m_pathEnd + 1 + len + 1);
- char* bufferPos = buffer.data();
+ char* bufferPos = parseBuffer.data();
// first copy everything before the path from the base
unsigned baseLength = base.m_string.length();
const UChar* baseCharacters = base.m_string.characters();
CharBuffer baseStringBuffer(baseLength);
- for (unsigned i = 0; i < baseLength; ++i)
- baseStringBuffer[i] = static_cast<char>(baseCharacters[i]);
+ copyASCII(baseCharacters, baseLength, baseStringBuffer.data());
const char* baseString = baseStringBuffer.data();
const char* baseStringStart = baseString;
const char* pathStart = baseStringStart + base.m_portEnd;
@@ -503,15 +518,22 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
// of the relative reference; this will also add a null terminator
strcpy(bufferPos, relStringPos);
- parse(buffer.data(), 0);
+ parse(parseBuffer.data(), 0);
- ASSERT(strlen(buffer.data()) + 1 <= buffer.size());
+ ASSERT(strlen(parseBuffer.data()) + 1 <= parseBuffer.size());
break;
}
}
}
}
+KURL KURL::copy() const
+{
+ KURL result = *this;
+ result.m_string = result.m_string.copy();
+ return result;
+}
+
bool KURL::hasPath() const
{
return m_pathEnd != m_portEnd;
@@ -582,17 +604,25 @@ bool KURL::hasRef() const
return m_fragmentEnd != m_queryEnd;
}
-static inline void assertProtocolIsGood(const char* protocol)
+#ifdef NDEBUG
+
+static inline void assertProtocolIsGood(const char*)
+{
+}
+
+#else
+
+static void assertProtocolIsGood(const char* protocol)
{
-#ifndef NDEBUG
const char* p = protocol;
while (*p) {
ASSERT(*p > ' ' && *p < 0x7F && !(*p >= 'A' && *p <= 'Z'));
++p;
}
-#endif
}
+#endif
+
bool KURL::protocolIs(const char* protocol) const
{
// Do the comparison without making a new string object.
@@ -618,6 +648,9 @@ String KURL::path() const
void KURL::setProtocol(const String& s)
{
+ // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations,
+ // and to avoid changing more than just the protocol.
+
if (!m_isValid) {
parse(s + ":" + m_string);
return;
@@ -631,6 +664,9 @@ void KURL::setHost(const String& s)
if (!m_isValid)
return;
+ // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations,
+ // and to avoid changing more than just the host.
+
bool slashSlashNeeded = m_userStart == m_schemeEnd + 1;
parse(m_string.left(hostStart()) + (slashSlashNeeded ? "//" : "") + s + m_string.substring(m_hostEnd));
@@ -641,6 +677,9 @@ void KURL::setPort(unsigned short i)
if (!m_isValid)
return;
+ // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations,
+ // and to avoid changing more than just the port.
+
bool colonNeeded = m_portEnd == m_hostEnd;
int portStart = (colonNeeded ? m_hostEnd : m_hostEnd + 1);
@@ -652,6 +691,9 @@ void KURL::setHostAndPort(const String& hostAndPort)
if (!m_isValid)
return;
+ // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations,
+ // and to avoid changing more than just host and port.
+
bool slashSlashNeeded = m_userStart == m_schemeEnd + 1;
parse(m_string.left(hostStart()) + (slashSlashNeeded ? "//" : "") + hostAndPort + m_string.substring(m_portEnd));
@@ -662,6 +704,8 @@ void KURL::setUser(const String& user)
if (!m_isValid)
return;
+ // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations,
+ // and to avoid changing more than just the user login.
String u;
int end = m_userEnd;
if (!user.isEmpty()) {
@@ -684,6 +728,8 @@ void KURL::setPass(const String& password)
if (!m_isValid)
return;
+ // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations,
+ // and to avoid changing more than just the user password.
String p;
int end = m_passwordEnd;
if (!password.isEmpty()) {
@@ -705,6 +751,8 @@ void KURL::setRef(const String& s)
{
if (!m_isValid)
return;
+
+ // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations.
parse(m_string.left(m_queryEnd) + (s.isNull() ? "" : "#" + s));
}
@@ -720,6 +768,9 @@ void KURL::setQuery(const String& query)
if (!m_isValid)
return;
+ // FIXME: '#' and non-ASCII characters must be encoded and escaped.
+ // Usually, the query is encoded using document encoding, not UTF-8, but we don't have
+ // access to the document in this function.
if ((query.isEmpty() || query[0] != '?') && !query.isNull())
parse(m_string.left(m_pathEnd) + "?" + query + m_string.substring(m_queryEnd));
else
@@ -732,6 +783,8 @@ void KURL::setPath(const String& s)
if (!m_isValid)
return;
+ // FIXME: encodeWithURLEscapeSequences does not correctly escape '#' and '?', so fragment and query parts
+ // may be inadvertently affected.
parse(m_string.left(m_portEnd) + encodeWithURLEscapeSequences(s) + m_string.substring(m_pathEnd));
}
@@ -943,8 +996,11 @@ static inline bool matchLetter(char c, char lowercaseLetter)
void KURL::parse(const String& string)
{
- CharBuffer buffer;
- encodeRelativeString(string, UTF8Encoding(), buffer);
+ checkEncodedString(string);
+
+ CharBuffer buffer(string.length() + 1);
+ copyASCII(string.characters(), string.length(), buffer.data());
+ buffer[string.length()] = '\0';
parse(buffer.data(), &string);
}
@@ -1480,7 +1536,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")) {
+ if (encoding != pathEncoding && encoding.isValid() && !protocolIs(rel, "mailto") && !protocolIs(rel, "data") && !protocolIs(rel, "javascript")) {
// Find the first instance of either # or ?, keep pathEnd at -1 otherwise.
pathEnd = findFirstOf(s.data(), s.size(), 0, "#?");
}
@@ -1563,7 +1619,7 @@ String mimeTypeFromDataURL(const String& url)
const KURL& blankURL()
{
- static KURL staticBlankURL("about:blank");
+ DEFINE_STATIC_LOCAL(KURL, staticBlankURL, ("about:blank"));
return staticBlankURL;
}
@@ -1575,3 +1631,5 @@ void KURL::print() const
#endif
}
+
+#endif // !USE(GOOGLEURL)
diff --git a/WebCore/platform/KURL.h b/WebCore/platform/KURL.h
index f31c641..7f6b102 100644
--- a/WebCore/platform/KURL.h
+++ b/WebCore/platform/KURL.h
@@ -46,6 +46,10 @@ class QUrl;
QT_END_NAMESPACE
#endif
+#if USE(GOOGLEURL)
+#include "GoogleURLPrivate.h"
+#endif
+
namespace WebCore {
class TextEncoding;
@@ -62,19 +66,8 @@ public:
KURL() { invalidate(); }
// The argument is an absolute URL string. The string is assumed to be
- // already encoded.
- // FIXME: This constructor has a special case for strings that start with
- // "/", prepending "file://" to such strings; it would be good to get
- // rid of that special case.
+ // an already encoded (ASCII-only) valid absolute URL.
explicit KURL(const char*);
-
- // The argument is an absolute URL string. The string is assumed to be
- // already encoded.
- // FIXME: For characters with codes other than 0000-00FF will be chopped
- // off, so this call is currently not safe to use with arbitrary strings.
- // FIXME: This constructor has a special case for strings that start with
- // "/", prepending "file://" to such strings; it would be good to get
- // rid of that special case.
explicit KURL(const String&);
// Resolves the relative URL with the given base URL. If provided, the
@@ -87,21 +80,37 @@ public:
KURL(const KURL& base, const String& relative);
KURL(const KURL& base, const String& relative, const TextEncoding&);
+#if USE(GOOGLEURL)
+ // For conversions for other structures that have already parsed and
+ // canonicalized the URL. The input must be exactly what KURL would have
+ // done with the same input.
+ KURL(const char* canonicalSpec, int canonicalSpecLen,
+ const url_parse::Parsed& parsed, bool isValid);
+#endif
+
// FIXME: The above functions should be harmonized so that passing a
// base of null or the empty string gives the same result as the
// standard String constructor.
- bool isNull() const { return m_string.isNull(); }
- bool isEmpty() const { return m_string.isEmpty(); }
+ // Makes a deep copy. Helpful only if you need to use a KURL on another
+ // thread. Since the underlying StringImpl objects are immutable, there's
+ // no other reason to ever prefer copy() over plain old assignment.
+ KURL copy() const;
- bool isValid() const { return m_isValid; }
+ bool isNull() const;
+ bool isEmpty() const;
+ bool isValid() const;
// Returns true if this URL has a path. Note that "http://foo.com/" has a
// path of "/", so this function will return true. Only invalid or
// non-hierarchical (like "javascript:") URLs will have no path.
bool hasPath() const;
+#if USE(GOOGLEURL)
+ const String& string() const { return m_url.string(); }
+#else
const String& string() const { return m_string; }
+#endif
String protocol() const;
String host() const;
@@ -145,20 +154,21 @@ public:
void setRef(const String&);
void removeRef();
-
+
friend bool equalIgnoringRef(const KURL&, const KURL&);
friend bool protocolHostAndPortAreEqual(const KURL&, const KURL&);
-
- operator const String&() const { return m_string; }
- operator JSC::UString() const { return m_string; }
- unsigned hostStart() const { return (m_passwordEnd == m_userStart) ? m_passwordEnd : m_passwordEnd + 1; }
- unsigned hostEnd() const { return m_hostEnd; }
-
- unsigned pathStart() const { return m_portEnd; }
- unsigned pathEnd() const { return m_pathEnd; }
- unsigned pathAfterLastSlash() const { return m_pathAfterLastSlash; }
+ unsigned hostStart() const;
+ unsigned hostEnd() const;
+
+ unsigned pathStart() const;
+ unsigned pathEnd() const;
+ unsigned pathAfterLastSlash() const;
+ operator const String&() const { return string(); }
+#if USE(JSC)
+ operator JSC::UString() const { return string(); }
+#endif
#if PLATFORM(CF)
KURL(CFURLRef);
@@ -170,7 +180,7 @@ public:
operator NSURL*() const;
#endif
#ifdef __OBJC__
- operator NSString*() const { return m_string; }
+ operator NSString*() const { return string(); }
#endif
#if PLATFORM(QT)
@@ -178,6 +188,12 @@ public:
operator QUrl() const;
#endif
+#if USE(GOOGLEURL)
+ // Getters for the parsed structure and its corresponding 8-bit string.
+ const url_parse::Parsed& parsed() const { return m_url.m_parsed; }
+ const CString& utf8String() const { return m_url.utf8String(); }
+#endif
+
#ifndef NDEBUG
void print() const;
#endif
@@ -185,10 +201,16 @@ public:
private:
void invalidate();
bool isHierarchical() const;
- void init(const KURL&, const String&, const TextEncoding&);
static bool protocolIs(const String&, const char*);
+#if USE(GOOGLEURL)
+ friend class GoogleURLPrivate;
+ void parse(const char* url, const String* originalString); // KURLMac calls this.
+ void copyToBuffer(Vector<char, 512>& buffer) const; // KURLCFNet uses this.
+ GoogleURLPrivate m_url;
+#else // !USE(GOOGLEURL)
+ void init(const KURL&, const String&, const TextEncoding&);
void copyToBuffer(Vector<char, 512>& buffer) const;
-
+
// Parses the given URL. The originalString parameter allows for an
// optimization: When the source is the same as the fixed-up string,
// it will use the passed-in string instead of allocating a new one.
@@ -207,6 +229,7 @@ private:
int m_pathEnd;
int m_queryEnd;
int m_fragmentEnd;
+#endif
};
bool operator==(const KURL&, const KURL&);
@@ -268,6 +291,53 @@ inline bool operator!=(const String& a, const KURL& b)
return a != b.string();
}
+#if !USE(GOOGLEURL)
+
+// Inline versions of some non-GoogleURL functions so we can get inlining
+// without having to have a lot of ugly ifdefs in the class definition.
+
+inline bool KURL::isNull() const
+{
+ return m_string.isNull();
+}
+
+inline bool KURL::isEmpty() const
+{
+ return m_string.isEmpty();
+}
+
+inline bool KURL::isValid() const
+{
+ return m_isValid;
+}
+
+inline unsigned KURL::hostStart() const
+{
+ return (m_passwordEnd == m_userStart) ? m_passwordEnd : m_passwordEnd + 1;
+}
+
+inline unsigned KURL::hostEnd() const
+{
+ return m_hostEnd;
+}
+
+inline unsigned KURL::pathStart() const
+{
+ return m_portEnd;
+}
+
+inline unsigned KURL::pathEnd() const
+{
+ return m_pathEnd;
+}
+
+inline unsigned KURL::pathAfterLastSlash() const
+{
+ return m_pathAfterLastSlash;
+}
+
+#endif // !USE(GOOGLEURL)
+
} // namespace WebCore
namespace WTF {
diff --git a/WebCore/platform/LinkHash.cpp b/WebCore/platform/LinkHash.cpp
new file mode 100644
index 0000000..793a65d
--- /dev/null
+++ b/WebCore/platform/LinkHash.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2001 Dirk Mueller (mueller@kde.org)
+ * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "AtomicString.h"
+#include "KURL.h"
+#include "LinkHash.h"
+#include "PlatformString.h"
+#include "StringHash.h"
+#include "StringImpl.h"
+
+namespace WebCore {
+
+static inline int findSlashDotDotSlash(const UChar* characters, size_t length)
+{
+ if (length < 4)
+ return -1;
+ unsigned loopLimit = length - 3;
+ for (unsigned i = 0; i < loopLimit; ++i) {
+ if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '.' && characters[i + 3] == '/')
+ return i;
+ }
+ return -1;
+}
+
+static inline int findSlashSlash(const UChar* characters, size_t length, int position)
+{
+ if (length < 2)
+ return -1;
+ unsigned loopLimit = length - 1;
+ for (unsigned i = position; i < loopLimit; ++i) {
+ if (characters[i] == '/' && characters[i + 1] == '/')
+ return i;
+ }
+ return -1;
+}
+
+static inline int findSlashDotSlash(const UChar* characters, size_t length)
+{
+ if (length < 3)
+ return -1;
+ unsigned loopLimit = length - 2;
+ for (unsigned i = 0; i < loopLimit; ++i) {
+ if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '/')
+ return i;
+ }
+ return -1;
+}
+
+static inline bool containsColonSlashSlash(const UChar* characters, unsigned length)
+{
+ if (length < 3)
+ return false;
+ unsigned loopLimit = length - 2;
+ for (unsigned i = 0; i < loopLimit; ++i) {
+ if (characters[i] == ':' && characters[i + 1] == '/' && characters[i + 2] == '/')
+ return true;
+ }
+ return false;
+}
+
+static inline void cleanPath(Vector<UChar, 512>& path)
+{
+ // FIXME: Shold not do this in the query or anchor part.
+ int pos;
+ while ((pos = findSlashDotDotSlash(path.data(), path.size())) != -1) {
+ int prev = reverseFind(path.data(), path.size(), '/', pos - 1);
+ // don't remove the host, i.e. http://foo.org/../foo.html
+ if (prev < 0 || (prev > 3 && path[prev - 2] == ':' && path[prev - 1] == '/'))
+ path.remove(pos, 3);
+ else
+ path.remove(prev, pos - prev + 3);
+ }
+
+ // FIXME: Shold not do this in the query part.
+ // Set refPos to -2 to mean "I haven't looked for the anchor yet".
+ // We don't want to waste a function call on the search for the the anchor
+ // in the vast majority of cases where there is no "//" in the path.
+ pos = 0;
+ int refPos = -2;
+ while ((pos = findSlashSlash(path.data(), path.size(), pos)) != -1) {
+ if (refPos == -2)
+ refPos = find(path.data(), path.size(), '#');
+ if (refPos > 0 && pos >= refPos)
+ break;
+
+ if (pos == 0 || path[pos - 1] != ':')
+ path.remove(pos);
+ else
+ pos += 2;
+ }
+
+ // FIXME: Shold not do this in the query or anchor part.
+ while ((pos = findSlashDotSlash(path.data(), path.size())) != -1)
+ path.remove(pos, 2);
+}
+
+
+static inline bool matchLetter(UChar c, UChar lowercaseLetter)
+{
+ return (c | 0x20) == lowercaseLetter;
+}
+
+static inline bool needsTrailingSlash(const UChar* characters, unsigned length)
+{
+ if (length < 6)
+ return false;
+ if (!matchLetter(characters[0], 'h')
+ || !matchLetter(characters[1], 't')
+ || !matchLetter(characters[2], 't')
+ || !matchLetter(characters[3], 'p'))
+ return false;
+ if (!(characters[4] == ':'
+ || (matchLetter(characters[4], 's') && characters[5] == ':')))
+ return false;
+
+ unsigned pos = characters[4] == ':' ? 5 : 6;
+
+ // Skip initial two slashes if present.
+ if (pos + 1 < length && characters[pos] == '/' && characters[pos + 1] == '/')
+ pos += 2;
+
+ // Find next slash.
+ while (pos < length && characters[pos] != '/')
+ ++pos;
+
+ return pos == length;
+}
+
+LinkHash visitedLinkHash(const UChar* url, unsigned length)
+{
+ return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(url, length));
+}
+
+LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL)
+{
+ const UChar* characters = attributeURL.characters();
+ unsigned length = attributeURL.length();
+ if (!length)
+ return 0;
+
+ // 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.
+ // For example, it does not handle international domain names properly.
+
+ // FIXME: It is wrong that we do not do further processing on strings that have "://" in them:
+ // 1) The "://" could be in the query or anchor.
+ // 2) The URL's path could have a "/./" or a "/../" or a "//" sequence in it.
+
+ // FIXME: needsTrailingSlash does not properly return true for a URL that has no path, but does
+ // have a query or anchor.
+
+ bool hasColonSlashSlash = containsColonSlashSlash(characters, length);
+
+ if (hasColonSlashSlash && !needsTrailingSlash(characters, length))
+ return visitedLinkHash(attributeURL.characters(), attributeURL.length());
+
+ 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());
+ }
+
+ switch (characters[0]) {
+ case '/':
+ buffer.append(base.string().characters(), base.pathStart());
+ break;
+ case '#':
+ buffer.append(base.string().characters(), base.pathEnd());
+ break;
+ default:
+ buffer.append(base.string().characters(), base.pathAfterLastSlash());
+ break;
+ }
+ buffer.append(characters, length);
+ cleanPath(buffer);
+ if (needsTrailingSlash(buffer.data(), buffer.size())) {
+ // 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('/');
+ }
+
+ return visitedLinkHash(buffer.data(), buffer.size());
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/LinkHash.h b/WebCore/platform/LinkHash.h
new file mode 100644
index 0000000..1ec1e16
--- /dev/null
+++ b/WebCore/platform/LinkHash.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 LinkHash_h
+#define LinkHash_h
+
+#include "StringHash.h"
+
+namespace WebCore {
+
+class AtomicString;
+class KURL;
+
+typedef uint64_t LinkHash;
+
+// Use the low 32-bits of the 64-bit LinkHash as the key for HashSets.
+struct LinkHashHash {
+ static unsigned hash(LinkHash key) { return static_cast<unsigned>(key); }
+ static bool equal(LinkHash a, LinkHash b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+
+ // See AlreadyHashed::avoidDeletedValue.
+ static unsigned avoidDeletedValue(LinkHash hash64)
+ {
+ ASSERT(hash64);
+ unsigned hash = static_cast<unsigned>(hash64);
+ unsigned newHash = hash | (!(hash + 1) << 31);
+ ASSERT(newHash);
+ ASSERT(newHash != 0xFFFFFFFF);
+ return newHash;
+ }
+};
+
+// Returns the has of the string that will be used for visited link coloring.
+LinkHash visitedLinkHash(const UChar* url, unsigned length);
+
+// 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
+// link coloring. It will return the special value of 0 if attributeURL does not
+// look like a relative URL.
+LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL);
+
+} // namespace WebCore
+
+#endif // LinkHash_h
diff --git a/WebCore/platform/LocalizedStrings.h b/WebCore/platform/LocalizedStrings.h
index 9b11a92..085c6e1 100644
--- a/WebCore/platform/LocalizedStrings.h
+++ b/WebCore/platform/LocalizedStrings.h
@@ -76,6 +76,7 @@ namespace WebCore {
String contextMenuItemTagUnderline();
String contextMenuItemTagOutline();
String contextMenuItemTagWritingDirectionMenu();
+ String contextMenuItemTagTextDirectionMenu();
String contextMenuItemTagDefaultDirection();
String contextMenuItemTagLeftToRight();
String contextMenuItemTagRightToLeft();
diff --git a/WebCore/platform/MIMETypeRegistry.cpp b/WebCore/platform/MIMETypeRegistry.cpp
index 70d953a..14becb5 100644
--- a/WebCore/platform/MIMETypeRegistry.cpp
+++ b/WebCore/platform/MIMETypeRegistry.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 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
@@ -35,6 +36,7 @@
#include <wtf/HashSet.h>
#if PLATFORM(CG)
+#include "ImageSourceCG.h"
#include <ApplicationServices/ApplicationServices.h>
#include <wtf/RetainPtr.h>
#endif
@@ -52,10 +54,6 @@ static HashSet<String>* supportedJavaScriptMIMETypes;
static HashSet<String>* supportedNonImageMIMETypes;
static HashSet<String>* supportedMediaMIMETypes;
-#if PLATFORM(CG)
-extern String getMIMETypeForUTI(const String& uti);
-#endif
-
static void initializeSupportedImageMIMETypes()
{
#if PLATFORM(CG)
@@ -63,7 +61,7 @@ static void initializeSupportedImageMIMETypes()
CFIndex count = CFArrayGetCount(supportedTypes.get());
for (CFIndex i = 0; i < count; i++) {
RetainPtr<CFStringRef> supportedType(AdoptCF, reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i)));
- String mimeType = getMIMETypeForUTI(supportedType.get());
+ String mimeType = MIMETypeForImageSourceType(supportedType.get());
if (!mimeType.isEmpty()) {
supportedImageMIMETypes->add(mimeType);
supportedImageResourceMIMETypes->add(mimeType);
@@ -154,7 +152,7 @@ static void initializeSupportedImageMIMETypesForEncoding()
CFIndex count = CFArrayGetCount(supportedTypes.get());
for (CFIndex i = 0; i < count; i++) {
RetainPtr<CFStringRef> supportedType(AdoptCF, reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i)));
- String mimeType = getMIMETypeForUTI(supportedType.get());
+ String mimeType = MIMETypeForImageSourceType(supportedType.get());
if (!mimeType.isEmpty())
supportedImageMIMETypesForEncoding->add(mimeType);
}
@@ -205,6 +203,10 @@ static void initializeSupportedJavaScriptMIMETypes()
static void initializeSupportedNonImageMimeTypes()
{
static const char* types[] = {
+#if ENABLE(WML)
+ "text/vnd.wap.wml",
+ "application/vnd.wap.wmlc",
+#endif
"text/html",
"text/xml",
"text/xsl",
diff --git a/WebCore/platform/NotImplemented.h b/WebCore/platform/NotImplemented.h
index 862f111..03ab424 100644
--- a/WebCore/platform/NotImplemented.h
+++ b/WebCore/platform/NotImplemented.h
@@ -58,7 +58,7 @@
#define notImplemented() do { \
static bool havePrinted = false; \
if (!havePrinted && !supressNotImplementedWarning()) { \
- WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &LogNotYetImplemented, "UNIMPLEMENTED: "); \
+ WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &::WebCore::LogNotYetImplemented, "UNIMPLEMENTED: "); \
havePrinted = true; \
} \
} while (0)
diff --git a/WebCore/platform/PurgeableBuffer.h b/WebCore/platform/PurgeableBuffer.h
new file mode 100644
index 0000000..bee21b9
--- /dev/null
+++ b/WebCore/platform/PurgeableBuffer.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PurgeableBuffer_h
+#define PurgeableBuffer_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+ class PurgeableBuffer : Noncopyable {
+ public:
+ static PurgeableBuffer* create(const char* data, size_t);
+ static PurgeableBuffer* create(const Vector<char>& v) { return create(v.data(), v.size()); }
+
+ ~PurgeableBuffer();
+
+ // Call makePurgeable(false) and check the return value before accessing the data.
+ const char* data() const;
+ size_t size() const { return m_size; }
+
+ enum PurgePriority { PurgeLast, PurgeMiddle, PurgeFirst, PurgeDefault = PurgeMiddle };
+ PurgePriority purgePriority() const { return m_purgePriority; }
+ void setPurgePriority(PurgePriority);
+
+ bool isPurgeable() const { return m_state != NonVolatile; }
+ bool wasPurged() const;
+
+ bool makePurgeable(bool purgeable);
+
+ private:
+ PurgeableBuffer(char* data, size_t);
+
+ char* m_data;
+ size_t m_size;
+ PurgePriority m_purgePriority;
+
+ enum State { NonVolatile, Volatile, Purged };
+ mutable State m_state;
+ };
+
+#if !PLATFORM(DARWIN) || defined(BUILDING_ON_TIGER) || PLATFORM(QT)
+ inline PurgeableBuffer* PurgeableBuffer::create(const char*, size_t) { return 0; }
+ inline PurgeableBuffer::~PurgeableBuffer() { }
+ inline const char* PurgeableBuffer::data() const { return 0; }
+ inline void PurgeableBuffer::setPurgePriority(PurgePriority) { }
+ inline bool PurgeableBuffer::wasPurged() const { return false; }
+ inline bool PurgeableBuffer::makePurgeable(bool) { return false; }
+#endif
+
+}
+
+#endif
diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp
index 9eb6ce7..573dabe 100644
--- a/WebCore/platform/ScrollView.cpp
+++ b/WebCore/platform/ScrollView.cpp
@@ -33,6 +33,7 @@
#include "PlatformWheelEvent.h"
#include "Scrollbar.h"
#include "ScrollbarTheme.h"
+#include <wtf/StdLibExtras.h>
using std::max;
@@ -47,10 +48,9 @@ ScrollView::ScrollView()
, m_scrollbarsSuppressed(false)
, m_inUpdateScrollbars(false)
, m_drawPanScrollIcon(false)
+ , m_useFixedLayout(false)
{
platformInit();
- if (platformWidget())
- platformSetCanBlitOnScroll();
}
ScrollView::~ScrollView()
@@ -79,7 +79,7 @@ void ScrollView::removeChild(Widget* child)
void ScrollView::setHasHorizontalScrollbar(bool hasBar)
{
if (hasBar && !m_horizontalScrollbar && !platformHasHorizontalAdjustment()) {
- m_horizontalScrollbar = Scrollbar::createNativeScrollbar(this, HorizontalScrollbar, RegularScrollbar);
+ m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
addChild(m_horizontalScrollbar.get());
} else if (!hasBar && m_horizontalScrollbar) {
removeChild(m_horizontalScrollbar.get());
@@ -90,7 +90,7 @@ void ScrollView::setHasHorizontalScrollbar(bool hasBar)
void ScrollView::setHasVerticalScrollbar(bool hasBar)
{
if (hasBar && !m_verticalScrollbar && !platformHasVerticalAdjustment()) {
- m_verticalScrollbar = Scrollbar::createNativeScrollbar(this, VerticalScrollbar, RegularScrollbar);
+ m_verticalScrollbar = createScrollbar(VerticalScrollbar);
addChild(m_verticalScrollbar.get());
} else if (!hasBar && m_verticalScrollbar) {
removeChild(m_verticalScrollbar.get());
@@ -98,6 +98,11 @@ void ScrollView::setHasVerticalScrollbar(bool hasBar)
}
}
+PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation)
+{
+ return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
+}
+
void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode)
{
if (horizontalMode == horizontalScrollbarMode() && verticalMode == verticalScrollbarMode())
@@ -142,11 +147,20 @@ void ScrollView::setCanHaveScrollbars(bool canScroll)
void ScrollView::setCanBlitOnScroll(bool b)
{
- if (m_canBlitOnScroll == b)
+ if (platformWidget()) {
+ platformSetCanBlitOnScroll(b);
return;
+ }
+
m_canBlitOnScroll = b;
+}
+
+bool ScrollView::canBlitOnScroll() const
+{
if (platformWidget())
- platformSetCanBlitOnScroll();
+ return platformCanBlitOnScroll();
+
+ return m_canBlitOnScroll;
}
IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
@@ -158,6 +172,42 @@ IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
max(0, height() - (horizontalScrollbar() && !includeScrollbars ? horizontalScrollbar()->height() : 0))));
}
+int ScrollView::layoutWidth() const
+{
+ return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleWidth() : m_fixedLayoutSize.width();
+}
+
+int ScrollView::layoutHeight() const
+{
+ return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleHeight() : m_fixedLayoutSize.height();
+}
+
+IntSize ScrollView::fixedLayoutSize() const
+{
+ return m_fixedLayoutSize;
+}
+
+void ScrollView::setFixedLayoutSize(const IntSize& newSize)
+{
+ if (fixedLayoutSize() == newSize)
+ return;
+ m_fixedLayoutSize = newSize;
+ updateScrollbars(scrollOffset());
+}
+
+bool ScrollView::useFixedLayout() const
+{
+ return m_useFixedLayout;
+}
+
+void ScrollView::setUseFixedLayout(bool enable)
+{
+ if (useFixedLayout() == enable)
+ return;
+ m_useFixedLayout = enable;
+ updateScrollbars(scrollOffset());
+}
+
IntSize ScrollView::contentsSize() const
{
if (platformWidget())
@@ -211,16 +261,27 @@ void ScrollView::scrollRectIntoViewRecursively(const IntRect& r)
if (platformProhibitsScrolling())
return;
#endif
- if (prohibitsScrolling())
- return;
-
- IntPoint p(max(0, r.x()), max(0, r.y()));
+ // FIXME: This method is not transform-aware. It should just be moved to FrameView so that an accurate
+ // position for the child view can be determined.
+ IntRect rect = r;
ScrollView* view = this;
while (view) {
- view->setScrollPosition(p);
- p.move(view->x() - view->scrollOffset().width(), view->y() - view->scrollOffset().height());
+ if (view->prohibitsScrolling()) // Allow the views to scroll into view recursively until we hit one that prohibits scrolling.
+ return;
+ view->setScrollPosition(rect.location());
+ rect.move(view->x() - view->scrollOffset().width(), view->y() - view->scrollOffset().height());
+ if (view->parent())
+ rect.intersect(view->frameRect());
view = view->parent();
}
+
+ // We may be embedded inside some containing platform scroll view that we don't manage. This is the case
+ // in Mail.app on OS X, for example, where the WebKit view for message bodies is inside a Cocoa NSScrollView
+ // that contains both it and message headers. Let the HostWindow know about this scroll so that it can pass the message
+ // on up the view chain.
+ // This rect is not clamped, since Mail actually relies on receiving an unclamped rect with negative coordinates in order to
+ // expose the headers.
+ hostWindow()->scrollRectIntoView(rect, this);
}
void ScrollView::setScrollPosition(const IntPoint& scrollPoint)
@@ -395,7 +456,7 @@ void ScrollView::scrollContents(const IntSize& scrollDelta)
IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2));
IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation , IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength));
panScrollIconDirtyRect.intersect(clipRect);
- hostWindow()->repaint(panScrollIconDirtyRect, true, true);
+ hostWindow()->repaint(panScrollIconDirtyRect, true);
}
if (canBlitOnScroll() && !rootPreventsBlitting()) { // The main frame can just blit the WebView window
@@ -588,7 +649,7 @@ void ScrollView::setFrameRect(const IntRect& newRect)
frameRectsChanged();
}
-void ScrollView::frameRectsChanged() const
+void ScrollView::frameRectsChanged()
{
if (platformWidget())
return;
@@ -673,10 +734,8 @@ void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
}
// Paint the panScroll Icon
- static RefPtr<Image> panScrollIcon;
if (m_drawPanScrollIcon) {
- if (!panScrollIcon)
- panScrollIcon = Image::loadPlatformResource("panIcon");
+ DEFINE_STATIC_LOCAL(RefPtr<Image>, panScrollIcon, (Image::loadPlatformResource("panIcon")));
context->drawImage(panScrollIcon.get(), m_panScrollIconPoint);
}
}
@@ -694,7 +753,7 @@ void ScrollView::setParentVisible(bool visible)
Widget::setParentVisible(visible);
- if (!isVisible())
+ if (!isSelfVisible())
return;
HashSet<Widget*>::iterator end = m_children.end();
@@ -778,10 +837,6 @@ void ScrollView::platformRemoveChild(Widget*)
#endif
#if !PLATFORM(MAC)
-void ScrollView::platformSetCanBlitOnScroll()
-{
-}
-
void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress)
{
}
@@ -796,12 +851,25 @@ void ScrollView::platformSetScrollbarModes()
void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const
{
}
+#endif
+
+void ScrollView::platformSetCanBlitOnScroll(bool)
+{
+}
+
+bool ScrollView::platformCanBlitOnScroll() const
+{
+ return false;
+}
+#if !PLATFORM(ANDROID)
IntRect ScrollView::platformVisibleContentRect(bool) const
{
return IntRect();
}
+#endif
+#if !PLATFORM(ANDROID)
IntSize ScrollView::platformContentsSize() const
{
return IntSize();
diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h
index acd3f85..f7bfbe8 100644
--- a/WebCore/platform/ScrollView.h
+++ b/WebCore/platform/ScrollView.h
@@ -95,6 +95,9 @@ public:
virtual void setCanHaveScrollbars(bool flag);
bool canHaveScrollbars() const { return horizontalScrollbarMode() != ScrollbarAlwaysOff || verticalScrollbarMode() != ScrollbarAlwaysOff; }
+ // Overridden by FrameView to create custom CSS scrollbars if applicable.
+ virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
+
// If the prohibits scrolling flag is set, then all scrolling in the view (even programmatic scrolling) is turned off.
void setProhibitsScrolling(bool b) { m_prohibitsScrolling = b; }
bool prohibitsScrolling() const { return m_prohibitsScrolling; }
@@ -102,7 +105,7 @@ public:
// Whether or not a scroll view will blit visible contents when it is scrolled. Blitting is disabled in situations
// where it would cause rendering glitches (such as with fixed backgrounds or when the view is partially transparent).
void setCanBlitOnScroll(bool);
- bool canBlitOnScroll() const { return m_canBlitOnScroll; }
+ bool canBlitOnScroll() const;
// The visible content rect has a location that is the scrolled offset of the document. The width and height are the viewport width
// and height. By default the scrollbars themselves are excluded from this rectangle, but an optional boolean argument allows them to be
@@ -110,13 +113,22 @@ public:
IntRect visibleContentRect(bool includeScrollbars = false) const;
int visibleWidth() const { return visibleContentRect().width(); }
int visibleHeight() const { return visibleContentRect().height(); }
+
+ // Methods for getting/setting the size webkit should use to layout the contents. By default this is the same as the visible
+ // content size. Explicitly setting a layout size value will cause webkit to layout the contents using this size instead.
+ int layoutWidth() const;
+ int layoutHeight() const;
+ IntSize fixedLayoutSize() const;
+ void setFixedLayoutSize(const IntSize&);
+ bool useFixedLayout() const;
+ void setUseFixedLayout(bool enable);
// 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;
int contentsWidth() const { return contentsSize().width(); }
int contentsHeight() const { return contentsSize().height(); }
- void setContentsSize(const IntSize&);
+ virtual void setContentsSize(const IntSize&);
// Methods for querying the current scrolled position (both as a point, a size, or as individual X and Y values).
IntPoint scrollPosition() const { return visibleContentRect().location(); }
@@ -165,7 +177,7 @@ public:
virtual void setParent(ScrollView*); // Overridden to update the overlapping scrollbar count.
// Called when our frame rect changes (or the rect/scroll position of an ancestor changes).
- virtual void frameRectsChanged() const;
+ virtual void frameRectsChanged();
// Widget override to update our scrollbars and notify our contents of the resize.
virtual void setFrameRect(const IntRect&);
@@ -229,8 +241,13 @@ private:
bool m_prohibitsScrolling;
HashSet<Widget*> m_children;
+
+ // This bool is unused on Mac OS because we directly ask the platform widget
+ // whether it is safe to blit on scroll.
bool m_canBlitOnScroll;
+
IntSize m_scrollOffset; // FIXME: Would rather store this as a position, but we will wait to make this change until more code is shared.
+ IntSize m_fixedLayoutSize;
IntSize m_contentsSize;
int m_scrollbarsAvoidingResizer;
@@ -240,6 +257,7 @@ private:
IntPoint m_panScrollIconPoint;
bool m_drawPanScrollIcon;
+ bool m_useFixedLayout;
void init();
void destroy();
@@ -253,7 +271,8 @@ private:
void platformRemoveChild(Widget*);
void platformSetScrollbarModes();
void platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const;
- void platformSetCanBlitOnScroll();
+ void platformSetCanBlitOnScroll(bool);
+ bool platformCanBlitOnScroll() const;
IntRect platformVisibleContentRect(bool includeScrollbars) const;
IntSize platformContentsSize() const;
void platformSetContentsSize();
diff --git a/WebCore/platform/Scrollbar.cpp b/WebCore/platform/Scrollbar.cpp
index 0c7d854..13bb0c9 100644
--- a/WebCore/platform/Scrollbar.cpp
+++ b/WebCore/platform/Scrollbar.cpp
@@ -364,14 +364,14 @@ bool Scrollbar::mouseDown(const PlatformMouseEvent& evt)
setPressedPart(theme()->hitTest(this, evt));
int pressedPos = (orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.pos()).x() : convertFromContainingWindow(evt.pos()).y());
- if (theme()->shouldCenterOnThumb(this, evt)) {
+ if ((pressedPart() == BackTrackPart || pressedPart() == ForwardTrackPart) && theme()->shouldCenterOnThumb(this, evt)) {
setHoveredPart(ThumbPart);
setPressedPart(ThumbPart);
int thumbLen = theme()->thumbLength(this);
- int desiredPos = pressedPos - thumbLen / 2;
- // Set the pressed position to the top of the thumb so that when we do the move, the delta
+ int desiredPos = pressedPos;
+ // Set the pressed position to the middle of the thumb so that when we do the move, the delta
// will be from the current pixel position of the thumb to the new desired position for the thumb.
- m_pressedPos = theme()->trackPosition(this) + theme()->thumbPosition(this);
+ m_pressedPos = theme()->trackPosition(this) + theme()->thumbPosition(this) + thumbLen / 2;
moveThumb(desiredPos);
return true;
}
@@ -433,14 +433,15 @@ void Scrollbar::setEnabled(bool e)
bool Scrollbar::isWindowActive() const
{
- return m_client->isActive();
+ return m_client && m_client->isActive();
}
void Scrollbar::invalidateRect(const IntRect& rect)
{
if (suppressInvalidation())
return;
- m_client->invalidateScrollbarRect(this, rect);
+ if (m_client)
+ m_client->invalidateScrollbarRect(this, rect);
}
PlatformMouseEvent Scrollbar::transformEvent(const PlatformMouseEvent& event)
diff --git a/WebCore/platform/ScrollbarClient.h b/WebCore/platform/ScrollbarClient.h
index ea35758..f720e95 100644
--- a/WebCore/platform/ScrollbarClient.h
+++ b/WebCore/platform/ScrollbarClient.h
@@ -27,6 +27,7 @@
#define ScrollbarClient_h
#include "IntRect.h"
+#include <wtf/Vector.h>
namespace WebCore {
@@ -42,6 +43,8 @@ public:
virtual bool isActive() const = 0;
virtual bool scrollbarCornerPresent() const = 0;
+
+ virtual void getTickmarks(Vector<IntRect>&) const { }
};
}
diff --git a/WebCore/platform/ScrollbarTheme.h b/WebCore/platform/ScrollbarTheme.h
index 1fdb2b2..e2aebc6 100644
--- a/WebCore/platform/ScrollbarTheme.h
+++ b/WebCore/platform/ScrollbarTheme.h
@@ -40,7 +40,7 @@ class ScrollbarTheme {
public:
virtual ~ScrollbarTheme() {};
- virtual bool paint(Scrollbar*, GraphicsContext*, const IntRect& damageRect) { return false; }
+ virtual bool paint(Scrollbar*, GraphicsContext*, const IntRect& /*damageRect*/) { return false; }
virtual ScrollbarPart hitTest(Scrollbar*, const PlatformMouseEvent&) { return NoPart; }
virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar) { return 0; }
diff --git a/WebCore/platform/ScrollbarThemeComposite.cpp b/WebCore/platform/ScrollbarThemeComposite.cpp
index 4ea74fe..ab5e16b 100644
--- a/WebCore/platform/ScrollbarThemeComposite.cpp
+++ b/WebCore/platform/ScrollbarThemeComposite.cpp
@@ -145,6 +145,8 @@ bool ScrollbarThemeComposite::paint(Scrollbar* scrollbar, GraphicsContext* graph
paintTrackPiece(graphicsContext, scrollbar, startTrackRect, BackTrackPart);
if (scrollMask & ForwardTrackPart)
paintTrackPiece(graphicsContext, scrollbar, endTrackRect, ForwardTrackPart);
+
+ paintTickmarks(graphicsContext, scrollbar, trackPaintRect);
}
// Paint the thumb.
diff --git a/WebCore/platform/ScrollbarThemeComposite.h b/WebCore/platform/ScrollbarThemeComposite.h
index 7748251..d8c3fbb 100644
--- a/WebCore/platform/ScrollbarThemeComposite.h
+++ b/WebCore/platform/ScrollbarThemeComposite.h
@@ -62,7 +62,8 @@ 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 void paintTickmarks(GraphicsContext*, Scrollbar*, const IntRect&) {}
+
virtual IntRect constrainTrackRectToTrackPieces(Scrollbar*, const IntRect& rect) { return rect; }
};
diff --git a/WebCore/platform/SharedBuffer.cpp b/WebCore/platform/SharedBuffer.cpp
index e1e812b..4a0d0f3 100644
--- a/WebCore/platform/SharedBuffer.cpp
+++ b/WebCore/platform/SharedBuffer.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "SharedBuffer.h"
+#include "PurgeableBuffer.h"
+
namespace WebCore {
SharedBuffer::SharedBuffer()
@@ -41,6 +43,10 @@ SharedBuffer::SharedBuffer(const unsigned char* data, int size)
{
m_buffer.append(data, size);
}
+
+SharedBuffer::~SharedBuffer()
+{
+}
PassRefPtr<SharedBuffer> SharedBuffer::adoptVector(Vector<char>& vector)
{
@@ -49,11 +55,22 @@ PassRefPtr<SharedBuffer> SharedBuffer::adoptVector(Vector<char>& vector)
return buffer.release();
}
+PassRefPtr<SharedBuffer> SharedBuffer::adoptPurgeableBuffer(PurgeableBuffer* purgeableBuffer)
+{
+ ASSERT(!purgeableBuffer->isPurgeable());
+ RefPtr<SharedBuffer> buffer = create();
+ buffer->m_purgeableBuffer.set(purgeableBuffer);
+ return buffer.release();
+}
+
unsigned SharedBuffer::size() const
{
if (hasPlatformData())
return platformDataSize();
+ if (m_purgeableBuffer)
+ return m_purgeableBuffer->size();
+
return m_buffer.size();
}
@@ -62,11 +79,16 @@ const char* SharedBuffer::data() const
if (hasPlatformData())
return platformData();
+ if (m_purgeableBuffer)
+ return m_purgeableBuffer->data();
+
return m_buffer.data();
}
void SharedBuffer::append(const char* data, int len)
{
+ ASSERT(!m_purgeableBuffer);
+
maybeTransferPlatformData();
m_buffer.append(data, len);
@@ -77,6 +99,7 @@ void SharedBuffer::clear()
clearPlatformData();
m_buffer.clear();
+ m_purgeableBuffer.clear();
}
PassRefPtr<SharedBuffer> SharedBuffer::copy() const
@@ -84,6 +107,11 @@ PassRefPtr<SharedBuffer> SharedBuffer::copy() const
return SharedBuffer::create(data(), size());
}
+PurgeableBuffer* SharedBuffer::releasePurgeableBuffer()
+{
+ ASSERT(hasOneRef());
+ return m_purgeableBuffer.release();
+}
#if !PLATFORM(CF)
diff --git a/WebCore/platform/SharedBuffer.h b/WebCore/platform/SharedBuffer.h
index eb5c167..3675a3b 100644
--- a/WebCore/platform/SharedBuffer.h
+++ b/WebCore/platform/SharedBuffer.h
@@ -26,8 +26,9 @@
#define SharedBuffer_h
#include "PlatformString.h"
-#include <wtf/RefCounted.h>
#include <wtf/Forward.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefCounted.h>
#include <wtf/Vector.h>
#if PLATFORM(CF)
@@ -44,6 +45,8 @@ class NSData;
#endif
namespace WebCore {
+
+class PurgeableBuffer;
class SharedBuffer : public RefCounted<SharedBuffer> {
public:
@@ -55,6 +58,12 @@ public:
static PassRefPtr<SharedBuffer> adoptVector(Vector<char>& vector);
+ // The buffer must be in non-purgeable state before adopted to a SharedBuffer.
+ // It will stay that way until released.
+ static PassRefPtr<SharedBuffer> adoptPurgeableBuffer(PurgeableBuffer* buffer);
+
+ ~SharedBuffer();
+
#if PLATFORM(MAC)
NSData *createNSData();
static PassRefPtr<SharedBuffer> wrapNSData(NSData *data);
@@ -76,6 +85,11 @@ public:
PassRefPtr<SharedBuffer> copy() const;
+ bool hasPurgeableBuffer() const { return m_purgeableBuffer.get(); }
+
+ // Ensure this buffer has no other clients before calling this.
+ PurgeableBuffer* releasePurgeableBuffer();
+
private:
SharedBuffer();
SharedBuffer(const char*, int);
@@ -86,6 +100,7 @@ private:
bool hasPlatformData() const;
Vector<char> m_buffer;
+ OwnPtr<PurgeableBuffer> m_purgeableBuffer;
#if PLATFORM(CF)
SharedBuffer(CFDataRef);
RetainPtr<CFDataRef> m_cfData;
diff --git a/WebCore/platform/SystemTime.h b/WebCore/platform/SystemTime.h
index 327b2c7..2620b94 100644
--- a/WebCore/platform/SystemTime.h
+++ b/WebCore/platform/SystemTime.h
@@ -28,16 +28,9 @@
namespace WebCore {
- // Return the current system time in seconds, using the classic POSIX epoch of January 1, 1970.
- // Like time(0) from <time.h>, except with a wider range of values and higher precision.
- double currentTime();
-
// Return the number of seconds since a user event has been generated
float userIdleTime();
-#if PLATFORM(ANDROID)
- uint32_t get_thread_msec();
-#endif
}
#endif
diff --git a/WebCore/platform/Theme.cpp b/WebCore/platform/Theme.cpp
index 185c7ca..5cf4af9 100644
--- a/WebCore/platform/Theme.cpp
+++ b/WebCore/platform/Theme.cpp
@@ -28,7 +28,7 @@
namespace WebCore {
-LengthBox Theme::controlBorder(ControlPart part, const Font&, const LengthBox& zoomedBox, float zoomFactor) const
+LengthBox Theme::controlBorder(ControlPart part, const Font&, const LengthBox& zoomedBox, float) const
{
switch (part) {
case PushButtonPart:
@@ -42,7 +42,7 @@ LengthBox Theme::controlBorder(ControlPart part, const Font&, const LengthBox& z
}
}
-LengthBox Theme::controlPadding(ControlPart part, const Font&, const LengthBox& zoomedBox, float zoomFactor) const
+LengthBox Theme::controlPadding(ControlPart part, const Font&, const LengthBox& zoomedBox, float) const
{
switch (part) {
case MenulistPart:
diff --git a/WebCore/platform/Theme.h b/WebCore/platform/Theme.h
index 85c3f24..5574bd7 100644
--- a/WebCore/platform/Theme.h
+++ b/WebCore/platform/Theme.h
@@ -73,7 +73,7 @@ public:
virtual Font systemFont(ThemeFont, FontDescription&) const { return Font(); }
// How fast the caret blinks in text fields.
- virtual double caretBlinkFrequency() const { return 0.5; }
+ virtual double caretBlinkInterval() const { return 0.5; }
// Notification when the theme has changed
virtual void themeChanged() { }
@@ -81,13 +81,13 @@ public:
// Methods used to adjust the RenderStyles of controls.
// The font description result should have a zoomed font size.
- virtual FontDescription controlFont(ControlPart, const Font& font, float zoomFactor) const { return font.fontDescription(); }
+ virtual FontDescription controlFont(ControlPart, const Font& font, float /*zoomFactor*/) const { return font.fontDescription(); }
// The size here is in zoomed coordinates already. If a new size is returned, it also needs to be in zoomed coordinates.
- virtual LengthSize controlSize(ControlPart, const Font&, const LengthSize& zoomedSize, float zoomFactor) const { return zoomedSize; }
+ virtual LengthSize controlSize(ControlPart, const Font&, const LengthSize& zoomedSize, float /*zoomFactor*/) const { return zoomedSize; }
// Returns the minimum size for a control in zoomed coordinates.
- virtual LengthSize minimumControlSize(ControlPart, const Font&, float zoomFactor) const { return LengthSize(Length(0, Fixed), Length(0, Fixed)); }
+ virtual LengthSize minimumControlSize(ControlPart, const Font&, float /*zoomFactor*/) const { return LengthSize(Length(0, Fixed), Length(0, Fixed)); }
// Allows the theme to modify the existing padding/border.
virtual LengthBox controlPadding(ControlPart, const Font&, const LengthBox& zoomedBox, float zoomFactor) const;
@@ -96,14 +96,14 @@ public:
// Whether or not whitespace: pre should be forced on always.
virtual bool controlRequiresPreWhiteSpace(ControlPart) const { return false; }
- // Method for painting a control. The rect is in zoomed coordinates.
- virtual void paint(ControlPart, ControlStates, GraphicsContext*, const IntRect& zoomedRect, float zoomFactor, ScrollView*) const { };
+ // Method for painting a control. The rect is in zoomed coordinates.
+ virtual void paint(ControlPart, ControlStates, GraphicsContext*, const IntRect& /*zoomedRect*/, float /*zoomFactor*/, ScrollView*) const { }
// Some controls may spill out of their containers (e.g., the check on an OS X checkbox). When these controls repaint,
// the theme needs to communicate this inflated rect to the engine so that it can invalidate the whole control.
// The rect passed in is in zoomed coordinates, so the inflation should take that into account and make sure the inflation
// amount is also scaled by the zoomFactor.
- virtual void inflateControlPaintRect(ControlPart, ControlStates, IntRect& zoomedRect, float zoomFactor) const { }
+ virtual void inflateControlPaintRect(ControlPart, ControlStates, IntRect& /*zoomedRect*/, float /*zoomFactor*/) const { }
// This method is called once, from RenderTheme::adjustDefaultStyleSheet(), to let each platform adjust
// the default CSS rules in html4.css.
diff --git a/WebCore/platform/ThemeTypes.h b/WebCore/platform/ThemeTypes.h
index 8d73ea3..ae85a63 100644
--- a/WebCore/platform/ThemeTypes.h
+++ b/WebCore/platform/ThemeTypes.h
@@ -46,8 +46,9 @@ typedef unsigned ControlStates;
enum ControlPart {
NoControlPart, CheckboxPart, RadioPart, PushButtonPart, SquareButtonPart, ButtonPart,
ButtonBevelPart, DefaultButtonPart, ListboxPart, ListItemPart,
- MediaFullscreenButtonPart, MediaMuteButtonPart, MediaPlayButtonPart,
- MediaSeekBackButtonPart, MediaSeekForwardButtonPart, MediaSliderPart, MediaSliderThumbPart,
+ MediaFullscreenButtonPart, MediaMuteButtonPart, MediaPlayButtonPart, MediaSeekBackButtonPart,
+ MediaSeekForwardButtonPart, MediaSliderPart, MediaSliderThumbPart, MediaTimelineContainerPart,
+ MediaCurrentTimePart, MediaTimeRemainingPart,
MenulistPart, MenulistButtonPart, MenulistTextPart, MenulistTextFieldPart,
SliderHorizontalPart, SliderVerticalPart, SliderThumbHorizontalPart,
SliderThumbVerticalPart, CaretPart, SearchFieldPart, SearchFieldDecorationPart,
diff --git a/WebCore/platform/ThreadGlobalData.cpp b/WebCore/platform/ThreadGlobalData.cpp
new file mode 100644
index 0000000..9bf0bf2
--- /dev/null
+++ b/WebCore/platform/ThreadGlobalData.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "ThreadGlobalData.h"
+
+#include "EventNames.h"
+#include "StringImpl.h"
+#include <wtf/UnusedParam.h>
+
+#if USE(ICU_UNICODE)
+#include "TextCodecICU.h"
+#endif
+
+#if PLATFORM(MAC)
+#include "TextCodecMac.h"
+#endif
+
+#if ENABLE(WORKERS)
+#include <wtf/Threading.h>
+#include <wtf/ThreadSpecific.h>
+using namespace WTF;
+#endif
+
+namespace WebCore {
+
+ThreadGlobalData& threadGlobalData()
+{
+ // FIXME: Workers are not necessarily the only feature that make per-thread global data necessary.
+ // We need to check for e.g. database objects manipulating strings on secondary threads.
+#if ENABLE(WORKERS)
+ // ThreadGlobalData is used on main thread before it could possibly be used on secondary ones, so there is no need for synchronization here.
+ static ThreadSpecific<ThreadGlobalData>* threadGlobalData = new ThreadSpecific<ThreadGlobalData>;
+ return **threadGlobalData;
+#else
+ static ThreadGlobalData* staticData;
+ if (!staticData) {
+ staticData = static_cast<ThreadGlobalData*>(fastMalloc(sizeof(ThreadGlobalData)));
+ // ThreadGlobalData constructor indirectly uses staticData, so we need to set up the memory before invoking it.
+ new (staticData) ThreadGlobalData;
+ }
+ return *staticData;
+#endif
+}
+
+ThreadGlobalData::ThreadGlobalData()
+ : m_emptyString(new StringImpl)
+ , m_atomicStringTable(new HashSet<StringImpl*>)
+ , m_eventNames(new EventNames)
+#if USE(ICU_UNICODE)
+ , m_cachedConverterICU(new ICUConverterWrapper)
+#endif
+#if PLATFORM(MAC)
+ , m_cachedConverterTEC(new TECConverterWrapper)
+#endif
+{
+}
+
+ThreadGlobalData::~ThreadGlobalData()
+{
+#if PLATFORM(MAC)
+ delete m_cachedConverterTEC;
+#endif
+#if USE(ICU_UNICODE)
+ delete m_cachedConverterICU;
+#endif
+
+ delete m_eventNames;
+ delete m_atomicStringTable;
+
+ 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.
+ delete m_emptyString;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/ThreadGlobalData.h b/WebCore/platform/ThreadGlobalData.h
new file mode 100644
index 0000000..17637aa
--- /dev/null
+++ b/WebCore/platform/ThreadGlobalData.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 ThreadGlobalData_h
+#define ThreadGlobalData_h
+
+#include "StringHash.h"
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+ class EventNames;
+ struct ICUConverterWrapper;
+ struct TECConverterWrapper;
+
+ class ThreadGlobalData : Noncopyable {
+ public:
+ ThreadGlobalData();
+ ~ThreadGlobalData();
+
+ EventNames& eventNames() { return *m_eventNames; }
+ StringImpl* emptyString() { return m_emptyString; }
+ HashSet<StringImpl*>& atomicStringTable() { return *m_atomicStringTable; }
+
+#if USE(ICU_UNICODE)
+ ICUConverterWrapper& cachedConverterICU() { return *m_cachedConverterICU; }
+#endif
+
+#if PLATFORM(MAC)
+ TECConverterWrapper& cachedConverterTEC() { return *m_cachedConverterTEC; }
+#endif
+
+ private:
+ StringImpl* m_emptyString;
+ HashSet<StringImpl*>* m_atomicStringTable;
+ EventNames* m_eventNames;
+
+#if USE(ICU_UNICODE)
+ ICUConverterWrapper* m_cachedConverterICU;
+#endif
+
+#if PLATFORM(MAC)
+ TECConverterWrapper* m_cachedConverterTEC;
+#endif
+ };
+
+ ThreadGlobalData& threadGlobalData();
+
+} // namespace WebCore
+
+#endif // ThreadGlobalData_h
diff --git a/WebCore/platform/Timer.cpp b/WebCore/platform/Timer.cpp
index 94e2af8..a8fcbb8 100644
--- a/WebCore/platform/Timer.cpp
+++ b/WebCore/platform/Timer.cpp
@@ -27,10 +27,10 @@
#include "Timer.h"
#include "SharedTimer.h"
-#include "SystemTime.h"
#include <limits.h>
#include <limits>
#include <math.h>
+#include <wtf/CurrentTime.h>
#include <wtf/HashSet.h>
#include <wtf/Vector.h>
@@ -46,7 +46,9 @@ namespace WebCore {
// ----------------
-static bool deferringTimers;
+#ifdef ANDROID_FIX // it is removed in http://trac.webkit.org/changeset/40080, but Android needs it
+static bool deferringTimers;
+#endif
static Vector<TimerBase*>* timerHeap;
static HashSet<const TimerBase*>* timersReadyToFire;
@@ -64,7 +66,8 @@ public:
TimerBase* timer() const { return m_timer; }
- void checkConsistency() const {
+ void checkConsistency() const
+ {
ASSERT(m_index >= 0);
ASSERT(m_index < (timerHeap ? static_cast<int>(timerHeap->size()) : 0));
}
@@ -131,9 +134,10 @@ public:
int index() const { return m_index; }
- void checkConsistency(int offset = 0) const {
- ASSERT(m_index + offset >= 0);
- ASSERT(m_index + offset <= (timerHeap ? static_cast<int>(timerHeap->size()) : 0));
+ void checkConsistency(int offset = 0) const
+ {
+ ASSERT_UNUSED(offset, m_index + offset >= 0);
+ ASSERT_UNUSED(offset, m_index + offset <= (timerHeap ? static_cast<int>(timerHeap->size()) : 0));
}
private:
@@ -154,7 +158,11 @@ inline int operator-(TimerHeapIterator a, TimerHeapIterator b) { return a.index(
void updateSharedTimer()
{
- if (timersReadyToFire || deferringTimers || !timerHeap || timerHeap->isEmpty())
+#ifdef ANDROID_FIX // it is removed in http://trac.webkit.org/changeset/40080, but Android needs it
+ if (timersReadyToFire || deferringTimers || !timerHeap || timerHeap->isEmpty())
+#else
+ if (timersReadyToFire || !timerHeap || timerHeap->isEmpty())
+#endif
stopSharedTimer();
else
setSharedTimerFireTime(timerHeap->first()->m_nextFireTime);
@@ -378,19 +386,21 @@ void TimerBase::fireTimersInNestedEventLoop()
updateSharedTimer();
}
-// ----------------
+#ifdef ANDROID_FIX // it is removed in http://trac.webkit.org/changeset/40080, but Android needs it
+// ----------------
-bool isDeferringTimers()
-{
- return deferringTimers;
-}
+bool isDeferringTimers()
+{
+ return deferringTimers;
+}
-void setDeferringTimers(bool shouldDefer)
-{
- if (shouldDefer == deferringTimers)
- return;
- deferringTimers = shouldDefer;
- updateSharedTimer();
+void setDeferringTimers(bool shouldDefer)
+{
+ if (shouldDefer == deferringTimers)
+ return;
+ deferringTimers = shouldDefer;
+ updateSharedTimer();
}
+#endif
}
diff --git a/WebCore/platform/Timer.h b/WebCore/platform/Timer.h
index ba98ec5..a2589f7 100644
--- a/WebCore/platform/Timer.h
+++ b/WebCore/platform/Timer.h
@@ -83,7 +83,9 @@ private:
unsigned m_heapInsertionOrder; // Used to keep order among equal-fire-time timers
friend void updateSharedTimer();
+#ifdef ANDROID_FIX // it is removed in http://trac.webkit.org/changeset/40080, but Android needs it
friend void setDeferringTimers(bool);
+#endif
friend class TimerHeapElement;
friend bool operator<(const TimerHeapElement&, const TimerHeapElement&);
};
@@ -102,10 +104,12 @@ private:
TimerFiredFunction m_function;
};
+#ifdef ANDROID_FIX // it is removed in http://trac.webkit.org/changeset/40080, but Android needs it
// Set to true to prevent any timers from firing.
// When set back to false, timers that were deferred will fire.
bool isDeferringTimers();
void setDeferringTimers(bool);
+#endif
}
diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h
index 1b82ab4..6684eb2 100644
--- a/WebCore/platform/Widget.h
+++ b/WebCore/platform/Widget.h
@@ -173,7 +173,7 @@ public:
IntPoint convertFromContainingWindow(const IntPoint&) const; // See comment above about when not to use this method.
IntRect convertFromContainingWindow(const IntRect&) const;
- virtual void frameRectsChanged() const {}
+ virtual void frameRectsChanged() {}
#if PLATFORM(MAC)
NSView* getOuterView() const;
diff --git a/WebCore/platform/android/FileChooserAndroid.cpp b/WebCore/platform/android/FileChooserAndroid.cpp
index 2c75373..a8c4150 100644
--- a/WebCore/platform/android/FileChooserAndroid.cpp
+++ b/WebCore/platform/android/FileChooserAndroid.cpp
@@ -31,7 +31,10 @@
namespace WebCore {
String FileChooser::basenameForWidth(const Font& font, int width) const
-{
+{
+ if (m_filenames.size() == 0) {
+ return String();
+ }
// FIXME: This could be a lot faster, but assuming the data will not
// often be much longer than the provided width, this may be fast enough.
String output = m_filenames[0].copy();
diff --git a/WebCore/platform/android/FileSystemAndroid.cpp b/WebCore/platform/android/FileSystemAndroid.cpp
index b6d58bc..fcb0413 100644
--- a/WebCore/platform/android/FileSystemAndroid.cpp
+++ b/WebCore/platform/android/FileSystemAndroid.cpp
@@ -29,7 +29,9 @@
#include "FileSystem.h"
#include "CString.h"
+#include <fnmatch.h>
#include <dlfcn.h>
+#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include "cutils/log.h"
@@ -98,4 +100,33 @@ String homeDirectoryPath()
return sPluginPath;
}
+// new as of webkit4, Feb 28, 2009
+Vector<String> listDirectory(const String& path, const String& filter)
+{
+ Vector<String> entries;
+ CString cpath = path.utf8();
+ CString cfilter = filter.utf8();
+ DIR* dir = opendir(cpath.data());
+ if (dir) {
+ struct dirent * dp;
+ while ((dp = readdir(dir)) != NULL) {
+ const char* name = dp->d_name;
+ if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
+ continue;
+ }
+ if (fnmatch(cfilter.data(), name, 0) != 0) {
+ continue;
+ }
+ char filePath[1024];
+ if ((int) (sizeof(filePath) - 1) < snprintf(filePath,
+ sizeof(filePath), "%s/%s", cpath.data(), name)) {
+ continue; // buffer overflow
+ }
+ entries.append(filePath);
+ }
+ closedir(dir);
+ }
+ return entries;
+}
+
}
diff --git a/WebCore/platform/android/SharedTimerAndroid.cpp b/WebCore/platform/android/SharedTimerAndroid.cpp
index d797cfb..3ff9705 100644
--- a/WebCore/platform/android/SharedTimerAndroid.cpp
+++ b/WebCore/platform/android/SharedTimerAndroid.cpp
@@ -27,10 +27,10 @@
#include "config.h"
#include "SharedTimer.h"
-#include "SystemTime.h"
#include "JavaSharedClient.h"
#include "TimerClient.h"
#include <utils/Log.h>
+#include <wtf/CurrentTime.h>
using namespace android;
@@ -48,7 +48,7 @@ void setSharedTimerFiredFunction(void (*f)())
// as the result of currentTime() is.
void setSharedTimerFireTime(double fireTime)
{
- long long timeInMS = (long long)((fireTime - currentTime()) * 1000);
+ long long timeInMS = (long long)((fireTime - WTF::currentTime()) * 1000);
LOGV("setSharedTimerFireTime: in %ld millisec", timeInMS);
if (JavaSharedClient::GetTimerClient())
diff --git a/WebCore/platform/android/SoundAndroid.cpp b/WebCore/platform/android/SoundAndroid.cpp
new file mode 100644
index 0000000..50cbfa5
--- /dev/null
+++ b/WebCore/platform/android/SoundAndroid.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "Sound.h"
+
+namespace WebCore {
+
+void systemBeep()
+{
+ // do nothing
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/android/SystemTimeAndroid.cpp b/WebCore/platform/android/SystemTimeAndroid.cpp
index 9ac32dc..a9c862a 100644
--- a/WebCore/platform/android/SystemTimeAndroid.cpp
+++ b/WebCore/platform/android/SystemTimeAndroid.cpp
@@ -26,34 +26,12 @@
#include "config.h"
#include "SystemTime.h"
-#include <sys/time.h>
-
namespace WebCore {
-double currentTime()
-{
- struct timeval tv;
-
- gettimeofday(&tv, (struct timezone *) NULL);
- double now = tv.tv_sec + (tv.tv_usec / 1000000.0);
-
- return now;
-}
-
-uint32_t get_thread_msec()
+float userIdleTime()
{
-#if defined(HAVE_POSIX_CLOCKS)
- struct timespec tm;
-
- clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
-
- return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
-#else
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
-#endif
+ // Needed for PageCache, which we currently have disabled.
+ return 0.0F;
}
} // namespace WebCore
diff --git a/WebCore/platform/android/TemporaryLinkStubs.cpp b/WebCore/platform/android/TemporaryLinkStubs.cpp
index 01789f4..5d71dd0 100644
--- a/WebCore/platform/android/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/android/TemporaryLinkStubs.cpp
@@ -424,6 +424,12 @@ String contextMenuItemTagRightToLeft()
return String();
}
+String contextMenuItemTagTextDirectionMenu()
+{
+ ASSERT(0);
+ return String();
+}
+
} // namespace WebCore
// FIXME, no support for spelling yet.
@@ -601,14 +607,6 @@ void ContextMenuItem::setEnabled(bool)
notImplemented();
}
-namespace WebCore {
-
-float userIdleTime()
-{
- notImplemented();
- return 0;
-}
-
// systemBeep() is called by the Editor to indicate that there was nothing to copy, and may be called from
// other places too.
void systemBeep()
@@ -616,8 +614,6 @@ void systemBeep()
notImplemented();
}
-}
-
// functions new to Jun-07 tip of tree merge:
// void WebCore::CachedPage::close() {}
@@ -750,14 +746,14 @@ PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String&)
namespace JSC { namespace Bindings {
-bool dispatchJNICall(ExecState*, void const*, _jobject*, bool, JNIType,
- _jmethodID*, jvalue*, jvalue&, char const*, JSValue*&)
+bool dispatchJNICall(ExecState*, const void* targetAppletView, jobject obj, bool isStatic, JNIType returnType,
+ jmethodID methodID, jvalue* args, jvalue& result, const char* callingURL, JSValuePtr& exceptionDescription)
{
notImplemented();
return false;
}
-} } // namespace JSC::Bindings
+} } // namespace Bindings
char* dirname(const char*)
{
@@ -811,12 +807,6 @@ ScrollbarTheme* ScrollbarTheme::nativeTheme()
return &theme;
}
-JSC::JSValue* toJS(JSC::ExecState*, JSC::Profile*)
-{
- notImplemented();
- return 0;
-}
-
} // namespace WebCore
FileList::FileList()
@@ -862,30 +852,38 @@ OpaqueJSClassContextData::~OpaqueJSClassContextData()
notImplemented();
}
+// as we don't use inspector/*.cpp, add stub here.
+
namespace WebCore {
-JSC::JSValue* JavaScriptCallFrame::evaluate(JSC::UString const&, JSC::JSValue*&) const
+JSValuePtr toJS(ExecState*, Profile*)
{
notImplemented();
- return 0;
+ return jsNull();
+}
+
+JSValuePtr JavaScriptCallFrame::evaluate(const UString& script, JSValuePtr& exception) const
+{
+ notImplemented();
+ return jsNull();
}
-const JSC::ScopeChainNode* JavaScriptCallFrame::scopeChain() const
+const ScopeChainNode* JavaScriptCallFrame::scopeChain() const
{
notImplemented();
return 0;
}
-JSC::JSObject* JavaScriptCallFrame::thisObject() const
+JSObject* JavaScriptCallFrame::thisObject() const
{
notImplemented();
return 0;
}
-JSC::DebuggerCallFrame::Type JavaScriptCallFrame::type() const
+DebuggerCallFrame::Type JavaScriptCallFrame::type() const
{
notImplemented();
- return (JSC::DebuggerCallFrame::Type) 0;
+ return (DebuggerCallFrame::Type) 0;
}
JavaScriptCallFrame* JavaScriptCallFrame::caller()
@@ -899,6 +897,7 @@ String JavaScriptCallFrame::functionName() const
notImplemented();
return String();
}
+
}
JavaScriptDebugServer::JavaScriptDebugServer() :
diff --git a/WebCore/platform/animation/Animation.cpp b/WebCore/platform/animation/Animation.cpp
new file mode 100644
index 0000000..5df4480
--- /dev/null
+++ b/WebCore/platform/animation/Animation.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Animation.h"
+
+namespace WebCore {
+
+Animation::Animation()
+ : m_delay(initialAnimationDelay())
+ , m_direction(initialAnimationDirection())
+ , m_duration(initialAnimationDuration())
+ , m_iterationCount(initialAnimationIterationCount())
+ , m_name(initialAnimationName())
+ , m_property(initialAnimationProperty())
+ , m_timingFunction(initialAnimationTimingFunction())
+ , m_playState(initialAnimationPlayState())
+ , m_delaySet(false)
+ , m_directionSet(false)
+ , m_durationSet(false)
+ , m_iterationCountSet(false)
+ , m_nameSet(false)
+ , m_playStateSet(false)
+ , m_propertySet(false)
+ , m_timingFunctionSet(false)
+ , m_isNone(false)
+{
+}
+
+Animation::Animation(const Animation& o)
+ : RefCounted<Animation>()
+ , m_delay(o.m_delay)
+ , m_direction(o.m_direction)
+ , m_duration(o.m_duration)
+ , m_iterationCount(o.m_iterationCount)
+ , m_name(o.m_name)
+ , m_property(o.m_property)
+ , m_timingFunction(o.m_timingFunction)
+ , m_playState(o.m_playState)
+ , m_delaySet(o.m_delaySet)
+ , m_directionSet(o.m_directionSet)
+ , m_durationSet(o.m_durationSet)
+ , m_iterationCountSet(o.m_iterationCountSet)
+ , m_nameSet(o.m_nameSet)
+ , m_playStateSet(o.m_playStateSet)
+ , m_propertySet(o.m_propertySet)
+ , m_timingFunctionSet(o.m_timingFunctionSet)
+ , m_isNone(o.m_isNone)
+{
+}
+
+Animation& Animation::operator=(const Animation& o)
+{
+ m_delay = o.m_delay;
+ m_direction = o.m_direction;
+ m_duration = o.m_duration;
+ m_iterationCount = o.m_iterationCount;
+ m_name = o.m_name;
+ m_playState = o.m_playState;
+ m_property = o.m_property;
+ m_timingFunction = o.m_timingFunction;
+
+ m_delaySet = o.m_delaySet;
+ m_directionSet = o.m_directionSet;
+ m_durationSet = o.m_durationSet;
+ m_iterationCountSet = o.m_iterationCountSet;
+ m_nameSet = o.m_nameSet;
+ m_playStateSet = o.m_playStateSet;
+ m_propertySet = o.m_propertySet;
+ m_timingFunctionSet = o.m_timingFunctionSet;
+
+ m_isNone = o.m_isNone;
+
+ return *this;
+}
+
+Animation::~Animation()
+{
+}
+
+bool Animation::animationsMatch(const Animation* o, bool matchPlayStates) const
+{
+ if (!o)
+ return false;
+
+ bool result = m_delay == o->m_delay &&
+ m_direction == o->m_direction &&
+ m_duration == o->m_duration &&
+ m_iterationCount == o->m_iterationCount &&
+ m_name == o->m_name &&
+ m_property == o->m_property &&
+ m_timingFunction == o->m_timingFunction &&
+ m_delaySet == o->m_delaySet &&
+ m_directionSet == o->m_directionSet &&
+ m_durationSet == o->m_durationSet &&
+ m_iterationCountSet == o->m_iterationCountSet &&
+ m_nameSet == o->m_nameSet &&
+ m_propertySet == o->m_propertySet &&
+ m_timingFunctionSet == o->m_timingFunctionSet &&
+ m_isNone == o->m_isNone;
+
+ if (!result)
+ return false;
+
+ return !matchPlayStates || (m_playState == o->m_playState && m_playStateSet == o->m_playStateSet);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/animation/Animation.h b/WebCore/platform/animation/Animation.h
new file mode 100644
index 0000000..294acdf
--- /dev/null
+++ b/WebCore/platform/animation/Animation.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 Animation_h
+#define Animation_h
+
+#include "PlatformString.h"
+#include "TimingFunction.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+const int cAnimateNone = 0;
+const int cAnimateAll = -2;
+
+class Animation : public RefCounted<Animation> {
+public:
+ ~Animation();
+
+ static PassRefPtr<Animation> create() { return adoptRef(new Animation); };
+
+ bool isDelaySet() const { return m_delaySet; }
+ bool isDirectionSet() const { return m_directionSet; }
+ bool isDurationSet() const { return m_durationSet; }
+ bool isIterationCountSet() const { return m_iterationCountSet; }
+ bool isNameSet() const { return m_nameSet; }
+ bool isPlayStateSet() const { return m_playStateSet; }
+ bool isPropertySet() const { return m_propertySet; }
+ bool isTimingFunctionSet() const { return m_timingFunctionSet; }
+
+ // Flags this to be the special "none" animation (animation-name: none)
+ bool isNoneAnimation() const { return m_isNone; }
+ // We can make placeholder Animation objects to keep the comma-separated lists
+ // of properties in sync. isValidAnimation means this is not a placeholder.
+ bool isValidAnimation() const { return !m_isNone && !m_name.isEmpty(); }
+
+ bool isEmpty() const
+ {
+ return (!m_directionSet && !m_durationSet && !m_nameSet && !m_playStateSet &&
+ !m_iterationCountSet && !m_delaySet && !m_timingFunctionSet && !m_propertySet);
+ }
+
+ bool isEmptyOrZeroDuration() const
+ {
+ return isEmpty() || (m_duration == 0 && m_delay <= 0);
+ }
+
+ void clearDelay() { m_delaySet = false; }
+ void clearDirection() { m_directionSet = false; }
+ void clearDuration() { m_durationSet = false; }
+ void clearIterationCount() { m_iterationCountSet = false; }
+ void clearName() { m_nameSet = false; }
+ void clearPlayState() { m_playStateSet = AnimPlayStatePlaying; }
+ void clearProperty() { m_propertySet = false; }
+ void clearTimingFunction() { m_timingFunctionSet = false; }
+
+ double delay() const { return m_delay; }
+ bool direction() const { return m_direction; }
+ double duration() const { return m_duration; }
+ int iterationCount() const { return m_iterationCount; }
+ const String& name() const { return m_name; }
+ unsigned playState() const { return m_playState; }
+ int property() const { return m_property; }
+ const TimingFunction& timingFunction() const { return m_timingFunction; }
+
+ void setDelay(double c) { m_delay = c; m_delaySet = true; }
+ void setDirection(bool d) { m_direction = d; m_directionSet = true; }
+ void setDuration(double d) { ASSERT(d >= 0); m_duration = d; m_durationSet = true; }
+ void setIterationCount(int c) { m_iterationCount = c; m_iterationCountSet = true; }
+ void setName(const String& n) { m_name = n; m_nameSet = true; }
+ void setPlayState(unsigned d) { m_playState = d; m_playStateSet = true; }
+ void setProperty(int t) { m_property = t; m_propertySet = true; }
+ void setTimingFunction(const TimingFunction& f) { m_timingFunction = f; m_timingFunctionSet = true; }
+
+ void setIsNoneAnimation(bool n) { m_isNone = n; }
+
+ Animation& operator=(const Animation& o);
+
+ // return true if all members of this class match (excluding m_next)
+ bool animationsMatch(const Animation*, bool matchPlayStates = true) const;
+
+ // return true every Animation in the chain (defined by m_next) match
+ bool operator==(const Animation& o) const { return animationsMatch(&o); }
+ bool operator!=(const Animation& o) const { return !(*this == o); }
+
+private:
+ Animation();
+ Animation(const Animation& o);
+
+ double m_delay;
+ bool m_direction;
+ double m_duration;
+ int m_iterationCount;
+ String m_name;
+ int m_property;
+ TimingFunction m_timingFunction;
+
+ unsigned m_playState : 2;
+
+ bool m_delaySet : 1;
+ bool m_directionSet : 1;
+ bool m_durationSet : 1;
+ bool m_iterationCountSet : 1;
+ bool m_nameSet : 1;
+ bool m_playStateSet : 1;
+ bool m_propertySet : 1;
+ bool m_timingFunctionSet : 1;
+
+ bool m_isNone : 1;
+
+public:
+ static float initialAnimationDelay() { return 0; }
+ static bool initialAnimationDirection() { return false; }
+ static double initialAnimationDuration() { return 0; }
+ static int initialAnimationIterationCount() { return 1; }
+ static String initialAnimationName() { return String("none"); }
+ static unsigned initialAnimationPlayState() { return AnimPlayStatePlaying; }
+ static int initialAnimationProperty() { return cAnimateAll; }
+ static TimingFunction initialAnimationTimingFunction() { return TimingFunction(); }
+};
+
+} // namespace WebCore
+
+#endif // Animation_h
diff --git a/WebCore/platform/animation/AnimationList.cpp b/WebCore/platform/animation/AnimationList.cpp
new file mode 100644
index 0000000..804dede
--- /dev/null
+++ b/WebCore/platform/animation/AnimationList.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "AnimationList.h"
+
+namespace WebCore {
+
+#define FILL_UNSET_PROPERTY(test, propGet, propSet) \
+for (i = 0; i < size() && animation(i)->test(); ++i) { } \
+if (i < size() && i != 0) { \
+ for (size_t j = 0; i < size(); ++i, ++j) \
+ animation(i)->propSet(animation(j)->propGet()); \
+}
+
+void AnimationList::fillUnsetProperties()
+{
+ size_t i;
+ FILL_UNSET_PROPERTY(isDelaySet, delay, setDelay);
+ FILL_UNSET_PROPERTY(isDirectionSet, direction, setDirection);
+ FILL_UNSET_PROPERTY(isDurationSet, duration, setDuration);
+ FILL_UNSET_PROPERTY(isIterationCountSet, iterationCount, setIterationCount);
+ FILL_UNSET_PROPERTY(isPlayStateSet, playState, setPlayState);
+ FILL_UNSET_PROPERTY(isNameSet, name, setName);
+ FILL_UNSET_PROPERTY(isTimingFunctionSet, timingFunction, setTimingFunction);
+ FILL_UNSET_PROPERTY(isPropertySet, property, setProperty);
+}
+
+bool AnimationList::operator==(const AnimationList& o) const
+{
+ if (size() != o.size())
+ return false;
+ for (size_t i = 0; i < size(); ++i)
+ if (*animation(i) != *o.animation(i))
+ return false;
+ return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/animation/AnimationList.h b/WebCore/platform/animation/AnimationList.h
new file mode 100644
index 0000000..9901424
--- /dev/null
+++ b/WebCore/platform/animation/AnimationList.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 AnimationList_h
+#define AnimationList_h
+
+#include "Animation.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AnimationList {
+public:
+ void fillUnsetProperties();
+ bool operator==(const AnimationList& o) const;
+ bool operator!=(const AnimationList& o) const
+ {
+ return !(*this == o);
+ }
+
+ size_t size() const { return m_animations.size(); }
+ bool isEmpty() const { return m_animations.isEmpty(); }
+
+ void resize(size_t n) { m_animations.resize(n); }
+ void remove(size_t i) { m_animations.remove(i); }
+ void append(PassRefPtr<Animation> anim) { m_animations.append(anim); }
+
+ Animation* animation(size_t i) { return m_animations[i].get(); }
+ const Animation* animation(size_t i) const { return m_animations[i].get(); }
+
+private:
+ Vector<RefPtr<Animation> > m_animations;
+};
+
+
+} // namespace WebCore
+
+#endif // AnimationList_h
diff --git a/WebCore/platform/animation/TimingFunction.h b/WebCore/platform/animation/TimingFunction.h
new file mode 100644
index 0000000..f114596
--- /dev/null
+++ b/WebCore/platform/animation/TimingFunction.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 TimingFunction_h
+#define TimingFunction_h
+
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+struct TimingFunction {
+ TimingFunction()
+ : m_type(CubicBezierTimingFunction)
+ , m_x1(0.25)
+ , m_y1(0.1)
+ , m_x2(0.25)
+ , m_y2(1.0)
+ {
+ }
+
+ TimingFunction(ETimingFunctionType timingFunction, double x1 = 0.0, double y1 = 0.0, double x2 = 1.0, double y2 = 1.0)
+ : m_type(timingFunction)
+ , m_x1(x1)
+ , m_y1(y1)
+ , m_x2(x2)
+ , m_y2(y2)
+ {
+ }
+
+ bool operator==(const TimingFunction& o) const
+ {
+ return m_type == o.m_type && m_x1 == o.m_x1 && m_y1 == o.m_y1 && m_x2 == o.m_x2 && m_y2 == o.m_y2;
+ }
+
+ double x1() const { return m_x1; }
+ double y1() const { return m_y1; }
+ double x2() const { return m_x2; }
+ double y2() const { return m_y2; }
+
+ ETimingFunctionType type() const { return m_type; }
+
+private:
+ ETimingFunctionType m_type;
+
+ double m_x1;
+ double m_y1;
+ double m_x2;
+ double m_y2;
+};
+
+} // namespace WebCore
+
+#endif // TimingFunction_h
diff --git a/WebCore/platform/cf/SharedBufferCF.cpp b/WebCore/platform/cf/SharedBufferCF.cpp
index c0e471a..7213c7e 100644
--- a/WebCore/platform/cf/SharedBufferCF.cpp
+++ b/WebCore/platform/cf/SharedBufferCF.cpp
@@ -28,6 +28,8 @@
#include "config.h"
#include "SharedBuffer.h"
+#include "PurgeableBuffer.h"
+
namespace WebCore {
SharedBuffer::SharedBuffer(CFDataRef cfData)
diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h
new file mode 100644
index 0000000..dd36c1a
--- /dev/null
+++ b/WebCore/platform/chromium/ChromiumBridge.h
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+#ifndef ChromiumBridge_h
+#define ChromiumBridge_h
+
+#include "LinkHash.h"
+#include "PassRefPtr.h"
+#include "PasteboardPrivate.h"
+
+class NativeImageSkia;
+
+typedef struct NPObject NPObject;
+typedef struct _NPP NPP_t;
+typedef NPP_t* NPP;
+
+#if PLATFORM(WIN_OS)
+typedef struct HFONT__* HFONT;
+#endif
+
+namespace WebCore {
+
+ class Color;
+ class Cursor;
+ class Document;
+ class Frame;
+ class GraphicsContext;
+ class Image;
+ class IntRect;
+ class KURL;
+ class String;
+ class Widget;
+
+ struct PluginInfo;
+
+ // An interface to the embedding layer, which has the ability to answer
+ // questions about the system and so on...
+
+ class ChromiumBridge {
+ public:
+ // Clipboard ----------------------------------------------------------
+ static bool clipboardIsFormatAvailable(PasteboardPrivate::ClipboardFormat);
+
+ static String clipboardReadPlainText();
+ static void clipboardReadHTML(String*, KURL*);
+
+ static void clipboardWriteSelection(const String&, const KURL&, const String&, bool);
+ static void clipboardWriteURL(const KURL&, const String&);
+ 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);
+
+ // DNS ----------------------------------------------------------------
+ static void prefetchDNS(const String& hostname);
+
+ // Font ---------------------------------------------------------------
+#if PLATFORM(WIN_OS)
+ static bool ensureFontLoaded(HFONT font);
+#endif
+
+ // Forms --------------------------------------------------------------
+ static void notifyFormStateChanged(const Document*);
+
+ // JavaScript ---------------------------------------------------------
+ static void notifyJSOutOfMemory(Frame*);
+
+ // Language -----------------------------------------------------------
+ static String computedDefaultLanguage();
+
+ // LayoutTestMode -----------------------------------------------------
+ static bool layoutTestMode();
+
+ // MimeType -----------------------------------------------------------
+ static bool isSupportedImageMIMEType(const char* mimeType);
+ static bool isSupportedJavascriptMIMEType(const char* mimeType);
+ static bool isSupportedNonImageMIMEType(const char* mimeType);
+ static bool matchesMIMEType(const String& pattern, const String& type);
+ static String mimeTypeForExtension(const String& ext);
+ static String mimeTypeFromFile(const String& filePath);
+ static String preferredExtensionForMIMEType(const String& mimeType);
+
+ // Plugin -------------------------------------------------------------
+ static bool plugins(bool refresh, Vector<PluginInfo*>*);
+ static NPObject* pluginScriptableObject(Widget*);
+ static bool popupsAllowed(NPP);
+
+ // Protocol -----------------------------------------------------------
+ static String uiResourceProtocol();
+
+ // Resources ----------------------------------------------------------
+ static PassRefPtr<Image> loadPlatformImageResource(const char* name);
+
+ // Screen -------------------------------------------------------------
+ static int screenDepth(Widget*);
+ static int screenDepthPerComponent(Widget*);
+ static bool screenIsMonochrome(Widget*);
+ static IntRect screenRect(Widget*);
+ static IntRect screenAvailableRect(Widget*);
+
+ // SharedTimers -------------------------------------------------------
+ static void setSharedTimerFiredFunction(void (*func)());
+ static void setSharedTimerFireTime(double fireTime);
+ static void stopSharedTimer();
+
+ // StatsCounters ------------------------------------------------------
+ static void decrementStatsCounter(const char* name);
+ static void incrementStatsCounter(const char* name);
+ static void initV8CounterFunction();
+
+ // SystemTime ---------------------------------------------------------
+ static double currentTime();
+
+ // Theming ------------------------------------------------------------
+#if PLATFORM(WIN_OS)
+ static void paintButton(
+ GraphicsContext*, int part, int state, int classicState, const IntRect&);
+ static void paintMenuList(
+ GraphicsContext*, int part, int state, int classicState, const IntRect&);
+ static void paintScrollbarArrow(
+ GraphicsContext*, int state, int classicState, const IntRect&);
+ static void paintScrollbarThumb(
+ GraphicsContext*, int part, int state, int classicState, const IntRect&);
+ static void paintScrollbarTrack(
+ GraphicsContext*, int part, int state, int classicState, const IntRect&, const IntRect& alignRect);
+ static void paintTextField(
+ GraphicsContext*, int part, int state, int classicState, const IntRect&, const Color&, bool fillContentArea, bool drawEdges);
+#endif
+
+ // Trace Event --------------------------------------------------------
+ static void traceEventBegin(const char* name, void* id, const char* extra);
+ static void traceEventEnd(const char* name, void* id, const char* extra);
+
+ // URL ----------------------------------------------------------------
+ static KURL inspectorURL();
+
+ // Visited links ------------------------------------------------------
+ static LinkHash visitedLinkHash(const UChar* url, unsigned length);
+ static LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL);
+ static bool isLinkVisited(LinkHash);
+
+ // Widget -------------------------------------------------------------
+ static void widgetSetCursor(Widget*, const Cursor&);
+ static void widgetSetFocus(Widget*);
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/ChromiumDataObject.cpp b/WebCore/platform/chromium/ChromiumDataObject.cpp
new file mode 100644
index 0000000..67e9d00
--- /dev/null
+++ b/WebCore/platform/chromium/ChromiumDataObject.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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 "config.h"
+#include "ChromiumDataObject.h"
+
+namespace WebCore {
+
+void ChromiumDataObject::clear()
+{
+ url = KURL();
+ urlTitle = "";
+ filenames.clear();
+ plainText = "";
+ textHtml = "";
+ htmlBaseUrl = KURL();
+ fileContentFilename = "";
+ if (fileContent)
+ fileContent->clear();
+}
+
+bool ChromiumDataObject::hasData()
+{
+ return !url.isEmpty()
+ || !filenames.isEmpty()
+ || !plainText.isEmpty()
+ || !textHtml.isEmpty()
+ || fileContent;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/ChromiumDataObject.h b/WebCore/platform/chromium/ChromiumDataObject.h
new file mode 100644
index 0000000..448e763
--- /dev/null
+++ b/WebCore/platform/chromium/ChromiumDataObject.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#ifndef ChromiumDataObject_h
+#define ChromiumDataObject_h
+
+#include "KURL.h"
+#include "PlatformString.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+ // A data object for holding data that would be in a clipboard or moved
+ // during a drag-n-drop operation. This is the data that WebCore is aware
+ // of and is not specific to a platform.
+ class ChromiumDataObject : public RefCounted<ChromiumDataObject> {
+ public:
+ static PassRefPtr<ChromiumDataObject> create()
+ {
+ return adoptRef(new ChromiumDataObject);
+ }
+
+ void clear();
+ bool hasData();
+
+ KURL url;
+ String urlTitle;
+
+ Vector<String> filenames;
+
+ String plainText;
+
+ String textHtml;
+ KURL htmlBaseUrl;
+
+ String fileContentFilename;
+ RefPtr<SharedBuffer> fileContent;
+
+ private:
+ ChromiumDataObject() {}
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp
new file mode 100644
index 0000000..7fc156e
--- /dev/null
+++ b/WebCore/platform/chromium/ClipboardChromium.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * 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 "ClipboardChromium.h"
+
+#include "CachedImage.h"
+#include "ChromiumBridge.h"
+#include "ChromiumDataObject.h"
+#include "ClipboardUtilitiesChromium.h"
+#include "Document.h"
+#include "Element.h"
+#include "Frame.h"
+#include "HTMLNames.h"
+#include "MIMETypeRegistry.h"
+#include "markup.h"
+#include "PlatformString.h"
+#include "Range.h"
+#include "RenderImage.h"
+#include "StringBuilder.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+// We provide the IE clipboard types (URL and Text), and the clipboard types specified in the WHATWG Web Applications 1.0 draft
+// see http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3
+
+enum ClipboardDataType { ClipboardDataTypeNone, ClipboardDataTypeURL, ClipboardDataTypeText };
+
+static ClipboardDataType clipboardTypeFromMIMEType(const String& type)
+{
+ String cleanType = type.stripWhiteSpace().lower();
+
+ // two special cases for IE compatibility
+ if (cleanType == "text" || cleanType == "text/plain" || cleanType.startsWith("text/plain;"))
+ return ClipboardDataTypeText;
+ if (cleanType == "url" || cleanType == "text/uri-list")
+ return ClipboardDataTypeURL;
+
+ return ClipboardDataTypeNone;
+}
+
+ClipboardChromium::ClipboardChromium(bool isForDragging,
+ PassRefPtr<ChromiumDataObject> dataObject,
+ ClipboardAccessPolicy policy)
+ : Clipboard(policy, isForDragging)
+ , m_dataObject(dataObject)
+{
+}
+
+PassRefPtr<ClipboardChromium> ClipboardChromium::create(bool isForDragging,
+ PassRefPtr<ChromiumDataObject> dataObject, ClipboardAccessPolicy policy)
+{
+ return adoptRef(new ClipboardChromium(isForDragging, dataObject, policy));
+}
+
+void ClipboardChromium::clearData(const String& type)
+{
+ if (policy() != ClipboardWritable || !m_dataObject)
+ return;
+
+ ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
+
+ if (dataType == ClipboardDataTypeURL) {
+ m_dataObject->url = KURL();
+ m_dataObject->urlTitle = "";
+ }
+ if (dataType == ClipboardDataTypeText)
+ m_dataObject->plainText = "";
+}
+
+void ClipboardChromium::clearAllData()
+{
+ if (policy() != ClipboardWritable)
+ return;
+
+ m_dataObject->clear();
+}
+
+String ClipboardChromium::getData(const String& type, bool& success) const
+{
+ success = false;
+ if (policy() != ClipboardReadable || !m_dataObject)
+ return String();
+
+ ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
+ String text;
+ if (dataType == ClipboardDataTypeText) {
+ if (!isForDragging()) {
+ // If this isn't for a drag, it's for a cut/paste event handler.
+ // In this case, we need to check the clipboard.
+ text = ChromiumBridge::clipboardReadPlainText();
+ success = !text.isEmpty();
+ } else if (!m_dataObject->plainText.isEmpty()) {
+ success = true;
+ text = m_dataObject->plainText;
+ }
+ } else if (dataType == ClipboardDataTypeURL) {
+ // FIXME: Handle the cut/paste event. This requires adding a new IPC
+ // message to get the URL from the clipboard directly.
+ if (!m_dataObject->url.isEmpty()) {
+ success = true;
+ text = m_dataObject->url.string();
+ }
+ }
+
+ return text;
+}
+
+bool ClipboardChromium::setData(const String& type, const String& data)
+{
+ if (policy() != ClipboardWritable)
+ return false;
+
+ ClipboardDataType winType = clipboardTypeFromMIMEType(type);
+
+ if (winType == ClipboardDataTypeURL) {
+ m_dataObject->url = KURL(data);
+ return m_dataObject->url.isValid();
+ }
+
+ if (winType == ClipboardDataTypeText) {
+ m_dataObject->plainText = data;
+ return true;
+ }
+ return false;
+}
+
+// extensions beyond IE's API
+HashSet<String> ClipboardChromium::types() const
+{
+ HashSet<String> results;
+ if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
+ return results;
+
+ if (!m_dataObject)
+ return results;
+
+ if (m_dataObject->url.isValid()) {
+ results.add("URL");
+ results.add("text/uri-list");
+ }
+
+ if (!m_dataObject->plainText.isEmpty()) {
+ results.add("Text");
+ results.add("text/plain");
+ }
+
+ return results;
+}
+
+void ClipboardChromium::setDragImage(CachedImage* image, Node* node, const IntPoint& loc)
+{
+ if (policy() != ClipboardImageWritable && policy() != ClipboardWritable)
+ return;
+
+ if (m_dragImage)
+ m_dragImage->removeClient(this);
+ m_dragImage = image;
+ if (m_dragImage)
+ m_dragImage->addClient(this);
+
+ m_dragLoc = loc;
+ m_dragImageElement = node;
+}
+
+void ClipboardChromium::setDragImage(CachedImage* img, const IntPoint& loc)
+{
+ setDragImage(img, 0, loc);
+}
+
+void ClipboardChromium::setDragImageElement(Node* node, const IntPoint& loc)
+{
+ setDragImage(0, node, loc);
+}
+
+DragImageRef ClipboardChromium::createDragImage(IntPoint& loc) const
+{
+ DragImageRef result = 0;
+ if (m_dragImage) {
+ result = createDragImageFromImage(m_dragImage->image());
+ loc = m_dragLoc;
+ }
+ return result;
+}
+
+static String imageToMarkup(const String& url, Element* element)
+{
+ StringBuilder markup;
+ markup.append("<img src=\"");
+ markup.append(url);
+ 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();
+ unsigned length = attrs->length();
+ for (unsigned i = 0; i < length; ++i) {
+ Attribute* attr = attrs->attributeItem(i);
+ if (attr->localName() == "src")
+ continue;
+ markup.append(" ");
+ markup.append(attr->localName());
+ markup.append("=\"");
+ String escapedAttr = attr->value();
+ escapedAttr.replace("\"", "&quot;");
+ markup.append(escapedAttr);
+ markup.append("\"");
+ }
+
+ markup.append("/>");
+ return markup.toString();
+}
+
+static CachedImage* getCachedImage(Element* element)
+{
+ // Attempt to pull CachedImage from element
+ ASSERT(element);
+ RenderObject* renderer = element->renderer();
+ if (!renderer || !renderer->isImage())
+ return 0;
+
+ RenderImage* image = static_cast<RenderImage*>(renderer);
+ if (image->cachedImage() && !image->cachedImage()->errorOccurred())
+ return image->cachedImage();
+
+ return 0;
+}
+
+static void writeImageToDataObject(ChromiumDataObject* dataObject, Element* element,
+ const KURL& url)
+{
+ // Shove image data into a DataObject for use as a file
+ CachedImage* cachedImage = getCachedImage(element);
+ if (!cachedImage || !cachedImage->image() || !cachedImage->isLoaded())
+ return;
+
+ SharedBuffer* imageBuffer = cachedImage->image()->data();
+ if (!imageBuffer || !imageBuffer->size())
+ return;
+
+ dataObject->fileContent = imageBuffer;
+
+ // Determine the filename for the file contents of the image. We try to
+ // use the alt tag if one exists, otherwise we fall back on the suggested
+ // filename in the http header, and finally we resort to using the filename
+ // in the URL.
+ String extension(".");
+ extension += MIMETypeRegistry::getPreferredExtensionForMIMEType(
+ cachedImage->response().mimeType());
+ String title = element->getAttribute(altAttr);
+ if (title.isEmpty()) {
+ title = cachedImage->response().suggestedFilename();
+ // FIXME: If title is empty, get the filename from the URL.
+ }
+ dataObject->fileContentFilename = title + extension;
+}
+
+void ClipboardChromium::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
+{
+ if (!m_dataObject)
+ return;
+
+ m_dataObject->url = url;
+ m_dataObject->urlTitle = title;
+
+ // Write the bytes in the image to the file format.
+ writeImageToDataObject(m_dataObject.get(), element, url);
+
+ AtomicString imageURL = element->getAttribute(srcAttr);
+ if (imageURL.isEmpty())
+ return;
+
+ String fullURL = frame->document()->completeURL(parseURL(imageURL));
+ if (fullURL.isEmpty())
+ return;
+
+ // Put img tag on the clipboard referencing the image
+ m_dataObject->textHtml = imageToMarkup(fullURL, element);
+}
+
+void ClipboardChromium::writeURL(const KURL& url, const String& title, Frame*)
+{
+ if (!m_dataObject)
+ return;
+ m_dataObject->url = url;
+ m_dataObject->urlTitle = title;
+
+ // The URL can also be used as plain text.
+ m_dataObject->plainText = url.string();
+
+ // The URL can also be used as an HTML fragment.
+ m_dataObject->textHtml = urlToMarkup(url, title);
+ m_dataObject->htmlBaseUrl = url;
+}
+
+void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
+{
+ ASSERT(selectedRange);
+ if (!m_dataObject)
+ return;
+
+ m_dataObject->textHtml = createMarkup(selectedRange, 0,
+ AnnotateForInterchange);
+ m_dataObject->htmlBaseUrl = frame->document()->url();
+
+ String str = frame->selectedText();
+#if PLATFORM(WIN_OS)
+ replaceNewlinesWithWindowsStyleNewlines(str);
+#endif
+ replaceNBSPWithSpace(str);
+ m_dataObject->plainText = str;
+}
+
+bool ClipboardChromium::hasData()
+{
+ if (!m_dataObject)
+ return false;
+
+ return m_dataObject->hasData();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/ClipboardChromium.h b/WebCore/platform/chromium/ClipboardChromium.h
new file mode 100644
index 0000000..1864c1a
--- /dev/null
+++ b/WebCore/platform/chromium/ClipboardChromium.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef ClipboardChromium_h
+#define ClipboardChromium_h
+
+#include "Clipboard.h"
+
+#include "CachedResourceClient.h"
+
+namespace WebCore {
+
+ class CachedImage;
+ class ChromiumDataObject;
+ class IntPoint;
+
+ class ClipboardChromium : public Clipboard, public CachedResourceClient {
+ public:
+ ~ClipboardChromium() {}
+
+ static PassRefPtr<ClipboardChromium> create(
+ bool isForDragging, PassRefPtr<ChromiumDataObject>, ClipboardAccessPolicy);
+
+ virtual void clearData(const String& type);
+ void clearAllData();
+ String getData(const String& type, bool& success) const;
+ bool setData(const String& type, const String& data);
+
+ // extensions beyond IE's API
+ HashSet<String> types() const;
+
+ void setDragImage(CachedImage*, const IntPoint&);
+ void setDragImageElement(Node*, const IntPoint&);
+
+ PassRefPtr<ChromiumDataObject> dataObject()
+ {
+ return m_dataObject;
+ }
+
+ virtual DragImageRef createDragImage(IntPoint& dragLoc) const;
+ virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*);
+ virtual void writeURL(const KURL&, const String&, Frame*);
+ virtual void writeRange(Range*, Frame*);
+
+ virtual bool hasData();
+
+ private:
+ ClipboardChromium(bool, PassRefPtr<ChromiumDataObject>, ClipboardAccessPolicy);
+
+ void resetFromClipboard();
+ void setDragImage(CachedImage*, Node*, const IntPoint&);
+ RefPtr<ChromiumDataObject> m_dataObject;
+ Frame* m_frame;
+ };
+
+} // namespace WebCore
+
+#endif // ClipboardChromium_h
diff --git a/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp b/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp
new file mode 100644
index 0000000..7efcb3c
--- /dev/null
+++ b/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp
@@ -0,0 +1,67 @@
+/*
+ * 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 "config.h"
+#include "ClipboardUtilitiesChromium.h"
+
+#include "KURL.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+#if PLATFORM(WIN_OS)
+void replaceNewlinesWithWindowsStyleNewlines(String& str)
+{
+ static const UChar Newline = '\n';
+ static const char* const WindowsNewline("\r\n");
+ str.replace(Newline, WindowsNewline);
+}
+#endif
+
+void replaceNBSPWithSpace(String& str)
+{
+ static const UChar NonBreakingSpaceCharacter = 0xA0;
+ static const UChar SpaceCharacter = ' ';
+ str.replace(NonBreakingSpaceCharacter, SpaceCharacter);
+}
+
+String urlToMarkup(const KURL& url, const String& title)
+{
+ String markup("<a href=\"");
+ markup.append(url.string());
+ markup.append("\">");
+ // FIXME: HTML escape this, possibly by moving into the glue layer so we
+ // can use net/base/escape.h.
+ markup.append(title);
+ markup.append("</a>");
+ return markup;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/ClipboardUtilitiesChromium.h b/WebCore/platform/chromium/ClipboardUtilitiesChromium.h
new file mode 100644
index 0000000..c597089
--- /dev/null
+++ b/WebCore/platform/chromium/ClipboardUtilitiesChromium.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+namespace WebCore {
+
+class KURL;
+class String;
+
+#if PLATFORM(WIN_OS)
+void replaceNewlinesWithWindowsStyleNewlines(String&);
+#endif
+void replaceNBSPWithSpace(String&);
+
+String urlToMarkup(const KURL&, const String&);
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/ContextMenuChromium.cpp b/WebCore/platform/chromium/ContextMenuChromium.cpp
new file mode 100644
index 0000000..0614e3e
--- /dev/null
+++ b/WebCore/platform/chromium/ContextMenuChromium.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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 "config.h"
+#include "ContextMenu.h"
+
+namespace WebCore {
+
+// This is a stub implementation of WebKit's ContextMenu class that does
+// nothing.
+
+ContextMenu::ContextMenu(const HitTestResult& result)
+ : m_hitTestResult(result)
+ , m_platformDescription(0)
+{
+}
+
+ContextMenu::ContextMenu(const HitTestResult& result, const PlatformMenuDescription menu)
+ : m_hitTestResult(result)
+ , m_platformDescription(0)
+{
+}
+
+ContextMenu::~ContextMenu()
+{
+}
+
+unsigned ContextMenu::itemCount() const
+{
+ return 0;
+}
+
+void ContextMenu::insertItem(unsigned position, ContextMenuItem& item)
+{
+}
+
+void ContextMenu::appendItem(ContextMenuItem& item)
+{
+}
+
+ContextMenuItem* ContextMenu::itemWithAction(unsigned action)
+{
+ return 0;
+}
+
+ContextMenuItem* ContextMenu::itemAtIndex(unsigned index, const PlatformMenuDescription platformDescription)
+{
+ return 0;
+}
+
+void ContextMenu::setPlatformDescription(PlatformMenuDescription menu)
+{
+}
+
+PlatformMenuDescription ContextMenu::platformDescription() const
+{
+ return m_platformDescription;
+}
+
+PlatformMenuDescription ContextMenu::releasePlatformDescription()
+{
+ return 0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/ContextMenuItemChromium.cpp b/WebCore/platform/chromium/ContextMenuItemChromium.cpp
new file mode 100644
index 0000000..f34ea23
--- /dev/null
+++ b/WebCore/platform/chromium/ContextMenuItemChromium.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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 "config.h"
+#include "ContextMenuItem.h"
+
+namespace WebCore {
+
+// This is a stub implementation of WebKit's ContextMenu class that does
+// nothing.
+
+ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item)
+{
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenu* subMenu)
+{
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
+{
+}
+
+ContextMenuItem::~ContextMenuItem()
+{
+}
+
+PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
+{
+ return PlatformMenuItemDescription();
+}
+
+ContextMenuItemType ContextMenuItem::type() const
+{
+ return ContextMenuItemType();
+}
+
+ContextMenuAction ContextMenuItem::action() const
+{
+ return ContextMenuAction();
+}
+
+String ContextMenuItem::title() const
+{
+ return String();
+}
+
+PlatformMenuDescription ContextMenuItem::platformSubMenu() const
+{
+ return PlatformMenuDescription();
+}
+
+void ContextMenuItem::setType(ContextMenuItemType type)
+{
+}
+
+void ContextMenuItem::setAction(ContextMenuAction action)
+{
+}
+
+void ContextMenuItem::setTitle(const String& title)
+{
+}
+
+void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
+{
+}
+
+void ContextMenuItem::setChecked(bool checked)
+{
+}
+
+void ContextMenuItem::setEnabled(bool enabled)
+{
+}
+
+bool ContextMenuItem::enabled() const
+{
+ return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/CursorChromium.cpp b/WebCore/platform/chromium/CursorChromium.cpp
new file mode 100644
index 0000000..16fa634
--- /dev/null
+++ b/WebCore/platform/chromium/CursorChromium.cpp
@@ -0,0 +1,317 @@
+/*
+ * 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 "config.h"
+#include "Cursor.h"
+
+namespace WebCore {
+
+Cursor::Cursor(const Cursor& other)
+ : m_impl(other.m_impl)
+{
+}
+
+Cursor::Cursor(Image* image, const IntPoint& hotSpot)
+ : m_impl(image, hotSpot)
+{
+}
+
+Cursor::~Cursor()
+{
+}
+
+Cursor& Cursor::operator=(const Cursor& other)
+{
+ m_impl = other.m_impl;
+ return *this;
+}
+
+Cursor::Cursor(PlatformCursor c)
+ : m_impl(c)
+{
+}
+
+const Cursor& pointerCursor()
+{
+ static const Cursor c(PlatformCursor::TypePointer);
+ return c;
+}
+
+const Cursor& crossCursor()
+{
+ static const Cursor c(PlatformCursor::TypeCross);
+ return c;
+}
+
+const Cursor& handCursor()
+{
+ static const Cursor c(PlatformCursor::TypeHand);
+ return c;
+}
+
+const Cursor& iBeamCursor()
+{
+ static const Cursor c(PlatformCursor::TypeIBeam);
+ return c;
+}
+
+const Cursor& waitCursor()
+{
+ static const Cursor c(PlatformCursor::TypeWait);
+ return c;
+}
+
+const Cursor& helpCursor()
+{
+ static const Cursor c(PlatformCursor::TypeHelp);
+ return c;
+}
+
+const Cursor& eastResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeEastResize);
+ return c;
+}
+
+const Cursor& northResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNorthResize);
+ return c;
+}
+
+const Cursor& northEastResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNorthEastResize);
+ return c;
+}
+
+const Cursor& northWestResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNorthWestResize);
+ return c;
+}
+
+const Cursor& southResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeSouthResize);
+ return c;
+}
+
+const Cursor& southEastResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeSouthEastResize);
+ return c;
+}
+
+const Cursor& southWestResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeSouthWestResize);
+ return c;
+}
+
+const Cursor& westResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeWestResize);
+ return c;
+}
+
+const Cursor& northSouthResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNorthSouthResize);
+ return c;
+}
+
+const Cursor& eastWestResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeEastWestResize);
+ return c;
+}
+
+const Cursor& northEastSouthWestResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNorthEastSouthWestResize);
+ return c;
+}
+
+const Cursor& northWestSouthEastResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNorthWestSouthEastResize);
+ return c;
+}
+
+const Cursor& columnResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeColumnResize);
+ return c;
+}
+
+const Cursor& rowResizeCursor()
+{
+ static const Cursor c(PlatformCursor::TypeRowResize);
+ return c;
+}
+
+const Cursor& middlePanningCursor()
+{
+ static const Cursor c(PlatformCursor::TypeMiddlePanning);
+ return c;
+}
+
+const Cursor& eastPanningCursor()
+{
+ static const Cursor c(PlatformCursor::TypeEastPanning);
+ return c;
+}
+
+const Cursor& northPanningCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNorthPanning);
+ return c;
+}
+
+const Cursor& northEastPanningCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNorthEastPanning);
+ return c;
+}
+
+const Cursor& northWestPanningCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNorthWestPanning);
+ return c;
+}
+
+const Cursor& southPanningCursor()
+{
+ static const Cursor c(PlatformCursor::TypeSouthPanning);
+ return c;
+}
+
+const Cursor& southEastPanningCursor()
+{
+ static const Cursor c(PlatformCursor::TypeSouthEastPanning);
+ return c;
+}
+
+const Cursor& southWestPanningCursor()
+{
+ static const Cursor c(PlatformCursor::TypeSouthWestPanning);
+ return c;
+}
+
+const Cursor& westPanningCursor()
+{
+ static const Cursor c(PlatformCursor::TypeWestPanning);
+ return c;
+}
+
+const Cursor& moveCursor()
+{
+ static const Cursor c(PlatformCursor::TypeMove);
+ return c;
+}
+
+const Cursor& verticalTextCursor()
+{
+ static const Cursor c(PlatformCursor::TypeVerticalText);
+ return c;
+}
+
+const Cursor& cellCursor()
+{
+ static const Cursor c(PlatformCursor::TypeCell);
+ return c;
+}
+
+const Cursor& contextMenuCursor()
+{
+ static const Cursor c(PlatformCursor::TypeContextMenu);
+ return c;
+}
+
+const Cursor& aliasCursor()
+{
+ static const Cursor c(PlatformCursor::TypeAlias);
+ return c;
+}
+
+const Cursor& progressCursor()
+{
+ static const Cursor c(PlatformCursor::TypeProgress);
+ return c;
+}
+
+const Cursor& noDropCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNoDrop);
+ return c;
+}
+
+const Cursor& copyCursor()
+{
+ static const Cursor c(PlatformCursor::TypeCopy);
+ return c;
+}
+
+const Cursor& noneCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNone);
+ return c;
+}
+
+const Cursor& notAllowedCursor()
+{
+ static const Cursor c(PlatformCursor::TypeNotAllowed);
+ return c;
+}
+
+const Cursor& zoomInCursor()
+{
+ static const Cursor c(PlatformCursor::TypeZoomIn);
+ return c;
+}
+
+const Cursor& zoomOutCursor()
+{
+ static const Cursor c(PlatformCursor::TypeZoomOut);
+ return c;
+}
+
+const Cursor& grabCursor()
+{
+ return pointerCursor();
+}
+
+const Cursor& grabbingCursor()
+{
+ return pointerCursor();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/DragDataChromium.cpp b/WebCore/platform/chromium/DragDataChromium.cpp
new file mode 100644
index 0000000..eaec025
--- /dev/null
+++ b/WebCore/platform/chromium/DragDataChromium.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * 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.
+ */
+
+// Modified from DragDataWin.cpp to not directly call any windows methods as
+// they may not be available to us in the multiprocess
+
+#include "config.h"
+#include "DragData.h"
+
+#include "ChromiumDataObject.h"
+#include "Clipboard.h"
+#include "ClipboardChromium.h"
+#include "DocumentFragment.h"
+#include "KURL.h"
+#include "markup.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+static bool containsHTML(const ChromiumDataObject* dropData)
+{
+ return dropData->textHtml.length() > 0;
+}
+
+PassRefPtr<Clipboard> DragData::createClipboard(ClipboardAccessPolicy policy) const
+{
+ RefPtr<ClipboardChromium> clipboard = ClipboardChromium::create(true,
+ m_platformDragData, policy);
+
+ return clipboard.release();
+}
+
+bool DragData::containsURL() const
+{
+ return m_platformDragData->url.isValid();
+}
+
+String DragData::asURL(String* title) const
+{
+ if (!m_platformDragData->url.isValid())
+ return String();
+
+ // |title| can be NULL
+ if (title)
+ *title = m_platformDragData->urlTitle;
+ return m_platformDragData->url.string();
+}
+
+bool DragData::containsFiles() const
+{
+ return !m_platformDragData->filenames.isEmpty();
+}
+
+void DragData::asFilenames(Vector<String>& result) const
+{
+ for (size_t i = 0; i < m_platformDragData->filenames.size(); ++i)
+ result.append(m_platformDragData->filenames[i]);
+}
+
+bool DragData::containsPlainText() const
+{
+ return !m_platformDragData->plainText.isEmpty();
+}
+
+String DragData::asPlainText() const
+{
+ return m_platformDragData->plainText;
+}
+
+bool DragData::containsColor() const
+{
+ notImplemented();
+ return false;
+}
+
+bool DragData::canSmartReplace() const
+{
+ // Mimic the situations in which mac allows drag&drop to do a smart replace.
+ // This is allowed whenever the drag data contains a 'range' (ie.,
+ // ClipboardWin::writeRange is called). For example, dragging a link
+ // should not result in a space being added.
+ return !m_platformDragData->plainText.isEmpty()
+ && !m_platformDragData->url.isValid();
+}
+
+bool DragData::containsCompatibleContent() const
+{
+ return containsPlainText()
+ || containsURL()
+ || containsHTML(m_platformDragData)
+ || containsColor();
+}
+
+PassRefPtr<DocumentFragment> DragData::asFragment(Document* doc) const
+{
+ /*
+ * Order is richest format first. On OSX this is:
+ * * Web Archive
+ * * Filenames
+ * * HTML
+ * * RTF
+ * * TIFF
+ * * PICT
+ */
+
+ if (containsFiles()) {
+ // FIXME: Implement this. Should be pretty simple to make some HTML
+ // and call createFragmentFromMarkup.
+ //if (RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(doc,
+ // ?, KURL()))
+ // return fragment;
+ }
+
+ if (!m_platformDragData->textHtml.isEmpty()) {
+ RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(doc,
+ m_platformDragData->textHtml, m_platformDragData->htmlBaseUrl);
+ return fragment.release();
+ }
+
+ return 0;
+}
+
+Color DragData::asColor() const
+{
+ notImplemented();
+ return Color();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/DragDataRef.h b/WebCore/platform/chromium/DragDataRef.h
new file mode 100644
index 0000000..de1fa1c
--- /dev/null
+++ b/WebCore/platform/chromium/DragDataRef.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#ifndef DragDataRef_h
+#define DragDataRef_h
+
+#include "ChromiumDataObject.h"
+
+namespace WebCore {
+
+ typedef ChromiumDataObject* DragDataRef;
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/DragImageChromium.cpp b/WebCore/platform/chromium/DragImageChromium.cpp
new file mode 100644
index 0000000..8c1484e
--- /dev/null
+++ b/WebCore/platform/chromium/DragImageChromium.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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 "config.h"
+#include "DragImage.h"
+
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+IntSize dragImageSize(DragImageRef image)
+{
+ notImplemented();
+ return IntSize();
+}
+
+void deleteDragImage(DragImageRef image)
+{
+ notImplemented();
+}
+
+DragImageRef scaleDragImage(DragImageRef image, FloatSize scale)
+{
+ notImplemented();
+ return 0;
+}
+
+DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
+{
+ notImplemented();
+ return image;
+}
+
+DragImageRef createDragImageFromImage(Image* img)
+{
+ notImplemented();
+ return 0;
+}
+
+DragImageRef createDragImageIconForCachedImage(CachedImage*)
+{
+ notImplemented();
+ return 0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/DragImageRef.h b/WebCore/platform/chromium/DragImageRef.h
new file mode 100644
index 0000000..53edd4f
--- /dev/null
+++ b/WebCore/platform/chromium/DragImageRef.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef DragImageRef_h
+#define DragImageRef_h
+
+namespace WebCore {
+
+ // FIXME: Need to support image drag-n-drop. For now, we just allow things
+ // to compile by defining this dummy type.
+ typedef void* DragImageRef;
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/DeprecatedPtrQueue.h b/WebCore/platform/chromium/FileChooserChromium.cpp
index 226cb18..7603e92 100644
--- a/WebCore/platform/DeprecatedPtrQueue.h
+++ b/WebCore/platform/chromium/FileChooserChromium.cpp
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,27 +24,27 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef DeprecatedPtrQueue_h
-#define DeprecatedPtrQueue_h
+#include "config.h"
+#include "FileChooser.h"
-#include "DeprecatedPtrList.h"
+#include "FileSystem.h"
+#include "LocalizedStrings.h"
+#include "StringTruncator.h"
namespace WebCore {
-template<class T> class DeprecatedPtrQueue
+String FileChooser::basenameForWidth(const Font& font, int width) const
{
-public:
- bool isEmpty() const { return list.isEmpty(); }
- T *dequeue() { T *tmp = list.getFirst(); list.removeFirst(); return tmp; }
- void enqueue(const T *item) { list.append (item); }
- unsigned count() const { return list.count(); }
- T *head() const { return list.getFirst(); }
- DeprecatedPtrQueue<T> &operator=(const DeprecatedPtrQueue<T> &q) { list = q.list; return *this; }
+ if (width <= 0)
+ return String();
- private:
- DeprecatedPtrList<T> list;
-};
+ String string;
+ if (!m_filenames.size())
+ string = fileButtonNoFileSelectedLabel();
+ else
+ string = pathGetFileName(m_filenames[0]);
+ return StringTruncator::centerTruncate(string, static_cast<float>(width), font, false);
}
-#endif /* DeprecatedPtrQueue_h */
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/FileSystemChromium.cpp b/WebCore/platform/chromium/FileSystemChromium.cpp
new file mode 100644
index 0000000..afa0c27
--- /dev/null
+++ b/WebCore/platform/chromium/FileSystemChromium.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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 "config.h"
+#include "FileSystem.h"
+
+#include "NotImplemented.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+bool deleteFile(const String&)
+{
+ notImplemented();
+ return false;
+}
+
+bool deleteEmptyDirectory(const String&)
+{
+ notImplemented();
+ return false;
+}
+
+bool getFileSize(const String&, long long& result)
+{
+ notImplemented();
+ return false;
+}
+
+bool getFileModificationTime(const String&, time_t& result)
+{
+ notImplemented();
+ return false;
+}
+
+String directoryName(const String&)
+{
+ notImplemented();
+ return String();
+}
+
+String pathByAppendingComponent(const String& path, const String& component)
+{
+ notImplemented();
+ return String();
+}
+
+bool makeAllDirectories(const String& path)
+{
+ notImplemented();
+ return false;
+}
+
+bool fileExists(const String&)
+{
+ notImplemented();
+ return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/FileSystemChromiumLinux.cpp b/WebCore/platform/chromium/FileSystemChromiumLinux.cpp
new file mode 100644
index 0000000..e388dee
--- /dev/null
+++ b/WebCore/platform/chromium/FileSystemChromiumLinux.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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 "config.h"
+#include "FileSystem.h"
+
+namespace WebCore {
+
+String pathGetFileName(const String& path)
+{
+ return path.substring(path.reverseFind('/') + 1);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/FileSystemChromiumMac.mm b/WebCore/platform/chromium/FileSystemChromiumMac.mm
new file mode 100644
index 0000000..7e880e1
--- /dev/null
+++ b/WebCore/platform/chromium/FileSystemChromiumMac.mm
@@ -0,0 +1,44 @@
+/*
+ * 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 "config.h"
+#include "FileSystem.h"
+
+#import <Foundation/NSFileManager.h>
+#include "PlatformString.h"
+
+namespace WebCore {
+
+String pathGetFileName(const String& path)
+{
+ return [[NSFileManager defaultManager] displayNameAtPath:path];
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/FileSystemChromiumWin.cpp b/WebCore/platform/chromium/FileSystemChromiumWin.cpp
new file mode 100644
index 0000000..704c39a
--- /dev/null
+++ b/WebCore/platform/chromium/FileSystemChromiumWin.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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 "config.h"
+#include "FileSystem.h"
+
+#include <windows.h>
+#include <shlwapi.h>
+
+namespace WebCore {
+
+String pathGetFileName(const String& path)
+{
+ return String(PathFindFileName(String(path).charactersWithNullTermination()));
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/FramelessScrollView.cpp b/WebCore/platform/chromium/FramelessScrollView.cpp
new file mode 100644
index 0000000..114eabb
--- /dev/null
+++ b/WebCore/platform/chromium/FramelessScrollView.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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 "config.h"
+#include "FramelessScrollView.h"
+
+#include "FramelessScrollViewClient.h"
+
+namespace WebCore {
+
+FramelessScrollView::~FramelessScrollView()
+{
+ // Remove native scrollbars now before we lose the connection to the HostWindow.
+ setHasHorizontalScrollbar(false);
+ setHasVerticalScrollbar(false);
+}
+
+void FramelessScrollView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
+{
+ // Add in our offset within the ScrollView.
+ IntRect dirtyRect = rect;
+ dirtyRect.move(scrollbar->x(), scrollbar->y());
+ invalidateRect(dirtyRect);
+}
+
+bool FramelessScrollView::isActive() const
+{
+ // FIXME
+ return true;
+}
+
+void FramelessScrollView::invalidateRect(const IntRect& rect)
+{
+ if (HostWindow* h = hostWindow())
+ h->repaint(rect, true);
+}
+
+HostWindow* FramelessScrollView::hostWindow() const
+{
+ return const_cast<FramelessScrollViewClient*>(m_client);
+}
+
+IntRect FramelessScrollView::windowClipRect(bool clipToContents) const
+{
+ return contentsToWindow(visibleContentRect(!clipToContents));
+}
+
+void FramelessScrollView::paintContents(GraphicsContext*, const IntRect& damageRect)
+{
+}
+
+void FramelessScrollView::contentsResized()
+{
+}
+
+void FramelessScrollView::visibleContentsResized()
+{
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/FramelessScrollView.h b/WebCore/platform/chromium/FramelessScrollView.h
new file mode 100644
index 0000000..300f418
--- /dev/null
+++ b/WebCore/platform/chromium/FramelessScrollView.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#ifndef FramelessScrollView_h
+#define FramelessScrollView_h
+
+#include "ScrollView.h"
+
+namespace WebCore {
+
+ class FramelessScrollViewClient;
+ class PlatformKeyboardEvent;
+ class PlatformMouseEvent;
+ class PlatformWheelEvent;
+
+ // A FramelessScrollView is a ScrollView that can be used to render custom
+ // content, which does not have an associated Frame.
+ //
+ // NOTE: It may be better to just develop a custom subclass of Widget that
+ // can have scroll bars for this instead of trying to reuse ScrollView.
+ //
+ class FramelessScrollView : public ScrollView {
+ public:
+ FramelessScrollView() : m_client(0) {}
+ ~FramelessScrollView();
+
+ FramelessScrollViewClient* client() const { return m_client; }
+ void setClient(FramelessScrollViewClient* client) { m_client = client; }
+
+ // Event handlers that subclasses must implement.
+ virtual bool handleMouseDownEvent(const PlatformMouseEvent&) = 0;
+ virtual bool handleMouseMoveEvent(const PlatformMouseEvent&) = 0;
+ virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&) = 0;
+ virtual bool handleWheelEvent(const PlatformWheelEvent&) = 0;
+ virtual bool handleKeyEvent(const PlatformKeyboardEvent&) = 0;
+
+ // ScrollbarClient public methods:
+ virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
+ virtual bool isActive() const;
+
+ // Widget public methods:
+ virtual void invalidateRect(const IntRect&);
+
+ // ScrollView public methods:
+ virtual HostWindow* hostWindow() const;
+ virtual IntRect windowClipRect(bool clipToContents = true) const;
+
+ protected:
+ // ScrollView protected methods:
+ virtual void paintContents(GraphicsContext*, const IntRect& damageRect);
+ virtual void contentsResized();
+ virtual void visibleContentsResized();
+
+ private:
+ FramelessScrollViewClient* m_client;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/FramelessScrollViewClient.h b/WebCore/platform/chromium/FramelessScrollViewClient.h
new file mode 100644
index 0000000..4b32a43
--- /dev/null
+++ b/WebCore/platform/chromium/FramelessScrollViewClient.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef FramelessScrollViewClient_h
+#define FramelessScrollViewClient_h
+
+#include "HostWindow.h"
+
+namespace WebCore {
+
+ class FramelessScrollViewClient : public HostWindow {
+ public:
+ virtual void popupClosed(FramelessScrollView* popup_view) = 0;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/KeyCodeConversion.h b/WebCore/platform/chromium/KeyCodeConversion.h
new file mode 100644
index 0000000..8bd0b46
--- /dev/null
+++ b/WebCore/platform/chromium/KeyCodeConversion.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef KeyCodeConversion_h
+#define KeyCodeConversion_h
+
+namespace WebCore {
+
+ int windowsKeyCodeForKeyEvent(unsigned keycode);
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/KeyCodeConversionGtk.cpp b/WebCore/platform/chromium/KeyCodeConversionGtk.cpp
new file mode 100644
index 0000000..a3efe44
--- /dev/null
+++ b/WebCore/platform/chromium/KeyCodeConversionGtk.cpp
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * 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.
+ */
+
+// windowsKeyCodeForKeyEvent is copied from platform/gtk/KeyEventGtk.cpp
+
+#include "config.h"
+#include "KeyCodeConversion.h"
+
+#include "KeyboardCodes.h"
+
+#include <gdk/gdkkeysyms.h>
+
+namespace WebCore {
+
+int windowsKeyCodeForKeyEvent(unsigned keycode)
+{
+ switch (keycode) {
+ case GDK_KP_0:
+ return VKEY_NUMPAD0; // (60) Numeric keypad 0 key
+ case GDK_KP_1:
+ return VKEY_NUMPAD1; // (61) Numeric keypad 1 key
+ case GDK_KP_2:
+ return VKEY_NUMPAD2; // (62) Numeric keypad 2 key
+ case GDK_KP_3:
+ return VKEY_NUMPAD3; // (63) Numeric keypad 3 key
+ case GDK_KP_4:
+ return VKEY_NUMPAD4; // (64) Numeric keypad 4 key
+ case GDK_KP_5:
+ return VKEY_NUMPAD5; //(65) Numeric keypad 5 key
+ case GDK_KP_6:
+ return VKEY_NUMPAD6; // (66) Numeric keypad 6 key
+ case GDK_KP_7:
+ return VKEY_NUMPAD7; // (67) Numeric keypad 7 key
+ case GDK_KP_8:
+ return VKEY_NUMPAD8; // (68) Numeric keypad 8 key
+ case GDK_KP_9:
+ return VKEY_NUMPAD9; // (69) Numeric keypad 9 key
+ case GDK_KP_Multiply:
+ return VKEY_MULTIPLY; // (6A) Multiply key
+ case GDK_KP_Add:
+ return VKEY_ADD; // (6B) Add key
+ case GDK_KP_Subtract:
+ return VKEY_SUBTRACT; // (6D) Subtract key
+ case GDK_KP_Decimal:
+ return VKEY_DECIMAL; // (6E) Decimal key
+ case GDK_KP_Divide:
+ return VKEY_DIVIDE; // (6F) Divide key
+
+ case GDK_BackSpace:
+ return VKEY_BACK; // (08) BACKSPACE key
+ case GDK_ISO_Left_Tab:
+ case GDK_3270_BackTab:
+ case GDK_Tab:
+ return VKEY_TAB; // (09) TAB key
+ case GDK_Clear:
+ return VKEY_CLEAR; // (0C) CLEAR key
+ case GDK_ISO_Enter:
+ case GDK_KP_Enter:
+ case GDK_Return:
+ return VKEY_RETURN; //(0D) Return key
+ case GDK_Shift_L:
+ case GDK_Shift_R:
+ return VKEY_SHIFT; // (10) SHIFT key
+ case GDK_Control_L:
+ case GDK_Control_R:
+ return VKEY_CONTROL; // (11) CTRL key
+ case GDK_Menu:
+ case GDK_Alt_L:
+ case GDK_Alt_R:
+ return VKEY_MENU; // (12) ALT key
+
+ case GDK_Pause:
+ return VKEY_PAUSE; // (13) PAUSE key
+ case GDK_Caps_Lock:
+ return VKEY_CAPITAL; // (14) CAPS LOCK key
+ case GDK_Kana_Lock:
+ case GDK_Kana_Shift:
+ return VKEY_KANA; // (15) Input Method Editor (IME) Kana mode
+ case GDK_Hangul:
+ return VKEY_HANGUL; // VKEY_HANGUL (15) IME Hangul mode
+ // VKEY_JUNJA (17) IME Junja mode
+ // VKEY_FINAL (18) IME final mode
+ case GDK_Hangul_Hanja:
+ return VKEY_HANJA; // (19) IME Hanja mode
+ case GDK_Kanji:
+ return VKEY_KANJI; // (19) IME Kanji mode
+ case GDK_Escape:
+ return VKEY_ESCAPE; // (1B) ESC key
+ // VKEY_CONVERT (1C) IME convert
+ // VKEY_NONCONVERT (1D) IME nonconvert
+ // VKEY_ACCEPT (1E) IME accept
+ // VKEY_MODECHANGE (1F) IME mode change request
+ case GDK_space:
+ return VKEY_SPACE; // (20) SPACEBAR
+ case GDK_Page_Up:
+ return VKEY_PRIOR; // (21) PAGE UP key
+ case GDK_Page_Down:
+ return VKEY_NEXT; // (22) PAGE DOWN key
+ case GDK_End:
+ return VKEY_END; // (23) END key
+ case GDK_Home:
+ return VKEY_HOME; // (24) HOME key
+ case GDK_Left:
+ return VKEY_LEFT; // (25) LEFT ARROW key
+ case GDK_Up:
+ return VKEY_UP; // (26) UP ARROW key
+ case GDK_Right:
+ return VKEY_RIGHT; // (27) RIGHT ARROW key
+ case GDK_Down:
+ return VKEY_DOWN; // (28) DOWN ARROW key
+ case GDK_Select:
+ return VKEY_SELECT; // (29) SELECT key
+ case GDK_Print:
+ return VKEY_PRINT; // (2A) PRINT key
+ case GDK_Execute:
+ return VKEY_EXECUTE;// (2B) EXECUTE key
+ //dunno on this
+ //case GDK_PrintScreen:
+ // return VKEY_SNAPSHOT; // (2C) PRINT SCREEN key
+ case GDK_Insert:
+ return VKEY_INSERT; // (2D) INS key
+ case GDK_Delete:
+ return VKEY_DELETE; // (2E) DEL key
+ case GDK_Help:
+ return VKEY_HELP; // (2F) HELP key
+ case GDK_0:
+ case GDK_parenleft:
+ return VKEY_0; // (30) 0) key
+ case GDK_1:
+ return VKEY_1; // (31) 1 ! key
+ case GDK_2:
+ case GDK_at:
+ return VKEY_2; // (32) 2 & key
+ case GDK_3:
+ case GDK_numbersign:
+ return VKEY_3; //case '3': case '#';
+ case GDK_4:
+ case GDK_dollar: // (34) 4 key '$';
+ return VKEY_4;
+ case GDK_5:
+ case GDK_percent:
+ return VKEY_5; // (35) 5 key '%'
+ case GDK_6:
+ case GDK_asciicircum:
+ return VKEY_6; // (36) 6 key '^'
+ case GDK_7:
+ case GDK_ampersand:
+ return VKEY_7; // (37) 7 key case '&'
+ case GDK_8:
+ case GDK_asterisk:
+ return VKEY_8; // (38) 8 key '*'
+ case GDK_9:
+ case GDK_parenright:
+ return VKEY_9; // (39) 9 key '('
+ case GDK_a:
+ case GDK_A:
+ return VKEY_A; // (41) A key case 'a': case 'A': return 0x41;
+ case GDK_b:
+ case GDK_B:
+ return VKEY_B; // (42) B key case 'b': case 'B': return 0x42;
+ case GDK_c:
+ case GDK_C:
+ return VKEY_C; // (43) C key case 'c': case 'C': return 0x43;
+ case GDK_d:
+ case GDK_D:
+ return VKEY_D; // (44) D key case 'd': case 'D': return 0x44;
+ case GDK_e:
+ case GDK_E:
+ return VKEY_E; // (45) E key case 'e': case 'E': return 0x45;
+ case GDK_f:
+ case GDK_F:
+ return VKEY_F; // (46) F key case 'f': case 'F': return 0x46;
+ case GDK_g:
+ case GDK_G:
+ return VKEY_G; // (47) G key case 'g': case 'G': return 0x47;
+ case GDK_h:
+ case GDK_H:
+ return VKEY_H; // (48) H key case 'h': case 'H': return 0x48;
+ case GDK_i:
+ case GDK_I:
+ return VKEY_I; // (49) I key case 'i': case 'I': return 0x49;
+ case GDK_j:
+ case GDK_J:
+ return VKEY_J; // (4A) J key case 'j': case 'J': return 0x4A;
+ case GDK_k:
+ case GDK_K:
+ return VKEY_K; // (4B) K key case 'k': case 'K': return 0x4B;
+ case GDK_l:
+ case GDK_L:
+ return VKEY_L; // (4C) L key case 'l': case 'L': return 0x4C;
+ case GDK_m:
+ case GDK_M:
+ return VKEY_M; // (4D) M key case 'm': case 'M': return 0x4D;
+ case GDK_n:
+ case GDK_N:
+ return VKEY_N; // (4E) N key case 'n': case 'N': return 0x4E;
+ case GDK_o:
+ case GDK_O:
+ return VKEY_O; // (4F) O key case 'o': case 'O': return 0x4F;
+ case GDK_p:
+ case GDK_P:
+ return VKEY_P; // (50) P key case 'p': case 'P': return 0x50;
+ case GDK_q:
+ case GDK_Q:
+ return VKEY_Q; // (51) Q key case 'q': case 'Q': return 0x51;
+ case GDK_r:
+ case GDK_R:
+ return VKEY_R; // (52) R key case 'r': case 'R': return 0x52;
+ case GDK_s:
+ case GDK_S:
+ return VKEY_S; // (53) S key case 's': case 'S': return 0x53;
+ case GDK_t:
+ case GDK_T:
+ return VKEY_T; // (54) T key case 't': case 'T': return 0x54;
+ case GDK_u:
+ case GDK_U:
+ return VKEY_U; // (55) U key case 'u': case 'U': return 0x55;
+ case GDK_v:
+ case GDK_V:
+ return VKEY_V; // (56) V key case 'v': case 'V': return 0x56;
+ case GDK_w:
+ case GDK_W:
+ return VKEY_W; // (57) W key case 'w': case 'W': return 0x57;
+ case GDK_x:
+ case GDK_X:
+ return VKEY_X; // (58) X key case 'x': case 'X': return 0x58;
+ case GDK_y:
+ case GDK_Y:
+ return VKEY_Y; // (59) Y key case 'y': case 'Y': return 0x59;
+ case GDK_z:
+ case GDK_Z:
+ return VKEY_Z; // (5A) Z key case 'z': case 'Z': return 0x5A;
+ case GDK_Meta_L:
+ return VKEY_LWIN; // (5B) Left Windows key (Microsoft Natural keyboard)
+ case GDK_Meta_R:
+ return VKEY_RWIN; // (5C) Right Windows key (Natural keyboard)
+ // VKEY_APPS (5D) Applications key (Natural keyboard)
+ // VKEY_SLEEP (5F) Computer Sleep key
+ // VKEY_SEPARATOR (6C) Separator key
+ // VKEY_SUBTRACT (6D) Subtract key
+ // VKEY_DECIMAL (6E) Decimal key
+ // VKEY_DIVIDE (6F) Divide key
+ // handled by key code above
+
+ case GDK_Num_Lock:
+ return VKEY_NUMLOCK; // (90) NUM LOCK key
+
+ case GDK_Scroll_Lock:
+ return VKEY_SCROLL; // (91) SCROLL LOCK key
+
+ // VKEY_LSHIFT (A0) Left SHIFT key
+ // VKEY_RSHIFT (A1) Right SHIFT key
+ // VKEY_LCONTROL (A2) Left CONTROL key
+ // VKEY_RCONTROL (A3) Right CONTROL key
+ // VKEY_LMENU (A4) Left MENU key
+ // VKEY_RMENU (A5) Right MENU key
+ // VKEY_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
+ // VKEY_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
+ // VKEY_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
+ // VKEY_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
+ // VKEY_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
+ // VKEY_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
+ // VKEY_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
+ // VKEY_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
+ // VKEY_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
+ // VKEY_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
+ // VKEY_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
+ // VKEY_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
+ // VKEY_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
+ // VKEY_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
+ // VKEY_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
+ // VKEY_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
+ // VKEY_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
+ // VKEY_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
+
+ // VKEY_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key
+ case GDK_semicolon:
+ case GDK_colon:
+ return VKEY_OEM_1; //case ';': case ':': return 0xBA;
+ // VKEY_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
+ case GDK_plus:
+ case GDK_equal:
+ return VKEY_OEM_PLUS; //case '=': case '+': return 0xBB;
+ // VKEY_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
+ case GDK_comma:
+ case GDK_less:
+ return VKEY_OEM_COMMA; //case ',': case '<': return 0xBC;
+ // VKEY_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
+ case GDK_minus:
+ case GDK_underscore:
+ return VKEY_OEM_MINUS; //case '-': case '_': return 0xBD;
+ // VKEY_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
+ case GDK_period:
+ case GDK_greater:
+ return VKEY_OEM_PERIOD; //case '.': case '>': return 0xBE;
+ // VKEY_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
+ case GDK_slash:
+ case GDK_question:
+ return VKEY_OEM_2; //case '/': case '?': return 0xBF;
+ // VKEY_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
+ case GDK_asciitilde:
+ case GDK_quoteleft:
+ return VKEY_OEM_3; //case '`': case '~': return 0xC0;
+ // VKEY_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
+ case GDK_bracketleft:
+ case GDK_braceleft:
+ return VKEY_OEM_4; //case '[': case '{': return 0xDB;
+ // VKEY_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
+ case GDK_backslash:
+ case GDK_bar:
+ return VKEY_OEM_5; //case '\\': case '|': return 0xDC;
+ // VKEY_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
+ case GDK_bracketright:
+ case GDK_braceright:
+ return VKEY_OEM_6; // case ']': case '}': return 0xDD;
+ // VKEY_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
+ case GDK_quoteright:
+ case GDK_quotedbl:
+ return VKEY_OEM_7; // case '\'': case '"': return 0xDE;
+ // VKEY_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
+ // VKEY_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
+ // VKEY_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
+ // VKEY_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VKEY_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
+ // VKEY_ATTN (F6) Attn key
+ // VKEY_CRSEL (F7) CrSel key
+ // VKEY_EXSEL (F8) ExSel key
+ // VKEY_EREOF (F9) Erase EOF key
+ // VKEY_PLAY (FA) Play key
+ // VKEY_ZOOM (FB) Zoom key
+ // VKEY_NONAME (FC) Reserved for future use
+ // VKEY_PA1 (FD) PA1 key
+ // VKEY_OEM_CLEAR (FE) Clear key
+ default:
+ return 0;
+ }
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/KeyboardCodes.h b/WebCore/platform/chromium/KeyboardCodes.h
new file mode 100644
index 0000000..10eb0cd
--- /dev/null
+++ b/WebCore/platform/chromium/KeyboardCodes.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef KeyboardCodes_h
+#define KeyboardCodes_h
+
+#if PLATFORM(WIN_OS)
+#include "KeyboardCodesWin.h"
+#else
+#include "KeyboardCodesPosix.h"
+#endif
+
+#endif
diff --git a/WebCore/platform/chromium/KeyboardCodesPosix.h b/WebCore/platform/chromium/KeyboardCodesPosix.h
new file mode 100644
index 0000000..1dfe77e
--- /dev/null
+++ b/WebCore/platform/chromium/KeyboardCodesPosix.h
@@ -0,0 +1,545 @@
+/*
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * 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 KeyboardCodesPosix_h
+#define KeyboardCodesPosix_h
+
+namespace WebCore {
+
+ enum {
+ // VKEY_LBUTTON (01) Left mouse button
+ // VKEY_RBUTTON (02) Right mouse button
+ // VKEY_CANCEL (03) Control-break processing
+ // VKEY_MBUTTON (04) Middle mouse button (three-button mouse)
+ // VKEY_XBUTTON1 (05)
+ // VKEY_XBUTTON2 (06)
+
+ // VKEY_BACK (08) BACKSPACE key
+ VKEY_BACK = 0x08,
+
+ // VKEY_TAB (09) TAB key
+ VKEY_TAB = 0x09,
+
+ // VKEY_CLEAR (0C) CLEAR key
+ VKEY_CLEAR = 0x0C,
+
+ // VKEY_RETURN (0D)
+ VKEY_RETURN = 0x0D,
+
+ // VKEY_SHIFT (10) SHIFT key
+ VKEY_SHIFT = 0x10,
+
+ // VKEY_CONTROL (11) CTRL key
+ VKEY_CONTROL = 0x11,
+
+ // VKEY_MENU (12) ALT key
+ VKEY_MENU = 0x12,
+
+ // VKEY_PAUSE (13) PAUSE key
+ VKEY_PAUSE = 0x13,
+
+ // VKEY_CAPITAL (14) CAPS LOCK key
+ VKEY_CAPITAL = 0x14,
+
+ // VKEY_KANA (15) Input Method Editor (IME) Kana mode
+ VKEY_KANA = 0x15,
+
+ // VKEY_HANGUEL (15) IME Hanguel mode (maintained for compatibility, use VKEY_HANGUL)
+ // VKEY_HANGUL (15) IME Hangul mode
+ VKEY_HANGUL = 0x15,
+
+ // VKEY_JUNJA (17) IME Junja mode
+ VKEY_JUNJA = 0x17,
+
+ // VKEY_FINAL (18) IME final mode
+ VKEY_FINAL = 0x18,
+
+ // VKEY_HANJA (19) IME Hanja mode
+ VKEY_HANJA = 0x19,
+
+ // VKEY_KANJI (19) IME Kanji mode
+ VKEY_KANJI = 0x19,
+
+ // VKEY_ESCAPE (1B) ESC key
+ VKEY_ESCAPE = 0x1B,
+
+ // VKEY_CONVERT (1C) IME convert
+ VKEY_CONVERT = 0x1C,
+
+ // VKEY_NONCONVERT (1D) IME nonconvert
+ VKEY_NONCONVERT = 0x1D,
+
+ // VKEY_ACCEPT (1E) IME accept
+ VKEY_ACCEPT = 0x1E,
+
+ // VKEY_MODECHANGE (1F) IME mode change request
+ VKEY_MODECHANGE = 0x1F,
+
+ // VKEY_SPACE (20) SPACEBAR
+ VKEY_SPACE = 0x20,
+
+ // VKEY_PRIOR (21) PAGE UP key
+ VKEY_PRIOR = 0x21,
+
+ // VKEY_NEXT (22) PAGE DOWN key
+ VKEY_NEXT = 0x22,
+
+ // VKEY_END (23) END key
+ VKEY_END = 0x23,
+
+ // VKEY_HOME (24) HOME key
+ VKEY_HOME = 0x24,
+
+ // VKEY_LEFT (25) LEFT ARROW key
+ VKEY_LEFT = 0x25,
+
+ // VKEY_UP (26) UP ARROW key
+ VKEY_UP = 0x26,
+
+ // VKEY_RIGHT (27) RIGHT ARROW key
+ VKEY_RIGHT = 0x27,
+
+ // VKEY_DOWN (28) DOWN ARROW key
+ VKEY_DOWN = 0x28,
+
+ // VKEY_SELECT (29) SELECT key
+ VKEY_SELECT = 0x29,
+
+ // VKEY_PRINT (2A) PRINT key
+ VKEY_PRINT = 0x2A,
+
+ // VKEY_EXECUTE (2B) EXECUTE key
+ VKEY_EXECUTE = 0x2B,
+
+ // VKEY_SNAPSHOT (2C) PRINT SCREEN key
+ VKEY_SNAPSHOT = 0x2C,
+
+ // VKEY_INSERT (2D) INS key
+ VKEY_INSERT = 0x2D,
+
+ // VKEY_DELETE (2E) DEL key
+ VKEY_DELETE = 0x2E,
+
+ // VKEY_HELP (2F) HELP key
+ VKEY_HELP = 0x2F,
+
+ // (30) 0 key
+ VKEY_0 = 0x30,
+
+ // (31) 1 key
+ VKEY_1 = 0x31,
+
+ // (32) 2 key
+ VKEY_2 = 0x32,
+
+ // (33) 3 key
+ VKEY_3 = 0x33,
+
+ // (34) 4 key
+ VKEY_4 = 0x34,
+
+ // (35) 5 key,
+
+ VKEY_5 = 0x35,
+
+ // (36) 6 key
+ VKEY_6 = 0x36,
+
+ // (37) 7 key
+ VKEY_7 = 0x37,
+
+ // (38) 8 key
+ VKEY_8 = 0x38,
+
+ // (39) 9 key
+ VKEY_9 = 0x39,
+
+ // (41) A key
+ VKEY_A = 0x41,
+
+ // (42) B key
+ VKEY_B = 0x42,
+
+ // (43) C key
+ VKEY_C = 0x43,
+
+ // (44) D key
+ VKEY_D = 0x44,
+
+ // (45) E key
+ VKEY_E = 0x45,
+
+ // (46) F key
+ VKEY_F = 0x46,
+
+ // (47) G key
+ VKEY_G = 0x47,
+
+ // (48) H key
+ VKEY_H = 0x48,
+
+ // (49) I key
+ VKEY_I = 0x49,
+
+ // (4A) J key
+ VKEY_J = 0x4A,
+
+ // (4B) K key
+ VKEY_K = 0x4B,
+
+ // (4C) L key
+ VKEY_L = 0x4C,
+
+ // (4D) M key
+ VKEY_M = 0x4D,
+
+ // (4E) N key
+ VKEY_N = 0x4E,
+
+ // (4F) O key
+ VKEY_O = 0x4F,
+
+ // (50) P key
+ VKEY_P = 0x50,
+
+ // (51) Q key
+ VKEY_Q = 0x51,
+
+ // (52) R key
+ VKEY_R = 0x52,
+
+ // (53) S key
+ VKEY_S = 0x53,
+
+ // (54) T key
+ VKEY_T = 0x54,
+
+ // (55) U key
+ VKEY_U = 0x55,
+
+ // (56) V key
+ VKEY_V = 0x56,
+
+ // (57) W key
+ VKEY_W = 0x57,
+
+ // (58) X key
+ VKEY_X = 0x58,
+
+ // (59) Y key
+ VKEY_Y = 0x59,
+
+ // (5A) Z key
+ VKEY_Z = 0x5A,
+
+ // VKEY_LWIN (5B) Left Windows key (Microsoft Natural keyboard)
+ VKEY_LWIN = 0x5B,
+
+ // VKEY_RWIN (5C) Right Windows key (Natural keyboard)
+ VKEY_RWIN = 0x5C,
+
+ // VKEY_APPS (5D) Applications key (Natural keyboard)
+ VKEY_APPS = 0x5D,
+
+ // VKEY_SLEEP (5F) Computer Sleep key
+ VKEY_SLEEP = 0x5F,
+
+ // VKEY_NUMPAD0 (60) Numeric keypad 0 key
+ VKEY_NUMPAD0 = 0x60,
+
+ // VKEY_NUMPAD1 (61) Numeric keypad 1 key
+ VKEY_NUMPAD1 = 0x61,
+
+ // VKEY_NUMPAD2 (62) Numeric keypad 2 key
+ VKEY_NUMPAD2 = 0x62,
+
+ // VKEY_NUMPAD3 (63) Numeric keypad 3 key
+ VKEY_NUMPAD3 = 0x63,
+
+ // VKEY_NUMPAD4 (64) Numeric keypad 4 key
+ VKEY_NUMPAD4 = 0x64,
+
+ // VKEY_NUMPAD5 (65) Numeric keypad 5 key
+ VKEY_NUMPAD5 = 0x65,
+
+ // VKEY_NUMPAD6 (66) Numeric keypad 6 key
+ VKEY_NUMPAD6 = 0x66,
+
+ // VKEY_NUMPAD7 (67) Numeric keypad 7 key
+ VKEY_NUMPAD7 = 0x67,
+
+ // VKEY_NUMPAD8 (68) Numeric keypad 8 key
+ VKEY_NUMPAD8 = 0x68,
+
+ // VKEY_NUMPAD9 (69) Numeric keypad 9 key
+ VKEY_NUMPAD9 = 0x69,
+
+ // VKEY_MULTIPLY (6A) Multiply key
+ VKEY_MULTIPLY = 0x6A,
+
+ // VKEY_ADD (6B) Add key
+ VKEY_ADD = 0x6B,
+
+ // VKEY_SEPARATOR (6C) Separator key
+ VKEY_SEPARATOR = 0x6C,
+
+ // VKEY_SUBTRACT (6D) Subtract key
+ VKEY_SUBTRACT = 0x6D,
+
+ // VKEY_DECIMAL (6E) Decimal key
+ VKEY_DECIMAL = 0x6E,
+
+ // VKEY_DIVIDE (6F) Divide key
+ VKEY_DIVIDE = 0x6F,
+
+ // VKEY_F1 (70) F1 key
+ VKEY_F1 = 0x70,
+
+ // VKEY_F2 (71) F2 key
+ VKEY_F2 = 0x71,
+
+ // VKEY_F3 (72) F3 key
+ VKEY_F3 = 0x72,
+
+ // VKEY_F4 (73) F4 key
+ VKEY_F4 = 0x73,
+
+ // VKEY_F5 (74) F5 key
+ VKEY_F5 = 0x74,
+
+ // VKEY_F6 (75) F6 key
+ VKEY_F6 = 0x75,
+
+ // VKEY_F7 (76) F7 key
+ VKEY_F7 = 0x76,
+
+ // VKEY_F8 (77) F8 key
+ VKEY_F8 = 0x77,
+
+ // VKEY_F9 (78) F9 key
+ VKEY_F9 = 0x78,
+
+ // VKEY_F10 (79) F10 key
+ VKEY_F10 = 0x79,
+
+ // VKEY_F11 (7A) F11 key
+ VKEY_F11 = 0x7A,
+
+ // VKEY_F12 (7B) F12 key
+ VKEY_F12 = 0x7B,
+
+ // VKEY_F13 (7C) F13 key
+ VKEY_F13 = 0x7C,
+
+ // VKEY_F14 (7D) F14 key
+ VKEY_F14 = 0x7D,
+
+ // VKEY_F15 (7E) F15 key
+ VKEY_F15 = 0x7E,
+
+ // VKEY_F16 (7F) F16 key
+ VKEY_F16 = 0x7F,
+
+ // VKEY_F17 (80H) F17 key
+ VKEY_F17 = 0x80,
+
+ // VKEY_F18 (81H) F18 key
+ VKEY_F18 = 0x81,
+
+ // VKEY_F19 (82H) F19 key
+ VKEY_F19 = 0x82,
+
+ // VKEY_F20 (83H) F20 key
+ VKEY_F20 = 0x83,
+
+ // VKEY_F21 (84H) F21 key
+ VKEY_F21 = 0x84,
+
+ // VKEY_F22 (85H) F22 key
+ VKEY_F22 = 0x85,
+
+ // VKEY_F23 (86H) F23 key
+ VKEY_F23 = 0x86,
+
+ // VKEY_F24 (87H) F24 key
+ VKEY_F24 = 0x87,
+
+ // VKEY_NUMLOCK (90) NUM LOCK key
+ VKEY_NUMLOCK = 0x90,
+
+ // VKEY_SCROLL (91) SCROLL LOCK key
+ VKEY_SCROLL = 0x91,
+
+ // VKEY_LSHIFT (A0) Left SHIFT key
+ VKEY_LSHIFT = 0xA0,
+
+ // VKEY_RSHIFT (A1) Right SHIFT key
+ VKEY_RSHIFT = 0xA1,
+
+ // VKEY_LCONTROL (A2) Left CONTROL key
+ VKEY_LCONTROL = 0xA2,
+
+ // VKEY_RCONTROL (A3) Right CONTROL key
+ VKEY_RCONTROL = 0xA3,
+
+ // VKEY_LMENU (A4) Left MENU key
+ VKEY_LMENU = 0xA4,
+
+ // VKEY_RMENU (A5) Right MENU key
+ VKEY_RMENU = 0xA5,
+
+ // VKEY_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
+ VKEY_BROWSER_BACK = 0xA6,
+
+ // VKEY_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
+ VKEY_BROWSER_FORWARD = 0xA7,
+
+ // VKEY_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
+ VKEY_BROWSER_REFRESH = 0xA8,
+
+ // VKEY_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
+ VKEY_BROWSER_STOP = 0xA9,
+
+ // VKEY_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
+ VKEY_BROWSER_SEARCH = 0xAA,
+
+ // VKEY_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
+ VKEY_BROWSER_FAVORITES = 0xAB,
+
+ // VKEY_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
+ VKEY_BROWSER_HOME = 0xAC,
+
+ // VKEY_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
+ VKEY_VOLUME_MUTE = 0xAD,
+
+ // VKEY_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
+ VKEY_VOLUME_DOWN = 0xAE,
+
+ // VKEY_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
+ VKEY_VOLUME_UP = 0xAF,
+
+ // VKEY_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
+ VKEY_MEDIA_NEXT_TRACK = 0xB0,
+
+ // VKEY_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
+ VKEY_MEDIA_PREV_TRACK = 0xB1,
+
+ // VKEY_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
+ VKEY_MEDIA_STOP = 0xB2,
+
+ // VKEY_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
+ VKEY_MEDIA_PLAY_PAUSE = 0xB3,
+
+ // VKEY_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
+ VKEY_MEDIA_LAUNCH_MAIL = 0xB4,
+
+ // VKEY_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
+ VKEY_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
+
+ // VKEY_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
+ VKEY_MEDIA_LAUNCH_APP1 = 0xB6,
+
+ // VKEY_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
+ VKEY_MEDIA_LAUNCH_APP2 = 0xB7,
+
+ // VKEY_OEM_1 (BA) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ',:' key
+ VKEY_OEM_1 = 0xBA,
+
+ // VKEY_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
+ VKEY_OEM_PLUS = 0xBB,
+
+ // VKEY_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
+ VKEY_OEM_COMMA = 0xBC,
+
+ // VKEY_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
+ VKEY_OEM_MINUS = 0xBD,
+
+ // VKEY_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
+ VKEY_OEM_PERIOD = 0xBE,
+
+ // VKEY_OEM_2 (BF) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
+ VKEY_OEM_2 = 0xBF,
+
+ // VKEY_OEM_3 (C0) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
+ VKEY_OEM_3 = 0xC0,
+
+ // VKEY_OEM_4 (DB) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
+ VKEY_OEM_4 = 0xDB,
+
+ // VKEY_OEM_5 (DC) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
+ VKEY_OEM_5 = 0xDC,
+
+ // VKEY_OEM_6 (DD) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
+ VKEY_OEM_6 = 0xDD,
+
+ // VKEY_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
+ VKEY_OEM_7 = 0xDE,
+
+ // VKEY_OEM_8 (DF) Used for miscellaneous characters, it can vary by keyboard.
+ VKEY_OEM_8 = 0xDF,
+
+ // VKEY_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
+ VKEY_OEM_102 = 0xE2,
+
+ // VKEY_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
+ VKEY_PROCESSKEY = 0xE5,
+
+ // VKEY_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VKEY_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
+ VKEY_PACKET = 0xE7,
+
+ // VKEY_ATTN (F6) Attn key
+ VKEY_ATTN = 0xF6,
+
+ // VKEY_CRSEL (F7) CrSel key
+ VKEY_CRSEL = 0xF7,
+
+ // VKEY_EXSEL (F8) ExSel key
+ VKEY_EXSEL = 0xF8,
+
+ // VKEY_EREOF (F9) Erase EOF key
+ VKEY_EREOF = 0xF9,
+
+ // VKEY_PLAY (FA) Play key
+ VKEY_PLAY = 0xFA,
+
+ // VKEY_ZOOM (FB) Zoom key
+ VKEY_ZOOM = 0xFB,
+
+ // VKEY_NONAME (FC) Reserved for future use
+ VKEY_NONAME = 0xFC,
+
+ // VKEY_PA1 (FD) PA1 key
+ VKEY_PA1 = 0xFD,
+
+ // VKEY_OEM_CLEAR (FE) Clear key
+ VKEY_OEM_CLEAR = 0xFE,
+
+ VKEY_UNKNOWN = 0
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/KeyboardCodesWin.h b/WebCore/platform/chromium/KeyboardCodesWin.h
new file mode 100644
index 0000000..bccd017
--- /dev/null
+++ b/WebCore/platform/chromium/KeyboardCodesWin.h
@@ -0,0 +1,551 @@
+/*
+ * 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.
+ */
+
+#ifndef KeyboardCodesWin_h
+#define KeyboardCodesWin_h
+
+#include <windows.h>
+
+namespace WebCore {
+
+ enum {
+ // VKEY_LBUTTON (01) Left mouse button
+ // VKEY_RBUTTON (02) Right mouse button
+ // VKEY_CANCEL (03) Control-break processing
+ // VKEY_MBUTTON (04) Middle mouse button (three-button mouse)
+ // VKEY_XBUTTON1 (05)
+ // VKEY_XBUTTON2 (06)
+
+ // VKEY_BACK (08) BACKSPACE key
+ VKEY_BACK = VK_BACK,
+
+ // VKEY_TAB (09) TAB key
+ VKEY_TAB = VK_TAB,
+
+ // VKEY_CLEAR (0C) CLEAR key
+ VKEY_CLEAR = VK_CLEAR,
+
+ // VKEY_RETURN (0D)
+ VKEY_RETURN = VK_RETURN,
+
+ // VKEY_SHIFT (10) SHIFT key
+ VKEY_SHIFT = VK_SHIFT,
+
+ // VKEY_CONTROL (11) CTRL key
+ VKEY_CONTROL = VK_CONTROL,
+
+ // VKEY_MENU (12) ALT key
+ VKEY_MENU = VK_MENU,
+
+ // VKEY_PAUSE (13) PAUSE key
+ VKEY_PAUSE = VK_PAUSE,
+
+ // VKEY_CAPITAL (14) CAPS LOCK key
+ VKEY_CAPITAL = VK_CAPITAL,
+
+ // VKEY_KANA (15) Input Method Editor (IME) Kana mode
+ VKEY_KANA = VK_KANA,
+
+ // VKEY_HANGUEL (15) IME Hanguel mode (maintained for compatibility, use VKEY_HANGUL)
+ // VKEY_HANGUL (15) IME Hangul mode
+ VKEY_HANGUL = VK_HANGUL,
+
+ // VKEY_JUNJA (17) IME Junja mode
+ VKEY_JUNJA = VK_JUNJA,
+
+ // VKEY_FINAL (18) IME final mode
+ VKEY_FINAL = VK_FINAL,
+
+ // VKEY_HANJA (19) IME Hanja mode
+ VKEY_HANJA = VK_HANJA,
+
+ // VKEY_KANJI (19) IME Kanji mode
+ VKEY_KANJI = VK_KANJI,
+
+ // VKEY_ESCAPE (1B) ESC key
+ VKEY_ESCAPE = VK_ESCAPE,
+
+ // VKEY_CONVERT (1C) IME convert
+ VKEY_CONVERT = VK_CONVERT,
+
+ // VKEY_NONCONVERT (1D) IME nonconvert
+ VKEY_NONCONVERT = VK_NONCONVERT,
+
+ // VKEY_ACCEPT (1E) IME accept
+ VKEY_ACCEPT = VK_ACCEPT,
+
+ // VKEY_MODECHANGE (1F) IME mode change request
+ VKEY_MODECHANGE = VK_MODECHANGE,
+
+ // VKEY_SPACE (20) SPACEBAR
+ VKEY_SPACE = VK_SPACE,
+
+ // VKEY_PRIOR (21) PAGE UP key
+ VKEY_PRIOR = VK_PRIOR,
+
+ // VKEY_NEXT (22) PAGE DOWN key
+ VKEY_NEXT = VK_NEXT,
+
+ // VKEY_END (23) END key
+ VKEY_END = VK_END,
+
+ // VKEY_HOME (24) HOME key
+ VKEY_HOME = VK_HOME,
+
+ // VKEY_LEFT (25) LEFT ARROW key
+ VKEY_LEFT = VK_LEFT,
+
+ // VKEY_UP (26) UP ARROW key
+ VKEY_UP = VK_UP,
+
+ // VKEY_RIGHT (27) RIGHT ARROW key
+ VKEY_RIGHT = VK_RIGHT,
+
+ // VKEY_DOWN (28) DOWN ARROW key
+ VKEY_DOWN = VK_DOWN,
+
+ // VKEY_SELECT (29) SELECT key
+ VKEY_SELECT = VK_SELECT,
+
+ // VKEY_PRINT (2A) PRINT key
+ VKEY_PRINT = VK_PRINT,
+
+ // VKEY_EXECUTE (2B) EXECUTE key
+ VKEY_EXECUTE = VK_EXECUTE,
+
+ // VKEY_SNAPSHOT (2C) PRINT SCREEN key
+ VKEY_SNAPSHOT = VK_SNAPSHOT,
+
+ // VKEY_INSERT (2D) INS key
+ VKEY_INSERT = VK_INSERT,
+
+ // VKEY_DELETE (2E) DEL key
+ VKEY_DELETE = VK_DELETE,
+
+ // VKEY_HELP (2F) HELP key
+ VKEY_HELP = VK_HELP,
+
+ // (30) 0 key
+ VKEY_0 = '0',
+
+ // (31) 1 key
+ VKEY_1 = '1',
+
+ // (32) 2 key
+ VKEY_2 = '2',
+
+ // (33) 3 key
+ VKEY_3 = '3',
+
+ // (34) 4 key
+ VKEY_4 = '4',
+
+ // (35) 5 key,
+
+ VKEY_5 = '5',
+
+ // (36) 6 key
+ VKEY_6 = '6',
+
+ // (37) 7 key
+ VKEY_7 = '7',
+
+ // (38) 8 key
+ VKEY_8 = '8',
+
+ // (39) 9 key
+ VKEY_9 = '9',
+
+ // (41) A key
+ VKEY_A = 'A',
+
+ // (42) B key
+ VKEY_B = 'B',
+
+ // (43) C key
+ VKEY_C = 'C',
+
+ // (44) D key
+ VKEY_D = 'D',
+
+ // (45) E key
+ VKEY_E = 'E',
+
+ // (46) F key
+ VKEY_F = 'F',
+
+ // (47) G key
+ VKEY_G = 'G',
+
+ // (48) H key
+ VKEY_H = 'H',
+
+ // (49) I key
+ VKEY_I = 'I',
+
+ // (4A) J key
+ VKEY_J = 'J',
+
+ // (4B) K key
+ VKEY_K = 'K',
+
+ // (4C) L key
+ VKEY_L = 'L',
+
+ // (4D) M key
+ VKEY_M = 'M',
+
+ // (4E) N key
+ VKEY_N = 'N',
+
+ // (4F) O key
+ VKEY_O = 'O',
+
+ // (50) P key
+ VKEY_P = 'P',
+
+ // (51) Q key
+ VKEY_Q = 'Q',
+
+ // (52) R key
+ VKEY_R = 'R',
+
+ // (53) S key
+ VKEY_S = 'S',
+
+ // (54) T key
+ VKEY_T = 'T',
+
+ // (55) U key
+ VKEY_U = 'U',
+
+ // (56) V key
+ VKEY_V = 'V',
+
+ // (57) W key
+ VKEY_W = 'W',
+
+ // (58) X key
+ VKEY_X = 'X',
+
+ // (59) Y key
+ VKEY_Y = 'Y',
+
+ // (5A) Z key
+ VKEY_Z = 'Z',
+
+ // VKEY_LWIN (5B) Left Windows key (Microsoft Natural keyboard)
+ VKEY_LWIN = VK_LWIN,
+
+ // VKEY_RWIN (5C) Right Windows key (Natural keyboard)
+ VKEY_RWIN = VK_RWIN,
+
+ // VKEY_APPS (5D) Applications key (Natural keyboard)
+ VKEY_APPS = VK_APPS,
+
+ // VKEY_SLEEP (5F) Computer Sleep key
+ VKEY_SLEEP = VK_SLEEP,
+
+ // VKEY_NUMPAD0 (60) Numeric keypad 0 key
+ VKEY_NUMPAD0 = VK_NUMPAD0,
+
+ // VKEY_NUMPAD1 (61) Numeric keypad 1 key
+ VKEY_NUMPAD1 = VK_NUMPAD1,
+
+ // VKEY_NUMPAD2 (62) Numeric keypad 2 key
+ VKEY_NUMPAD2 = VK_NUMPAD2,
+
+ // VKEY_NUMPAD3 (63) Numeric keypad 3 key
+ VKEY_NUMPAD3 = VK_NUMPAD3,
+
+ // VKEY_NUMPAD4 (64) Numeric keypad 4 key
+ VKEY_NUMPAD4 = VK_NUMPAD4,
+
+ // VKEY_NUMPAD5 (65) Numeric keypad 5 key
+ VKEY_NUMPAD5 = VK_NUMPAD5,
+
+ // VKEY_NUMPAD6 (66) Numeric keypad 6 key
+ VKEY_NUMPAD6 = VK_NUMPAD6,
+
+ // VKEY_NUMPAD7 (67) Numeric keypad 7 key
+ VKEY_NUMPAD7 = VK_NUMPAD7,
+
+ // VKEY_NUMPAD8 (68) Numeric keypad 8 key
+ VKEY_NUMPAD8 = VK_NUMPAD8,
+
+ // VKEY_NUMPAD9 (69) Numeric keypad 9 key
+ VKEY_NUMPAD9 = VK_NUMPAD9,
+
+ // VKEY_MULTIPLY (6A) Multiply key
+ VKEY_MULTIPLY = VK_MULTIPLY,
+
+ // VKEY_ADD (6B) Add key
+ VKEY_ADD = VK_ADD,
+
+ // VKEY_SEPARATOR (6C) Separator key
+ VKEY_SEPARATOR = VK_SEPARATOR,
+
+ // VKEY_SUBTRACT (6D) Subtract key
+ VKEY_SUBTRACT = VK_SUBTRACT,
+
+ // VKEY_DECIMAL (6E) Decimal key
+ VKEY_DECIMAL = VK_DECIMAL,
+
+ // VKEY_DIVIDE (6F) Divide key
+ VKEY_DIVIDE = VK_DIVIDE,
+
+ // VKEY_F1 (70) F1 key
+ VKEY_F1 = VK_F1,
+
+ // VKEY_F2 (71) F2 key
+ VKEY_F2 = VK_F2,
+
+ // VKEY_F3 (72) F3 key
+ VKEY_F3 = VK_F3,
+
+ // VKEY_F4 (73) F4 key
+ VKEY_F4 = VK_F4,
+
+ // VKEY_F5 (74) F5 key
+ VKEY_F5 = VK_F5,
+
+ // VKEY_F6 (75) F6 key
+ VKEY_F6 = VK_F6,
+
+ // VKEY_F7 (76) F7 key
+ VKEY_F7 = VK_F7,
+
+ // VKEY_F8 (77) F8 key
+ VKEY_F8 = VK_F8,
+
+ // VKEY_F9 (78) F9 key
+ VKEY_F9 = VK_F9,
+
+ // VKEY_F10 (79) F10 key
+ VKEY_F10 = VK_F10,
+
+ // VKEY_F11 (7A) F11 key
+ VKEY_F11 = VK_F11,
+
+ // VKEY_F12 (7B) F12 key
+ VKEY_F12 = VK_F12,
+
+ // VKEY_F13 (7C) F13 key
+ VKEY_F13 = VK_F13,
+
+ // VKEY_F14 (7D) F14 key
+ VKEY_F14 = VK_F14,
+
+ // VKEY_F15 (7E) F15 key
+ VKEY_F15 = VK_F15,
+
+ // VKEY_F16 (7F) F16 key
+ VKEY_F16 = VK_F16,
+
+ // VKEY_F17 (80H) F17 key
+ VKEY_F17 = VK_F17,
+
+ // VKEY_F18 (81H) F18 key
+ VKEY_F18 = VK_F18,
+
+ // VKEY_F19 (82H) F19 key
+ VKEY_F19 = VK_F19,
+
+ // VKEY_F20 (83H) F20 key
+ VKEY_F20 = VK_F20,
+
+ // VKEY_F21 (84H) F21 key
+ VKEY_F21 = VK_F21,
+
+ // VKEY_F22 (85H) F22 key
+ VKEY_F22 = VK_F22,
+
+ // VKEY_F23 (86H) F23 key
+ VKEY_F23 = VK_F23,
+
+ // VKEY_F24 (87H) F24 key
+ VKEY_F24 = VK_F24,
+
+ // VKEY_NUMLOCK (90) NUM LOCK key
+ VKEY_NUMLOCK = VK_NUMLOCK,
+
+ // VKEY_SCROLL (91) SCROLL LOCK key
+ VKEY_SCROLL = VK_SCROLL,
+
+ // VKEY_LSHIFT (A0) Left SHIFT key
+ VKEY_LSHIFT = VK_LSHIFT,
+
+ // VKEY_RSHIFT (A1) Right SHIFT key
+ VKEY_RSHIFT = VK_RSHIFT,
+
+ // VKEY_LCONTROL (A2) Left CONTROL key
+ VKEY_LCONTROL = VK_LCONTROL,
+
+ // VKEY_RCONTROL (A3) Right CONTROL key
+ VKEY_RCONTROL = VK_RCONTROL,
+
+ // VKEY_LMENU (A4) Left MENU key
+ VKEY_LMENU = VK_LMENU,
+
+ // VKEY_RMENU (A5) Right MENU key
+ VKEY_RMENU = VK_RMENU,
+
+ // VKEY_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
+ VKEY_BROWSER_BACK = VK_BROWSER_BACK,
+
+ // VKEY_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
+ VKEY_BROWSER_FORWARD = VK_BROWSER_FORWARD,
+
+ // VKEY_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
+ VKEY_BROWSER_REFRESH = VK_BROWSER_REFRESH,
+
+ // VKEY_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
+ VKEY_BROWSER_STOP = VK_BROWSER_STOP,
+
+ // VKEY_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
+ VKEY_BROWSER_SEARCH = VK_BROWSER_SEARCH,
+
+ // VKEY_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
+ VKEY_BROWSER_FAVORITES = VK_BROWSER_FAVORITES,
+
+ // VKEY_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
+ VKEY_BROWSER_HOME = VK_BROWSER_HOME,
+
+ // VKEY_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
+ VKEY_VOLUME_MUTE = VK_VOLUME_MUTE,
+
+ // VKEY_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
+ VKEY_VOLUME_DOWN = VK_VOLUME_DOWN,
+
+ // VKEY_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
+ VKEY_VOLUME_UP = VK_VOLUME_UP,
+
+ // VKEY_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
+ VKEY_MEDIA_NEXT_TRACK = VK_MEDIA_NEXT_TRACK,
+
+ // VKEY_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
+ VKEY_MEDIA_PREV_TRACK = VK_MEDIA_PREV_TRACK,
+
+ // VKEY_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
+ VKEY_MEDIA_STOP = VK_MEDIA_STOP,
+
+ // VKEY_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
+ VKEY_MEDIA_PLAY_PAUSE = VK_MEDIA_PLAY_PAUSE,
+
+ // VKEY_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
+ VKEY_MEDIA_LAUNCH_MAIL = 0xB4,
+
+ // VKEY_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
+ VKEY_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
+
+ // VKEY_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
+ VKEY_MEDIA_LAUNCH_APP1 = 0xB6,
+
+ // VKEY_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
+ VKEY_MEDIA_LAUNCH_APP2 = 0xB7,
+
+ // VKEY_OEM_1 (BA) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ',:' key
+ VKEY_OEM_1 = VK_OEM_1,
+
+ // VKEY_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
+ VKEY_OEM_PLUS = VK_OEM_PLUS,
+
+ // VKEY_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
+ VKEY_OEM_COMMA = VK_OEM_COMMA,
+
+ // VKEY_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
+ VKEY_OEM_MINUS = VK_OEM_MINUS,
+
+ // VKEY_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
+ VKEY_OEM_PERIOD = VK_OEM_PERIOD,
+
+ // VKEY_OEM_2 (BF) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
+ VKEY_OEM_2 = VK_OEM_2,
+
+ // VKEY_OEM_3 (C0) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
+ VKEY_OEM_3 = VK_OEM_3,
+
+ // VKEY_OEM_4 (DB) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
+ VKEY_OEM_4 = VK_OEM_4,
+
+ // VKEY_OEM_5 (DC) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
+ VKEY_OEM_5 = VK_OEM_5,
+
+ // VKEY_OEM_6 (DD) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
+ VKEY_OEM_6 = VK_OEM_6,
+
+ // VKEY_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
+ VKEY_OEM_7 = VK_OEM_7,
+
+ // VKEY_OEM_8 (DF) Used for miscellaneous characters, it can vary by keyboard.
+ VKEY_OEM_8 = VK_OEM_8,
+
+ // VKEY_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
+ VKEY_OEM_102 = VK_OEM_102,
+
+ // VKEY_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
+ VKEY_PROCESSKEY = VK_PROCESSKEY,
+
+ // VKEY_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VKEY_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
+ VKEY_PACKET = VK_PACKET,
+
+ // VKEY_ATTN (F6) Attn key
+ VKEY_ATTN = VK_ATTN,
+
+ // VKEY_CRSEL (F7) CrSel key
+ VKEY_CRSEL = VK_CRSEL,
+
+ // VKEY_EXSEL (F8) ExSel key
+ VKEY_EXSEL = VK_EXSEL,
+
+ // VKEY_EREOF (F9) Erase EOF key
+ VKEY_EREOF = VK_EREOF,
+
+ // VKEY_PLAY (FA) Play key
+ VKEY_PLAY = VK_PLAY,
+
+ // VKEY_ZOOM (FB) Zoom key
+ VKEY_ZOOM = VK_ZOOM,
+
+ // VKEY_NONAME (FC) Reserved for future use
+ VKEY_NONAME = VK_NONAME,
+
+ // VKEY_PA1 (FD) PA1 key
+ VKEY_PA1 = VK_PA1,
+
+ // VKEY_OEM_CLEAR (FE) Clear key
+ VKEY_OEM_CLEAR = VK_OEM_CLEAR,
+
+ VKEY_UNKNOWN = 0
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/Language.cpp b/WebCore/platform/chromium/Language.cpp
new file mode 100644
index 0000000..2612af4
--- /dev/null
+++ b/WebCore/platform/chromium/Language.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 "config.h"
+#include "Language.h"
+
+#include "ChromiumBridge.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+String defaultLanguage()
+{
+ static String computedDefaultLanguage;
+ if (computedDefaultLanguage.isEmpty())
+ computedDefaultLanguage = ChromiumBridge::computedDefaultLanguage();
+ return computedDefaultLanguage;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/LinkHashChromium.cpp b/WebCore/platform/chromium/LinkHashChromium.cpp
new file mode 100644
index 0000000..9cb93ea
--- /dev/null
+++ b/WebCore/platform/chromium/LinkHashChromium.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 "config.h"
+#include "LinkHash.h"
+
+#include "ChromiumBridge.h"
+
+namespace WebCore {
+
+LinkHash visitedLinkHash(const UChar* url, unsigned length)
+{
+ return ChromiumBridge::visitedLinkHash(url, length);
+}
+
+LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL)
+{
+ return ChromiumBridge::visitedLinkHash(base, attributeURL);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/MimeTypeRegistryChromium.cpp b/WebCore/platform/chromium/MimeTypeRegistryChromium.cpp
new file mode 100644
index 0000000..5d6f426
--- /dev/null
+++ b/WebCore/platform/chromium/MimeTypeRegistryChromium.cpp
@@ -0,0 +1,147 @@
+/*
+ * 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 "config.h"
+#include "MIMETypeRegistry.h"
+
+#include "ChromiumBridge.h"
+#include "CString.h"
+#include "MediaPlayer.h"
+
+// NOTE: Unlike other ports, we don't use the shared implementation bits in
+// MIMETypeRegistry.cpp. Instead, we need to route most functions via the
+// ChromiumBridge to the embedder.
+
+namespace WebCore {
+
+// Checks if any of the plugins handle this extension, and if so returns the
+// plugin's mime type for this extension. Otherwise returns an empty string.
+// See PluginsChromium.cpp for the implementation of this function.
+String getPluginMimeTypeFromExtension(const String& extension);
+
+String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
+{
+ return ChromiumBridge::mimeTypeForExtension(ext);
+}
+
+// Returns the file extension if one is found. Does not include the dot in the
+// filename. E.g., 'html'.
+String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type)
+{
+ // Prune out any parameters in case they happen to have snuck in there...
+ // FIXME: Is this really necessary??
+ String mimeType = type.substring(0, static_cast<unsigned>(type.find(';')));
+
+ String ext = ChromiumBridge::preferredExtensionForMIMEType(type);
+ if (!ext.isEmpty() && ext[0] == '.')
+ ext = ext.substring(1);
+
+ return ext;
+}
+
+String MIMETypeRegistry::getMIMETypeForPath(const String& path)
+{
+ int pos = path.reverseFind('.');
+ if (pos < 0)
+ return "application/octet-stream";
+ String extension = path.substring(pos + 1);
+ String mimeType = getMIMETypeForExtension(extension);
+ if (mimeType.isEmpty()) {
+ // If there's no mimetype registered for the extension, check to see
+ // if a plugin can handle the extension.
+ mimeType = getPluginMimeTypeFromExtension(extension);
+ }
+ return mimeType;
+}
+
+bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType)
+{
+ return !mimeType.isEmpty()
+ && ChromiumBridge::isSupportedImageMIMEType(mimeType.latin1().data());
+}
+
+bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
+{
+ return isSupportedImageMIMEType(mimeType);
+}
+
+bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType)
+{
+ // FIXME: Fill this out. See: http://trac.webkit.org/changeset/30888
+ return isSupportedImageMIMEType(mimeType);
+}
+
+bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType)
+{
+ return !mimeType.isEmpty()
+ && ChromiumBridge::isSupportedJavascriptMIMEType(mimeType.latin1().data());
+}
+
+bool MIMETypeRegistry::isSupportedNonImageMIMEType(const String& mimeType)
+{
+ return !mimeType.isEmpty()
+ && ChromiumBridge::isSupportedNonImageMIMEType(mimeType.latin1().data());
+}
+
+bool MIMETypeRegistry::isSupportedMediaMIMEType(const String& mimeType)
+{
+ HashSet<String> supportedMediaMIMETypes;
+#if ENABLE(VIDEO)
+ MediaPlayer::getSupportedTypes(supportedMediaMIMETypes);
+#endif
+ return !mimeType.isEmpty() && supportedMediaMIMETypes.contains(mimeType);
+}
+
+bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType)
+{
+ // Since this set is very limited and is likely to remain so we won't bother with the overhead
+ // of using a hash set.
+ // Any of the MIME types below may be followed by any number of specific versions of the JVM,
+ // which is why we use startsWith()
+ return mimeType.startsWith("application/x-java-applet", false)
+ || mimeType.startsWith("application/x-java-bean", false)
+ || mimeType.startsWith("application/x-java-vm", false);
+}
+
+static HashSet<String>& dummyHashSet()
+{
+ ASSERT_NOT_REACHED();
+ static HashSet<String> dummy;
+ return dummy;
+}
+
+// NOTE: the following methods should never be reached
+HashSet<String>& MIMETypeRegistry::getSupportedImageMIMETypes() { return dummyHashSet(); }
+HashSet<String>& MIMETypeRegistry::getSupportedImageResourceMIMETypes() { return dummyHashSet(); }
+HashSet<String>& MIMETypeRegistry::getSupportedImageMIMETypesForEncoding() { return dummyHashSet(); }
+HashSet<String>& MIMETypeRegistry::getSupportedNonImageMIMETypes() { return dummyHashSet(); }
+HashSet<String>& MIMETypeRegistry::getSupportedMediaMIMETypes() { return dummyHashSet(); }
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/PasteboardChromium.cpp b/WebCore/platform/chromium/PasteboardChromium.cpp
new file mode 100644
index 0000000..e7b2203
--- /dev/null
+++ b/WebCore/platform/chromium/PasteboardChromium.cpp
@@ -0,0 +1,174 @@
+/*
+ * 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 "config.h"
+#include "Pasteboard.h"
+
+#include "ChromiumBridge.h"
+#include "ClipboardUtilitiesChromium.h"
+#include "DocumentFragment.h"
+#include "Document.h"
+#include "Element.h"
+#include "Frame.h"
+#include "HTMLNames.h"
+#include "Image.h"
+#include "KURL.h"
+#include "markup.h"
+#include "NativeImageSkia.h"
+#include "Range.h"
+#include "RenderImage.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "XLinkNames.h"
+#endif
+
+namespace WebCore {
+
+Pasteboard* Pasteboard::generalPasteboard()
+{
+ static Pasteboard* pasteboard = new Pasteboard;
+ return pasteboard;
+}
+
+Pasteboard::Pasteboard()
+{
+}
+
+void Pasteboard::clear()
+{
+ // The ScopedClipboardWriter class takes care of clearing the clipboard's
+ // previous contents.
+}
+
+void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+{
+ String html = createMarkup(selectedRange, 0, AnnotateForInterchange);
+ ExceptionCode ec = 0;
+ KURL url = selectedRange->startContainer(ec)->document()->url();
+ String plainText = frame->selectedText();
+#if PLATFORM(WIN_OS)
+ replaceNewlinesWithWindowsStyleNewlines(plainText);
+#endif
+ replaceNBSPWithSpace(plainText);
+
+ ChromiumBridge::clipboardWriteSelection(html, url, plainText, canSmartCopyOrDelete);
+}
+
+void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
+{
+ ASSERT(!url.isEmpty());
+
+ String title(titleStr);
+ if (title.isEmpty()) {
+ title = url.lastPathComponent();
+ if (title.isEmpty())
+ title = url.host();
+ }
+
+ ChromiumBridge::clipboardWriteURL(url, title);
+}
+
+void Pasteboard::writeImage(Node* node, const KURL&, const String& title)
+{
+ // If the image is wrapped in a link, |url| points to the target of the
+ // link. This isn't useful to us, so get the actual image URL.
+ AtomicString urlString;
+ if (node->hasTagName(HTMLNames::imgTag) || node->hasTagName(HTMLNames::inputTag))
+ urlString = static_cast<Element*>(node)->getAttribute(HTMLNames::srcAttr);
+#if ENABLE(SVG)
+ else if (node->hasTagName(SVGNames::imageTag))
+ urlString = static_cast<Element*>(node)->getAttribute(XLinkNames::hrefAttr);
+#endif
+ else if (node->hasTagName(HTMLNames::embedTag) || node->hasTagName(HTMLNames::objectTag)) {
+ Element* element = static_cast<Element*>(node);
+ urlString = element->getAttribute(element->imageSourceAttributeName());
+ }
+ KURL url = urlString.isEmpty() ? KURL() : node->document()->completeURL(parseURL(urlString));
+
+ ASSERT(node);
+ ASSERT(node->renderer());
+ ASSERT(node->renderer()->isImage());
+
+ RenderImage* renderer = static_cast<RenderImage*>(node->renderer());
+ CachedImage* cachedImage = static_cast<CachedImage*>(renderer->cachedImage());
+ ASSERT(cachedImage);
+ Image* image = cachedImage->image();
+ ASSERT(image);
+
+ NativeImageSkia* bitmap = 0;
+#if !PLATFORM(CG)
+ bitmap = image->nativeImageForCurrentFrame();
+#endif
+ ChromiumBridge::clipboardWriteImage(bitmap, url, title);
+}
+
+bool Pasteboard::canSmartReplace()
+{
+ return ChromiumBridge::clipboardIsFormatAvailable(
+ PasteboardPrivate::WebSmartPasteFormat);
+}
+
+String Pasteboard::plainText(Frame* frame)
+{
+ return ChromiumBridge::clipboardReadPlainText();
+}
+
+PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText)
+{
+ chosePlainText = false;
+
+ if (ChromiumBridge::clipboardIsFormatAvailable(PasteboardPrivate::HTMLFormat)) {
+ String markup;
+ KURL srcURL;
+ ChromiumBridge::clipboardReadHTML(&markup, &srcURL);
+
+ RefPtr<DocumentFragment> fragment =
+ createFragmentFromMarkup(frame->document(), markup, srcURL);
+ if (fragment)
+ return fragment.release();
+ }
+
+ if (allowPlainText) {
+ String markup = ChromiumBridge::clipboardReadPlainText();
+ if (!markup.isEmpty()) {
+ chosePlainText = true;
+
+ RefPtr<DocumentFragment> fragment =
+ createFragmentFromText(context.get(), markup);
+ if (fragment)
+ return fragment.release();
+ }
+ }
+
+ return 0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/PasteboardPrivate.h b/WebCore/platform/chromium/PasteboardPrivate.h
new file mode 100644
index 0000000..26d45a0
--- /dev/null
+++ b/WebCore/platform/chromium/PasteboardPrivate.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PasteboardPrivate_h
+#define PasteboardPrivate_h
+
+namespace WebCore {
+
+ class PasteboardPrivate
+ {
+ public:
+ enum ClipboardFormat {
+ HTMLFormat,
+ BookmarkFormat,
+ WebSmartPasteFormat,
+ };
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/PlatformCursor.h b/WebCore/platform/chromium/PlatformCursor.h
new file mode 100644
index 0000000..692c007
--- /dev/null
+++ b/WebCore/platform/chromium/PlatformCursor.h
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#ifndef PlatformCursor_h
+#define PlatformCursor_h
+
+#include "Image.h"
+#include "IntPoint.h"
+#include "RefPtr.h"
+
+namespace WebCore {
+
+ class PlatformCursor {
+ public:
+ enum Type {
+ TypePointer,
+ TypeCross,
+ TypeHand,
+ TypeIBeam,
+ TypeWait,
+ TypeHelp,
+ TypeEastResize,
+ TypeNorthResize,
+ TypeNorthEastResize,
+ TypeNorthWestResize,
+ TypeSouthResize,
+ TypeSouthEastResize,
+ TypeSouthWestResize,
+ TypeWestResize,
+ TypeNorthSouthResize,
+ TypeEastWestResize,
+ TypeNorthEastSouthWestResize,
+ TypeNorthWestSouthEastResize,
+ TypeColumnResize,
+ TypeRowResize,
+ TypeMiddlePanning,
+ TypeEastPanning,
+ TypeNorthPanning,
+ TypeNorthEastPanning,
+ TypeNorthWestPanning,
+ TypeSouthPanning,
+ TypeSouthEastPanning,
+ TypeSouthWestPanning,
+ TypeWestPanning,
+ TypeMove,
+ TypeVerticalText,
+ TypeCell,
+ TypeContextMenu,
+ TypeAlias,
+ TypeProgress,
+ TypeNoDrop,
+ TypeCopy,
+ TypeNone,
+ TypeNotAllowed,
+ TypeZoomIn,
+ TypeZoomOut,
+ TypeCustom
+ };
+
+ // Cursor.h assumes that it can initialize us to 0.
+ explicit PlatformCursor(int type = 0) : m_type(TypePointer) {}
+
+ PlatformCursor(Type type) : m_type(type) {}
+
+ PlatformCursor(Image* image, const IntPoint& hotSpot)
+ : m_image(image)
+ , m_hotSpot(hotSpot)
+ , m_type(TypeCustom) {}
+
+ PassRefPtr<Image> customImage() const { return m_image; }
+ const IntPoint& hotSpot() const { return m_hotSpot; }
+ Type type() const { return m_type; }
+
+ private:
+ RefPtr<Image> m_image;
+ IntPoint m_hotSpot;
+ Type m_type;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp b/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp
new file mode 100644
index 0000000..6840bdf
--- /dev/null
+++ b/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * 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 "PlatformKeyboardEvent.h"
+
+#if PLATFORM(WIN_OS)
+#include <windows.h>
+#elif PLATFORM(DARWIN)
+#import <Carbon/Carbon.h>
+#else
+#include "NotImplemented.h"
+#endif
+
+namespace WebCore {
+
+void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode)
+{
+#if PLATFORM(WIN_OS)
+ // No KeyDown events on Windows to disambiguate.
+ ASSERT_NOT_REACHED();
+#elif PLATFORM(DARWIN)
+ // Can only change type from KeyDown to RawKeyDown or Char, as we lack information for other conversions.
+ ASSERT(m_type == KeyDown);
+ ASSERT(type == RawKeyDown || type == Char);
+ m_type = type;
+ if (backwardCompatibilityMode)
+ return;
+
+ if (type == RawKeyDown) {
+ m_text = String();
+ m_unmodifiedText = String();
+ } else {
+ m_keyIdentifier = String();
+ m_windowsVirtualKeyCode = 0;
+ if (m_text.length() == 1 && (m_text[0U] >= 0xF700 && m_text[0U] <= 0xF7FF)) {
+ // According to NSEvents.h, OpenStep reserves the range 0xF700-0xF8FF for function keys. However, some actual private use characters
+ // happen to be in this range, e.g. the Apple logo (Option+Shift+K).
+ // 0xF7FF is an arbitrary cut-off.
+ m_text = String();
+ m_unmodifiedText = String();
+ }
+ }
+#endif
+}
+
+bool PlatformKeyboardEvent::currentCapsLockState()
+{
+#if PLATFORM(WIN_OS)
+ // FIXME: Does this even work inside the sandbox?
+ return GetKeyState(VK_CAPITAL) & 1;
+#elif PLATFORM(DARWIN)
+ return GetCurrentKeyModifiers() & alphaLock;
+#else
+ notImplemented();
+ return false;
+#endif
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/PlatformScreenChromium.cpp b/WebCore/platform/chromium/PlatformScreenChromium.cpp
new file mode 100644
index 0000000..e659ef5
--- /dev/null
+++ b/WebCore/platform/chromium/PlatformScreenChromium.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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 "config.h"
+#include "PlatformScreen.h"
+
+#include "ChromiumBridge.h"
+#include "IntRect.h"
+
+namespace WebCore {
+
+int screenDepth(Widget* widget)
+{
+ return ChromiumBridge::screenDepth(widget);
+}
+
+int screenDepthPerComponent(Widget* widget)
+{
+ return ChromiumBridge::screenDepthPerComponent(widget);
+}
+
+bool screenIsMonochrome(Widget* widget)
+{
+ return ChromiumBridge::screenIsMonochrome(widget);
+}
+
+FloatRect screenRect(Widget* widget)
+{
+ return ChromiumBridge::screenRect(widget);
+}
+
+FloatRect screenAvailableRect(Widget* widget)
+{
+ return ChromiumBridge::screenAvailableRect(widget);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/PlatformWidget.h b/WebCore/platform/chromium/PlatformWidget.h
new file mode 100644
index 0000000..e4e6a18
--- /dev/null
+++ b/WebCore/platform/chromium/PlatformWidget.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef PlatformWidget_h
+#define PlatformWidget_h
+
+// PlatformWidget is an opaque identifier corresponding to whatever native
+// view type the embedder may use. PlatformWidget CANNOT be assumed to be
+// a valid pointer. Some embedders may not use this identifier at all.
+
+typedef void* PlatformWidget;
+
+#endif
diff --git a/WebCore/platform/chromium/PopupMenuChromium.cpp b/WebCore/platform/chromium/PopupMenuChromium.cpp
new file mode 100644
index 0000000..fad0a6b
--- /dev/null
+++ b/WebCore/platform/chromium/PopupMenuChromium.cpp
@@ -0,0 +1,1181 @@
+/*
+ * 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 "config.h"
+#include "PopupMenuChromium.h"
+
+#include "CharacterNames.h"
+#include "ChromeClientChromium.h"
+#include "Font.h"
+#include "FontSelector.h"
+#include "FrameView.h"
+#include "Frame.h"
+#include "FramelessScrollView.h"
+#include "FramelessScrollViewClient.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "KeyboardCodes.h"
+#include "Page.h"
+#include "PlatformKeyboardEvent.h"
+#include "PlatformMouseEvent.h"
+#include "PlatformScreen.h"
+#include "PlatformWheelEvent.h"
+#include "PopupMenu.h"
+#include "RenderTheme.h"
+#include "ScrollbarTheme.h"
+#include "SystemTime.h"
+
+#include <wtf/CurrentTime.h>
+
+using namespace WTF;
+using namespace Unicode;
+
+using std::min;
+using std::max;
+
+namespace WebCore {
+
+typedef unsigned long long TimeStamp;
+
+static const int kMaxVisibleRows = 20;
+static const int kMaxHeight = 500;
+static const int kBorderSize = 1;
+static const TimeStamp kTypeAheadTimeoutMs = 1000;
+
+// This class uses WebCore code to paint and handle events for a drop-down list
+// box ("combobox" on Windows).
+class PopupListBox : public FramelessScrollView, public RefCounted<PopupListBox> {
+public:
+ // FramelessScrollView
+ virtual void paint(GraphicsContext*, const IntRect&);
+ virtual bool handleMouseDownEvent(const PlatformMouseEvent&);
+ virtual bool handleMouseMoveEvent(const PlatformMouseEvent&);
+ virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&);
+ virtual bool handleWheelEvent(const PlatformWheelEvent&);
+ virtual bool handleKeyEvent(const PlatformKeyboardEvent&);
+
+ // ScrollView
+ virtual HostWindow* hostWindow() const;
+
+ // Widget
+ virtual void invalidateRect(const IntRect&);
+
+ // PopupListBox methods
+
+ // Shows the popup
+ void showPopup();
+
+ // Hides the popup. Do not call this directly: use client->hidePopup().
+ void hidePopup();
+
+ // Updates our internal list to match the client.
+ void updateFromElement();
+
+ // Frees any allocated resources used in a particular popup session.
+ void clear();
+
+ // Sets the index of the option that is displayed in the <select> widget in the page
+ void setOriginalIndex(int index);
+
+ // Gets the index of the item that the user is currently moused over or has selected with
+ // the keyboard. This is not the same as the original index, since the user has not yet
+ // accepted this input.
+ int selectedIndex() const { return m_selectedIndex; }
+
+ // Moves selection down/up the given number of items, scrolling if necessary.
+ // Positive is down. The resulting index will be clamped to the range
+ // [0, numItems), and non-option items will be skipped.
+ void adjustSelectedIndex(int delta);
+
+ // Returns the number of items in the list.
+ int numItems() const { return static_cast<int>(m_items.size()); }
+
+ void setBaseWidth(int width) { m_baseWidth = width; }
+
+ // Computes the size of widget and children.
+ void layout();
+
+ // Returns whether the popup wants to process events for the passed key.
+ bool isInterestedInEventForKey(int keyCode);
+
+ // Sets whether the PopupMenuClient should be told to change its text when a
+ // new item is selected (by using the arrow keys). Default is true.
+ void setTextOnIndexChange(bool value) { m_setTextOnIndexChange = value; }
+
+ // Sets whether we should accept the selected index when the popup is
+ // abandonned.
+ void setAcceptOnAbandon(bool value) { m_shouldAcceptOnAbandon = value; }
+
+ // Sets whether pressing the down/up arrow when the last/first row is
+ // selected clears the selection on the first key press and then selects the
+ // first/last row on the next key press. If false, the selected row stays
+ // the last/first row.
+ void setLoopSelectionNavigation(bool value) { m_loopSelectionNavigation = value; }
+
+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)
+ : m_originalIndex(0)
+ , m_selectedIndex(0)
+ , m_shouldAcceptOnAbandon(true)
+ , m_willAcceptOnAbandon(false)
+ , m_visibleRows(0)
+ , m_popupClient(client)
+ , m_repeatingChar(0)
+ , m_lastCharTime(0)
+ , m_setTextOnIndexChange(true)
+ , m_loopSelectionNavigation(false)
+ {
+ setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
+ }
+
+ ~PopupListBox()
+ {
+ clear();
+ }
+
+ void disconnectClient() { m_popupClient = 0; }
+
+ // Closes the popup
+ void abandon();
+ // Select an index in the list, scrolling if necessary.
+ void selectIndex(int index);
+ // Accepts the selected index as the value to be displayed in the <select> widget on
+ // 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();
+
+ // Scrolls to reveal the given index.
+ void scrollToRevealRow(int index);
+ void scrollToRevealSelection() { scrollToRevealRow(m_selectedIndex); }
+
+ // 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);
+
+ // Converts a point to an index of the row the point is over
+ int pointToRowIndex(const IntPoint&);
+
+ // Paint an individual row
+ void paintRow(GraphicsContext*, const IntRect&, int rowIndex);
+
+ // Test if the given point is within the bounds of the popup window.
+ bool isPointInBounds(const IntPoint&);
+
+ // Called when the user presses a text key. Does a prefix-search of the items.
+ void typeAheadFind(const PlatformKeyboardEvent&);
+
+ // Returns the font to use for the given row
+ Font getRowFont(int index);
+
+ // Moves the selection down/up one item, taking care of looping back to the
+ // first/last element if m_loopSelectionNavigation is true.
+ void selectPreviousRow();
+ void selectNextRow();
+
+ // This is the index of the item marked as "selected" - i.e. displayed in the widget on the
+ // page.
+ int m_originalIndex;
+
+ // This is the index of the item that the user is hovered over or has selected using the
+ // keyboard in the list. They have not confirmed this selection by clicking or pressing
+ // enter yet however.
+ int m_selectedIndex;
+
+ // Whether we should accept the selectedIndex as chosen when the popup is
+ // "abandoned". This value is set through its setter and is useful as
+ // select popup menu and form autofill popup menu have different behaviors.
+ bool m_shouldAcceptOnAbandon;
+
+ // 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
+ // selection to change immediately, and is only used if
+ // m_shouldAcceptOnAbandon is true.
+ bool m_willAcceptOnAbandon;
+
+ // 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
+ // page size in data units.
+ int m_visibleRows;
+
+ // Our suggested width, not including scrollbar.
+ int m_baseWidth;
+
+ // A list of the options contained within the <select>
+ Vector<ListItem*> m_items;
+
+ // The <select> PopupMenuClient that opened us.
+ PopupMenuClient* m_popupClient;
+
+ // The scrollbar which has mouse capture. Mouse events go straight to this
+ // if non-NULL.
+ RefPtr<Scrollbar> m_capturingScrollbar;
+
+ // The last scrollbar that the mouse was over. Used for mouseover highlights.
+ RefPtr<Scrollbar> m_lastScrollbarUnderMouse;
+
+ // The string the user has typed so far into the popup. Used for typeAheadFind.
+ String m_typedString;
+
+ // The char the user has hit repeatedly. Used for typeAheadFind.
+ UChar m_repeatingChar;
+
+ // The last time the user hit a key. Used for typeAheadFind.
+ TimeStamp m_lastCharTime;
+
+ bool m_setTextOnIndexChange;
+
+ bool m_loopSelectionNavigation;
+};
+
+static PlatformMouseEvent constructRelativeMouseEvent(const PlatformMouseEvent& e,
+ FramelessScrollView* parent,
+ FramelessScrollView* child)
+{
+ IntPoint pos = parent->convertSelfToChild(child, e.pos());
+
+ // FIXME: This is a horrible hack since PlatformMouseEvent has no setters for x/y.
+ PlatformMouseEvent relativeEvent = e;
+ IntPoint& relativePos = const_cast<IntPoint&>(relativeEvent.pos());
+ relativePos.setX(pos.x());
+ relativePos.setY(pos.y());
+ return relativeEvent;
+}
+
+static PlatformWheelEvent constructRelativeWheelEvent(const PlatformWheelEvent& e,
+ FramelessScrollView* parent,
+ FramelessScrollView* child)
+{
+ IntPoint pos = parent->convertSelfToChild(child, e.pos());
+
+ // FIXME: This is a horrible hack since PlatformWheelEvent has no setters for x/y.
+ PlatformWheelEvent relativeEvent = e;
+ IntPoint& relativePos = const_cast<IntPoint&>(relativeEvent.pos());
+ relativePos.setX(pos.x());
+ relativePos.setY(pos.y());
+ return relativeEvent;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PopupContainer implementation
+
+// static
+PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client,
+ bool focusOnShow)
+{
+ return adoptRef(new PopupContainer(client, focusOnShow));
+}
+
+PopupContainer::PopupContainer(PopupMenuClient* client, bool focusOnShow)
+ : m_listBox(new PopupListBox(client)),
+ m_focusOnShow(focusOnShow)
+{
+ // FrameViews are created with a refcount of 1 so it needs releasing after we
+ // assign it to a RefPtr.
+ m_listBox->deref();
+
+ setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
+}
+
+PopupContainer::~PopupContainer()
+{
+ if (m_listBox)
+ removeChild(m_listBox.get());
+}
+
+void PopupContainer::showPopup(FrameView* view)
+{
+ // Pre-layout, our size matches the <select> dropdown control.
+ int selectHeight = frameRect().height();
+
+ // Lay everything out to figure out our preferred size, then tell the view's
+ // WidgetClient about it. It should assign us a client.
+ layout();
+
+ ChromeClientChromium* chromeClient = static_cast<ChromeClientChromium*>(
+ view->frame()->page()->chrome()->client());
+ if (chromeClient) {
+ // If the popup would extend past the bottom of the screen, open upwards
+ // instead.
+ FloatRect screen = screenRect(view);
+ IntRect widgetRect = chromeClient->windowToScreen(frameRect());
+ if (widgetRect.bottom() > static_cast<int>(screen.bottom()))
+ widgetRect.move(0, -(widgetRect.height() + selectHeight));
+
+ chromeClient->popupOpened(this, widgetRect, m_focusOnShow);
+ }
+
+ // Must get called after we have a client and containingWindow.
+ addChild(m_listBox.get());
+
+ // Enable scrollbars after the listbox is inserted into the hierarchy, so
+ // it has a proper WidgetClient.
+ m_listBox->setVerticalScrollbarMode(ScrollbarAuto);
+
+ m_listBox->scrollToRevealSelection();
+
+ invalidate();
+}
+
+void PopupContainer::hidePopup()
+{
+ invalidate();
+
+ m_listBox->disconnectClient();
+ removeChild(m_listBox.get());
+ m_listBox = 0;
+
+ if (client())
+ client()->popupClosed(this);
+}
+
+void PopupContainer::layout()
+{
+ m_listBox->layout();
+
+ // Place the listbox within our border.
+ m_listBox->move(kBorderSize, kBorderSize);
+
+ // Size ourselves to contain listbox + border.
+ resize(m_listBox->width() + kBorderSize * 2, m_listBox->height() + kBorderSize * 2);
+
+ invalidate();
+}
+
+bool PopupContainer::handleMouseDownEvent(const PlatformMouseEvent& event)
+{
+ return m_listBox->handleMouseDownEvent(
+ constructRelativeMouseEvent(event, this, m_listBox.get()));
+}
+
+bool PopupContainer::handleMouseMoveEvent(const PlatformMouseEvent& event)
+{
+ return m_listBox->handleMouseMoveEvent(
+ constructRelativeMouseEvent(event, this, m_listBox.get()));
+}
+
+bool PopupContainer::handleMouseReleaseEvent(const PlatformMouseEvent& event)
+{
+ return m_listBox->handleMouseReleaseEvent(
+ constructRelativeMouseEvent(event, this, m_listBox.get()));
+}
+
+bool PopupContainer::handleWheelEvent(const PlatformWheelEvent& event)
+{
+ return m_listBox->handleWheelEvent(
+ constructRelativeWheelEvent(event, this, m_listBox.get()));
+}
+
+bool PopupContainer::handleKeyEvent(const PlatformKeyboardEvent& event)
+{
+ return m_listBox->handleKeyEvent(event);
+}
+
+void PopupContainer::hide()
+{
+ m_listBox->abandon();
+}
+
+void PopupContainer::paint(GraphicsContext* gc, const IntRect& rect)
+{
+ // adjust coords for scrolled frame
+ IntRect r = intersection(rect, frameRect());
+ int tx = x();
+ int ty = y();
+
+ r.move(-tx, -ty);
+
+ gc->translate(static_cast<float>(tx), static_cast<float>(ty));
+ m_listBox->paint(gc, r);
+ gc->translate(-static_cast<float>(tx), -static_cast<float>(ty));
+
+ paintBorder(gc, rect);
+}
+
+void PopupContainer::paintBorder(GraphicsContext* gc, const IntRect& rect)
+{
+ // FIXME: Where do we get the border color from?
+ Color borderColor(127, 157, 185);
+
+ gc->setStrokeStyle(NoStroke);
+ gc->setFillColor(borderColor);
+
+ int tx = x();
+ int ty = y();
+
+ // top, left, bottom, right
+ gc->drawRect(IntRect(tx, ty, width(), kBorderSize));
+ gc->drawRect(IntRect(tx, ty, kBorderSize, height()));
+ gc->drawRect(IntRect(tx, ty + height() - kBorderSize, width(), kBorderSize));
+ gc->drawRect(IntRect(tx + width() - kBorderSize, ty, kBorderSize, height()));
+}
+
+bool PopupContainer::isInterestedInEventForKey(int keyCode)
+{
+ return m_listBox->isInterestedInEventForKey(keyCode);
+}
+
+void PopupContainer::show(const IntRect& r, FrameView* v, int index)
+{
+ // The rect is the size of the select box. It's usually larger than we need.
+ // subtract border size so that usually the container will be displayed
+ // exactly the same width as the select box.
+ listBox()->setBaseWidth(max(r.width() - kBorderSize * 2, 0));
+
+ listBox()->updateFromElement();
+
+ // We set the selected item in updateFromElement(), and disregard the
+ // index passed into this function (same as Webkit's PopupMenuWin.cpp)
+ // FIXME: make sure this is correct, and add an assertion.
+ // ASSERT(popupWindow(popup)->listBox()->selectedIndex() == index);
+
+ // Convert point to main window coords.
+ IntPoint location = v->contentsToWindow(r.location());
+
+ // Move it below the select widget.
+ location.move(0, r.height());
+
+ IntRect popupRect(location, r.size());
+ setFrameRect(popupRect);
+ showPopup(v);
+}
+
+void PopupContainer::setTextOnIndexChange(bool value)
+{
+ listBox()->setTextOnIndexChange(value);
+}
+
+void PopupContainer::setAcceptOnAbandon(bool value)
+{
+ listBox()->setAcceptOnAbandon(value);
+}
+
+void PopupContainer::setLoopSelectionNavigation(bool value)
+{
+ listBox()->setLoopSelectionNavigation(value);
+}
+
+void PopupContainer::refresh()
+{
+ listBox()->updateFromElement();
+ layout();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PopupListBox implementation
+
+bool PopupListBox::handleMouseDownEvent(const PlatformMouseEvent& event)
+{
+ Scrollbar* scrollbar = scrollbarUnderMouse(event);
+ if (scrollbar) {
+ m_capturingScrollbar = scrollbar;
+ m_capturingScrollbar->mouseDown(event);
+ return true;
+ }
+
+ if (!isPointInBounds(event.pos()))
+ abandon();
+
+ return true;
+}
+
+bool PopupListBox::handleMouseMoveEvent(const PlatformMouseEvent& event)
+{
+ if (m_capturingScrollbar) {
+ m_capturingScrollbar->mouseMoved(event);
+ return true;
+ }
+
+ Scrollbar* scrollbar = scrollbarUnderMouse(event);
+ if (m_lastScrollbarUnderMouse != scrollbar) {
+ // Send mouse exited to the old scrollbar.
+ if (m_lastScrollbarUnderMouse)
+ m_lastScrollbarUnderMouse->mouseExited();
+ m_lastScrollbarUnderMouse = scrollbar;
+ }
+
+ if (scrollbar) {
+ scrollbar->mouseMoved(event);
+ return true;
+ }
+
+ if (!isPointInBounds(event.pos()))
+ return false;
+
+ selectIndex(pointToRowIndex(event.pos()));
+ return true;
+}
+
+bool PopupListBox::handleMouseReleaseEvent(const PlatformMouseEvent& event)
+{
+ if (m_capturingScrollbar) {
+ m_capturingScrollbar->mouseUp();
+ m_capturingScrollbar = 0;
+ return true;
+ }
+
+ if (!isPointInBounds(event.pos()))
+ return true;
+
+ acceptIndex(pointToRowIndex(event.pos()));
+ return true;
+}
+
+bool PopupListBox::handleWheelEvent(const PlatformWheelEvent& event)
+{
+ if (!isPointInBounds(event.pos())) {
+ abandon();
+ return true;
+ }
+
+ // Pass it off to the scroll view.
+ // Sadly, WebCore devs don't understand the whole "const" thing.
+ wheelEvent(const_cast<PlatformWheelEvent&>(event));
+ return true;
+}
+
+// Should be kept in sync with handleKeyEvent().
+bool PopupListBox::isInterestedInEventForKey(int keyCode)
+{
+ switch (keyCode) {
+ case VKEY_ESCAPE:
+ case VKEY_RETURN:
+ case VKEY_UP:
+ case VKEY_DOWN:
+ case VKEY_PRIOR:
+ case VKEY_NEXT:
+ case VKEY_HOME:
+ case VKEY_END:
+ case VKEY_TAB:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event)
+{
+ if (event.type() == PlatformKeyboardEvent::KeyUp)
+ return true;
+
+ if (numItems() == 0 && event.windowsVirtualKeyCode() != VKEY_ESCAPE)
+ return true;
+
+ switch (event.windowsVirtualKeyCode()) {
+ case VKEY_ESCAPE:
+ abandon(); // may delete this
+ return true;
+ case VKEY_RETURN:
+ if (m_selectedIndex == -1) {
+ m_popupClient->hidePopup();
+ // Don't eat the enter if nothing is selected.
+ return false;
+ }
+ acceptIndex(m_selectedIndex); // may delete this
+ return true;
+ case VKEY_UP:
+ selectPreviousRow();
+ break;
+ case VKEY_DOWN:
+ selectNextRow();
+ break;
+ case VKEY_PRIOR:
+ adjustSelectedIndex(-m_visibleRows);
+ break;
+ case VKEY_NEXT:
+ adjustSelectedIndex(m_visibleRows);
+ break;
+ case VKEY_HOME:
+ adjustSelectedIndex(-m_selectedIndex);
+ break;
+ case VKEY_END:
+ adjustSelectedIndex(m_items.size());
+ break;
+ default:
+ if (!event.ctrlKey() && !event.altKey() && !event.metaKey()
+ && isPrintableChar(event.windowsVirtualKeyCode()))
+ typeAheadFind(event);
+ break;
+ }
+
+ if (m_originalIndex != m_selectedIndex) {
+ // Keyboard events should update the selection immediately (but we don't
+ // want to fire the onchange event until the popup is closed, to match
+ // IE). We change the original index so we revert to that when the
+ // popup is closed.
+ if (m_shouldAcceptOnAbandon)
+ m_willAcceptOnAbandon = true;
+
+ setOriginalIndex(m_selectedIndex);
+ if (m_setTextOnIndexChange)
+ m_popupClient->setTextFromItem(m_selectedIndex);
+ } else if (!m_setTextOnIndexChange && event.windowsVirtualKeyCode() == VKEY_TAB) {
+ // TAB is a special case as it should select the current item if any and
+ // advance focus.
+ if (m_selectedIndex >= 0)
+ m_popupClient->setTextFromItem(m_selectedIndex);
+ // Return false so the TAB key event is propagated to the page.
+ return false;
+ }
+
+ return true;
+}
+
+HostWindow* PopupListBox::hostWindow() const
+{
+ // Our parent is the root ScrollView, so it is the one that has a
+ // HostWindow. FrameView::hostWindow() works similarly.
+ return parent() ? parent()->hostWindow() : 0;
+}
+
+void PopupListBox::invalidateRect(const IntRect& rect)
+{
+ // Since we are returning the HostWindow of our parent as our own in
+ // hostWindow(), we need to invalidate in our parent's coordinates.
+ IntRect newRect(rect);
+ newRect.move(kBorderSize, kBorderSize);
+ FramelessScrollView::invalidateRect(newRect);
+}
+
+// From HTMLSelectElement.cpp
+static String stripLeadingWhiteSpace(const String& string)
+{
+ int length = string.length();
+ int i;
+ for (i = 0; i < length; ++i)
+ if (string[i] != noBreakSpace
+ && (string[i] <= 0x7F ? !isspace(string[i]) : (direction(string[i]) != WhiteSpaceNeutral)))
+ break;
+
+ return string.substring(i, length - i);
+}
+
+// From HTMLSelectElement.cpp, with modifications
+void PopupListBox::typeAheadFind(const PlatformKeyboardEvent& event)
+{
+ TimeStamp now = static_cast<TimeStamp>(currentTime() * 1000.0f);
+ TimeStamp delta = now - m_lastCharTime;
+
+ m_lastCharTime = now;
+
+ UChar c = event.windowsVirtualKeyCode();
+
+ String prefix;
+ int searchStartOffset = 1;
+ if (delta > kTypeAheadTimeoutMs) {
+ m_typedString = prefix = String(&c, 1);
+ m_repeatingChar = c;
+ } else {
+ m_typedString.append(c);
+
+ if (c == m_repeatingChar)
+ // The user is likely trying to cycle through all the items starting with this character, so just search on the character
+ prefix = String(&c, 1);
+ else {
+ m_repeatingChar = 0;
+ prefix = m_typedString;
+ searchStartOffset = 0;
+ }
+ }
+
+ int itemCount = numItems();
+ int index = (max(0, m_selectedIndex) + searchStartOffset) % itemCount;
+ for (int i = 0; i < itemCount; i++, index = (index + 1) % itemCount) {
+ if (!isSelectableItem(index))
+ continue;
+
+ if (stripLeadingWhiteSpace(m_items[index]->label).startsWith(prefix, false)) {
+ selectIndex(index);
+ return;
+ }
+ }
+}
+
+void PopupListBox::paint(GraphicsContext* gc, const IntRect& rect)
+{
+ // adjust coords for scrolled frame
+ IntRect r = intersection(rect, frameRect());
+ int tx = x() - scrollX();
+ int ty = y() - scrollY();
+
+ r.move(-tx, -ty);
+
+ // set clip rect to match revised damage rect
+ gc->save();
+ gc->translate(static_cast<float>(tx), static_cast<float>(ty));
+ gc->clip(r);
+
+ // FIXME: Can we optimize scrolling to not require repainting the entire
+ // window? Should we?
+ for (int i = 0; i < numItems(); ++i)
+ paintRow(gc, r, i);
+
+ // Special case for an empty popup.
+ if (numItems() == 0)
+ gc->fillRect(r, Color::white);
+
+ gc->restore();
+
+ ScrollView::paint(gc, rect);
+}
+
+static const int separatorPadding = 4;
+static const int separatorHeight = 1;
+
+void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowIndex)
+{
+ // This code is based largely on RenderListBox::paint* methods.
+
+ IntRect rowRect = getRowBounds(rowIndex);
+ if (!rowRect.intersects(rect))
+ return;
+
+ PopupMenuStyle style = m_popupClient->itemStyle(rowIndex);
+
+ // Paint background
+ Color backColor, textColor;
+ if (rowIndex == m_selectedIndex) {
+ backColor = theme()->activeListBoxSelectionBackgroundColor();
+ textColor = theme()->activeListBoxSelectionForegroundColor();
+ } else {
+ backColor = style.backgroundColor();
+ textColor = style.foregroundColor();
+ }
+
+ // If we have a transparent background, make sure it has a color to blend
+ // against.
+ if (backColor.hasAlpha())
+ gc->fillRect(rowRect, Color::white);
+
+ gc->fillRect(rowRect, backColor);
+
+ if (m_popupClient->itemIsSeparator(rowIndex)) {
+ IntRect separatorRect(
+ rowRect.x() + separatorPadding,
+ rowRect.y() + (rowRect.height() - separatorHeight) / 2,
+ rowRect.width() - 2 * separatorPadding, separatorHeight);
+ gc->fillRect(separatorRect, textColor);
+ return;
+ }
+
+ gc->setFillColor(textColor);
+
+ // Bunch of shit to deal with RTL text...
+ String itemText = m_popupClient->itemText(rowIndex);
+ unsigned length = itemText.length();
+ const UChar* str = itemText.characters();
+
+ TextRun textRun(str, length, false, 0, 0, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft);
+
+ // FIXME: http://b/1210481 We should get the padding of individual option
+ // elements. This probably implies changes to PopupMenuClient.
+
+ // Draw the item text
+ if (style.isVisible()) {
+ Font itemFont = getRowFont(rowIndex);
+ int textX = max(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
+ int textY = rowRect.y() + itemFont.ascent() + (rowRect.height() - itemFont.height()) / 2;
+ gc->drawBidiText(itemFont, textRun, IntPoint(textX, textY));
+ }
+}
+
+Font PopupListBox::getRowFont(int rowIndex)
+{
+ Font itemFont = m_popupClient->itemStyle(rowIndex).font();
+ if (m_popupClient->itemIsLabel(rowIndex)) {
+ // Bold-ify labels (ie, an <optgroup> heading).
+ FontDescription d = itemFont.fontDescription();
+ d.setWeight(FontWeightBold);
+ Font font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
+ font.update(0);
+ return font;
+ }
+
+ return itemFont;
+}
+
+void PopupListBox::abandon()
+{
+ RefPtr<PopupListBox> keepAlive(this);
+
+ m_selectedIndex = m_originalIndex;
+
+ if (m_willAcceptOnAbandon)
+ m_popupClient->valueChanged(m_selectedIndex);
+
+ // valueChanged may have torn down the popup!
+ if (m_popupClient)
+ m_popupClient->hidePopup();
+}
+
+int PopupListBox::pointToRowIndex(const IntPoint& point)
+{
+ int y = scrollY() + point.y();
+
+ // FIXME: binary search if perf matters.
+ for (int i = 0; i < numItems(); ++i) {
+ if (y < m_items[i]->y)
+ return i-1;
+ }
+
+ // Last item?
+ if (y < contentsHeight())
+ return m_items.size()-1;
+
+ return -1;
+}
+
+void PopupListBox::acceptIndex(int index)
+{
+ ASSERT(index >= -1 && index < numItems());
+ if (index == -1 && m_popupClient) {
+ // Enter pressed with no selection, just close the popup.
+ m_popupClient->hidePopup();
+ return;
+ }
+
+ if (isSelectableItem(index)) {
+ RefPtr<PopupListBox> keepAlive(this);
+
+ // Tell the <select> PopupMenuClient what index was selected, and hide ourself.
+ m_popupClient->valueChanged(index);
+
+ // valueChanged may have torn down the popup!
+ if (m_popupClient)
+ m_popupClient->hidePopup();
+ }
+}
+
+void PopupListBox::selectIndex(int index)
+{
+ ASSERT(index >= 0 && index < numItems());
+
+ if (index != m_selectedIndex && isSelectableItem(index)) {
+ invalidateRow(m_selectedIndex);
+ m_selectedIndex = index;
+ invalidateRow(m_selectedIndex);
+
+ scrollToRevealSelection();
+ }
+}
+
+void PopupListBox::setOriginalIndex(int index)
+{
+ m_originalIndex = m_selectedIndex = index;
+}
+
+int PopupListBox::getRowHeight(int index)
+{
+ if (index < 0)
+ return 0;
+
+ return m_popupClient->itemStyle(index).font().height();
+}
+
+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));
+}
+
+void PopupListBox::invalidateRow(int index)
+{
+ if (index < 0)
+ return;
+
+ invalidateRect(getRowBounds(index));
+}
+
+void PopupListBox::scrollToRevealRow(int index)
+{
+ if (index < 0)
+ return;
+
+ IntRect rowRect = getRowBounds(index);
+
+ if (rowRect.y() < scrollY()) {
+ // Row is above current scroll position, scroll up.
+ ScrollView::setScrollPosition(IntPoint(0, rowRect.y()));
+ } else if (rowRect.bottom() > scrollY() + visibleHeight()) {
+ // Row is below current scroll position, scroll down.
+ ScrollView::setScrollPosition(IntPoint(0, rowRect.bottom() - visibleHeight()));
+ }
+}
+
+bool PopupListBox::isSelectableItem(int index) {
+ return m_items[index]->type == TypeOption && m_popupClient->itemIsEnabled(index);
+}
+
+void PopupListBox::clearSelection()
+{
+ if (m_selectedIndex != -1) {
+ invalidateRow(m_selectedIndex);
+ m_selectedIndex = -1;
+ }
+}
+
+void PopupListBox::selectNextRow()
+{
+ if (!m_loopSelectionNavigation || m_selectedIndex != numItems() - 1) {
+ adjustSelectedIndex(1);
+ return;
+ }
+
+ // We are moving past the last item, no row should be selected.
+ clearSelection();
+}
+
+void PopupListBox::selectPreviousRow()
+{
+ if (!m_loopSelectionNavigation || m_selectedIndex > 0) {
+ adjustSelectedIndex(-1);
+ return;
+ }
+
+ if (m_selectedIndex == 0) {
+ // We are moving past the first item, clear the selection.
+ clearSelection();
+ return;
+ }
+
+ // No row are selected, jump to the last item.
+ selectIndex(numItems() - 1);
+ scrollToRevealSelection();
+}
+
+void PopupListBox::adjustSelectedIndex(int delta)
+{
+ int targetIndex = m_selectedIndex + delta;
+ targetIndex = min(max(targetIndex, 0), numItems() - 1);
+ if (!isSelectableItem(targetIndex)) {
+ // We didn't land on an option. Try to find one.
+ // We try to select the closest index to target, prioritizing any in
+ // the range [current, target].
+
+ int dir = delta > 0 ? 1 : -1;
+ int testIndex = m_selectedIndex;
+ int bestIndex = m_selectedIndex;
+ bool passedTarget = false;
+ while (testIndex >= 0 && testIndex < numItems()) {
+ if (isSelectableItem(testIndex))
+ bestIndex = testIndex;
+ if (testIndex == targetIndex)
+ passedTarget = true;
+ if (passedTarget && bestIndex != m_selectedIndex)
+ break;
+
+ testIndex += dir;
+ }
+
+ // Pick the best index, which may mean we don't change.
+ targetIndex = bestIndex;
+ }
+
+ // Select the new index, and ensure its visible. We do this regardless of
+ // whether the selection changed to ensure keyboard events always bring the
+ // selection into view.
+ selectIndex(targetIndex);
+ scrollToRevealSelection();
+}
+
+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;
+ if (m_popupClient->itemIsSeparator(i))
+ type = PopupListBox::TypeSeparator;
+ else if (m_popupClient->itemIsLabel(i))
+ type = PopupListBox::TypeGroup;
+ else
+ type = PopupListBox::TypeOption;
+ m_items.append(new ListItem(m_popupClient->itemText(i), type));
+ }
+
+ m_selectedIndex = m_popupClient->selectedIndex();
+ setOriginalIndex(m_selectedIndex);
+
+ layout();
+}
+
+void PopupListBox::layout()
+{
+ // Size our child items.
+ int baseWidth = 0;
+ int paddingWidth = 0;
+ int y = 0;
+ for (int i = 0; i < numItems(); ++i) {
+ Font itemFont = getRowFont(i);
+
+ // Place the item vertically.
+ m_items[i]->y = y;
+ y += itemFont.height();
+
+ // Ensure the popup is wide enough to fit this item.
+ String text = m_popupClient->itemText(i);
+ if (!text.isEmpty()) {
+ int width = itemFont.width(TextRun(text));
+ baseWidth = max(baseWidth, width);
+ }
+ // FIXME: http://b/1210481 We should get the padding of individual option elements.
+ paddingWidth = max(paddingWidth,
+ m_popupClient->clientPaddingLeft() + m_popupClient->clientPaddingRight());
+ }
+
+ int windowHeight = 0;
+ m_visibleRows = min(numItems(), kMaxVisibleRows);
+ for (int i = 0; i < m_visibleRows; ++i) {
+ int rowHeight = getRowHeight(i);
+ if (windowHeight + rowHeight > kMaxHeight) {
+ m_visibleRows = i;
+ break;
+ }
+
+ windowHeight += rowHeight;
+ }
+
+ // Set our widget and scrollable contents sizes.
+ int scrollbarWidth = 0;
+ if (m_visibleRows < numItems())
+ scrollbarWidth = ScrollbarTheme::nativeTheme()->scrollbarThickness();
+
+ int windowWidth = baseWidth + scrollbarWidth + paddingWidth;
+ int contentWidth = baseWidth;
+
+ if (windowWidth < m_baseWidth) {
+ windowWidth = m_baseWidth;
+ contentWidth = m_baseWidth - scrollbarWidth - paddingWidth;
+ } else {
+ m_baseWidth = baseWidth;
+ }
+
+ resize(windowWidth, windowHeight);
+ setContentsSize(IntSize(contentWidth, getRowBounds(numItems() - 1).bottom()));
+
+ if (hostWindow())
+ scrollToRevealSelection();
+
+ invalidate();
+}
+
+void PopupListBox::clear()
+{
+ for (Vector<ListItem*>::iterator it = m_items.begin(); it != m_items.end(); ++it)
+ delete *it;
+ m_items.clear();
+}
+
+bool PopupListBox::isPointInBounds(const IntPoint& point)
+{
+ return numItems() != 0 && IntRect(0, 0, width(), height()).contains(point);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PopupMenu implementation
+//
+// Note: you cannot add methods to this class, since it is defined above the
+// portability layer. To access methods and properties on the
+// popup widgets, use |popupWindow| above.
+
+PopupMenu::PopupMenu(PopupMenuClient* client)
+ : m_popupClient(client)
+{
+}
+
+PopupMenu::~PopupMenu()
+{
+ hide();
+}
+
+void PopupMenu::show(const IntRect& r, FrameView* v, int index)
+{
+ p.popup = PopupContainer::create(client(), true);
+ p.popup->show(r, v, index);
+}
+
+void PopupMenu::hide()
+{
+ if (p.popup) {
+ p.popup->hidePopup();
+ p.popup = 0;
+ }
+}
+
+void PopupMenu::updateFromElement()
+{
+ p.popup->listBox()->updateFromElement();
+}
+
+bool PopupMenu::itemWritingDirectionIsNatural()
+{
+ return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/PopupMenuChromium.h b/WebCore/platform/chromium/PopupMenuChromium.h
new file mode 100644
index 0000000..a57383d
--- /dev/null
+++ b/WebCore/platform/chromium/PopupMenuChromium.h
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#ifndef PopupMenuChromium_h
+#define PopupMenuChromium_h
+
+#include "config.h"
+#include "PopupMenuClient.h"
+
+#include "FramelessScrollView.h"
+#include "IntRect.h"
+
+namespace WebCore {
+
+ class FrameView;
+ class PopupListBox;
+
+ // FIXME: Our FramelessScrollView classes should probably implement HostWindow!
+
+ // This class holds a PopupListBox (see cpp file). Its sole purpose is to be
+ // able to draw a border around its child. All its paint/event handling is
+ // just forwarded to the child listBox (with the appropriate transforms).
+ // NOTE: this class is exposed so it can be instantiated direcly for the
+ // autofill popup. We cannot use the Popup class directly in that case as the
+ // autofill popup should not be focused when shown and we want to forward the
+ // key events to it (through handleKeyEvent).
+
+ class PopupContainer : public FramelessScrollView, public RefCounted<PopupContainer> {
+ public:
+ static PassRefPtr<PopupContainer> create(PopupMenuClient*, bool focusOnShow);
+
+ // Whether a key event should be sent to this popup.
+ virtual bool isInterestedInEventForKey(int keyCode);
+
+ // FramelessScrollView
+ virtual void paint(GraphicsContext*, const IntRect&);
+ virtual void hide();
+ virtual bool handleMouseDownEvent(const PlatformMouseEvent&);
+ virtual bool handleMouseMoveEvent(const PlatformMouseEvent&);
+ virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&);
+ virtual bool handleWheelEvent(const PlatformWheelEvent&);
+ virtual bool handleKeyEvent(const PlatformKeyboardEvent&);
+
+ // PopupContainer methods
+
+ // Show the popup
+ void showPopup(FrameView*);
+
+ // 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.
+ void show(const IntRect&, FrameView*, int index);
+
+ // Hide the popup. Do not call this directly: use client->hidePopup().
+ void hidePopup();
+
+ // Compute size of widget and children.
+ void layout();
+
+ // Sets whether the PopupMenuClient should be told to change its text when a
+ // new item is selected (by using the arrow keys). Default is true.
+ void setTextOnIndexChange(bool);
+
+ // Sets whether the selection should be accepted when the popup menu is
+ // closed (through ESC being pressed or the focus going away). Default
+ // is true. Note that when TAB is pressed, the selection is always
+ // accepted regardless of this setting.
+ void setAcceptOnAbandon(bool);
+
+ // Sets whether we should move the selection to the first/last item
+ // when the user presses down/up arrow keys and the last/first item is
+ // selected. Default is false, causing the first/last item to stay
+ // selected.
+ void setLoopSelectionNavigation(bool);
+
+ PopupListBox* listBox() const { return m_listBox.get(); }
+
+ // Refresh the popup values from the PopupMenuClient.
+ void refresh();
+
+ private:
+ friend class WTF::RefCounted<PopupContainer>;
+
+ PopupContainer(PopupMenuClient*, bool focusOnShow);
+ ~PopupContainer();
+
+ // Paint the border.
+ void paintBorder(GraphicsContext*, const IntRect&);
+
+ RefPtr<PopupListBox> m_listBox;
+
+ // Whether the window showing this popup should be focused when shown.
+ bool m_focusOnShow;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/PopupMenuPrivate.h b/WebCore/platform/chromium/PopupMenuPrivate.h
new file mode 100644
index 0000000..fb8f850
--- /dev/null
+++ b/WebCore/platform/chromium/PopupMenuPrivate.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef PopupMenuPrivate_h
+#define PopupMenuPrivate_h
+
+#include "RefPtr.h"
+
+namespace WebCore {
+
+ class PopupContainer;
+
+ struct PopupMenuPrivate {
+ RefPtr<PopupContainer> popup;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/SSLKeyGeneratorChromium.cpp b/WebCore/platform/chromium/SSLKeyGeneratorChromium.cpp
new file mode 100644
index 0000000..fdedf2b
--- /dev/null
+++ b/WebCore/platform/chromium/SSLKeyGeneratorChromium.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 "config.h"
+#include "SSLKeyGenerator.h"
+
+namespace WebCore {
+
+// These are defined in webkit/glue/localized_strings.cpp.
+String keygenMenuHighGradeKeySize();
+String keygenMenuMediumGradeKeySize();
+
+// Returns the key sizes supported by the HTML keygen tag. The first string
+// is displayed as the default key size in the keygen menu.
+Vector<String> supportedKeySizes()
+{
+ Vector<String> sizes(2);
+ sizes[0] = keygenMenuHighGradeKeySize();
+ sizes[1] = keygenMenuMediumGradeKeySize();
+ return sizes;
+}
+
+// FIXME: implement signedPublicKeyAndChallengeString here.
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromium.cpp b/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
new file mode 100644
index 0000000..de40572
--- /dev/null
+++ b/WebCore/platform/chromium/ScrollbarThemeChromium.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * 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 "ScrollbarThemeChromium.h"
+
+#include "ChromiumBridge.h"
+#include "PlatformMouseEvent.h"
+#include "Scrollbar.h"
+#include "ScrollbarClient.h"
+#include "ScrollbarThemeComposite.h"
+
+// -----------------------------------------------------------------------------
+// This file contains scrollbar theme code that is cross platform. Additional
+// members of ScrollbarThemeChromium can be found in the platform specific files
+// -----------------------------------------------------------------------------
+
+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
+ // painting the thumb can be skipped. We don't have to be exact here.
+ return thumbLength(scrollbar) > 0;
+}
+
+IntRect ScrollbarThemeChromium::backButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
+{
+ // Windows and Linux just have single arrows.
+ if (part == BackButtonEndPart)
+ return IntRect();
+
+ IntSize size = buttonSize(scrollbar);
+ return IntRect(scrollbar->x(), scrollbar->y(), size.width(), size.height());
+}
+
+IntRect ScrollbarThemeChromium::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
+{
+ // Windows and Linux just have single arrows.
+ if (part == ForwardButtonStartPart)
+ return IntRect();
+
+ IntSize size = buttonSize(scrollbar);
+ int x, y;
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ x = scrollbar->x() + scrollbar->width() - size.width();
+ y = scrollbar->y();
+ } else {
+ x = scrollbar->x();
+ y = scrollbar->y() + scrollbar->height() - size.height();
+ }
+ return IntRect(x, y, size.width(), size.height());
+}
+
+IntRect ScrollbarThemeChromium::trackRect(Scrollbar* scrollbar, bool)
+{
+ IntSize bs = buttonSize(scrollbar);
+ int thickness = scrollbarThickness();
+ 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.
+ if (!hasThumb(scrollbar))
+ paintTrackPiece(context, scrollbar, rect, ForwardTrackPart);
+}
+
+void ScrollbarThemeChromium::paintTickmarks(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
+{
+ if (scrollbar->orientation() != VerticalScrollbar)
+ return;
+
+ if (rect.height() <= 0 || rect.width() <= 0)
+ return; // nothing to draw on.
+
+ // Get the tickmarks for the frameview.
+ Vector<IntRect> tickmarks;
+ scrollbar->client()->getTickmarks(tickmarks);
+ if (!tickmarks.size())
+ return;
+
+ // Get the image for the tickmarks.
+ static RefPtr<Image> dash = Image::loadPlatformResource("tickmarkDash");
+ if (dash->isNull()) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ context->save();
+
+ for (Vector<IntRect>::const_iterator i = tickmarks.begin(); i != tickmarks.end(); ++i) {
+ // Calculate how far down (in %) the tick-mark should appear.
+ const float percent = static_cast<float>(i->y()) / scrollbar->totalSize();
+
+ // Calculate how far down (in pixels) the tick-mark should appear.
+ const int yPos = rect.topLeft().y() + (rect.height() * percent);
+
+ IntPoint tick(scrollbar->x(), yPos);
+ context->drawImage(dash.get(), tick);
+ }
+
+ context->restore();
+}
+
+void ScrollbarThemeChromium::paintScrollCorner(ScrollView* view, GraphicsContext* context, const IntRect& cornerRect)
+{
+ // ScrollbarThemeComposite::paintScrollCorner incorrectly assumes that the
+ // ScrollView is a FrameView (see FramelessScrollView), so we cannot let
+ // that code run. For FrameView's this is correct since we don't do custom
+ // scrollbar corner rendering, which ScrollbarThemeComposite supports.
+ ScrollbarTheme::paintScrollCorner(view, context, cornerRect);
+}
+
+bool ScrollbarThemeChromium::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
+{
+ return evt.shiftKey() && evt.button() == LeftButton;
+}
+
+IntSize ScrollbarThemeChromium::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();
+
+#if !defined(__linux__)
+ // 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;
+#else
+ int girth = thickness;
+#endif
+
+ 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
new file mode 100644
index 0000000..87ffd44
--- /dev/null
+++ b/WebCore/platform/chromium/ScrollbarThemeChromium.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#ifndef ScrollbarThemeChromium_h
+#define ScrollbarThemeChromium_h
+
+#include "ScrollbarThemeComposite.h"
+
+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
+ 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*);
+
+ virtual IntRect backButtonRect(Scrollbar*, ScrollbarPart, bool painting = false);
+ virtual IntRect forwardButtonRect(Scrollbar*, ScrollbarPart, bool painting = false);
+ virtual IntRect trackRect(Scrollbar*, bool painting = false);
+
+ virtual void paintScrollCorner(ScrollView*, GraphicsContext*, const IntRect&);
+ 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;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp
new file mode 100644
index 0000000..95d0f78
--- /dev/null
+++ b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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 "config.h"
+#include "ScrollbarThemeChromium.h"
+
+#include "NotImplemented.h"
+#include "PlatformContextSkia.h"
+#include "PlatformMouseEvent.h"
+#include "Scrollbar.h"
+#include "TransformationMatrix.h"
+
+#include "gtkdrawing.h"
+#include <gtk/gtk.h>
+#include "skia/ext/GdkSkia.h"
+
+namespace WebCore {
+
+int ScrollbarThemeChromium::scrollbarThickness(ScrollbarControlSize controlSize)
+{
+ static int size = 0;
+ if (!size) {
+ MozGtkScrollbarMetrics metrics;
+ moz_gtk_get_scrollbar_metrics(&metrics);
+ size = metrics.slider_width;
+ }
+ return size;
+}
+
+bool ScrollbarThemeChromium::invalidateOnMouseEnterExit()
+{
+ notImplemented();
+ return false;
+}
+
+// Given an uninitialised widget state object, set the members such that it's
+// sane for drawing scrollbars
+static void initMozState(GtkWidgetState* mozState)
+{
+ mozState->active = true;
+ mozState->focused = false;
+ mozState->inHover = false;
+ mozState->disabled = false;
+ mozState->isDefault = false;
+ mozState->canDefault = false;
+ mozState->depressed = false;
+ mozState->curpos = 0;
+ mozState->maxpos = 0;
+}
+
+// Paint a GTK widget
+// gc: context to draw onto
+// rect: the area of the widget
+// widget_type: the type of widget to draw
+// flags: widget dependent flags (e.g. direction of scrollbar arrows etc)
+//
+// See paintMozWiget in RenderThemeGtk.cpp for an explanation of the clipping.
+static void paintScrollbarWidget(GraphicsContext* gc, const IntRect& rect,
+ GtkThemeWidgetType widget_type, gint flags)
+{
+ PlatformContextSkia* pcs = gc->platformContext();
+
+ GdkRectangle gdkRect = { rect.x(), rect.y(), rect.width(), rect.height() };
+
+ const SkIRect clip_region = pcs->canvas()->getTotalClip().getBounds();
+ TransformationMatrix ctm = gc->getCTM().inverse();
+ IntPoint pos = ctm.mapPoint(
+ IntPoint(SkScalarRound(clip_region.fLeft), SkScalarRound(clip_region.fTop)));
+ GdkRectangle gdkClipRect;
+ gdkClipRect.x = pos.x();
+ gdkClipRect.y = pos.y();
+ gdkClipRect.width = clip_region.width();
+ gdkClipRect.height = clip_region.height();
+
+ gdk_rectangle_intersect(&gdkRect, &gdkClipRect, &gdkClipRect);
+
+ GtkWidgetState mozState;
+ initMozState(&mozState);
+
+ moz_gtk_widget_paint(widget_type, pcs->gdk_skia(), &gdkRect, &gdkClipRect,
+ &mozState, flags, GTK_TEXT_DIR_LTR);
+}
+
+void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar,
+ const IntRect& rect, ScrollbarPart partType)
+{
+ const bool horz = scrollbar->orientation() == HorizontalScrollbar;
+ const GtkThemeWidgetType track_type =
+ horz ? MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL : MOZ_GTK_SCROLLBAR_TRACK_VERTICAL;
+ paintScrollbarWidget(gc, rect, track_type, 0);
+}
+
+void ScrollbarThemeChromium::paintButton(GraphicsContext* gc, Scrollbar* scrollbar,
+ const IntRect& rect, ScrollbarPart part)
+{
+ // FIXME: It appears the either we're upsetting GTK by forcing WebKit sizes
+ // on it, or the buttons expect the track to be drawn under them. Either
+ // way, we end up with unpainted pixels which are upsetting the pixel
+ // tests. Thus we paint green under the buttons to, at least, make the
+ // pixel output the same between debug and opt builds.
+ SkPaint paint;
+ paint.setARGB(255, 0, 255, 128);
+ SkRect skrect;
+ skrect.set(rect.x(), rect.y(), rect.x() + rect.width() - 1, rect.y() + rect.height() - 1);
+ gc->platformContext()->canvas()->drawRect(skrect, paint);
+
+ const bool horz = scrollbar->orientation() == HorizontalScrollbar;
+ gint flags = horz ? 0 : MOZ_GTK_STEPPER_VERTICAL;
+ flags |= ForwardButtonEndPart == part ? MOZ_GTK_STEPPER_DOWN : 0;
+ paintScrollbarWidget(gc, rect, MOZ_GTK_SCROLLBAR_BUTTON, flags);
+}
+
+void ScrollbarThemeChromium::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
+{
+ const bool horz = scrollbar->orientation() == HorizontalScrollbar;
+ const GtkThemeWidgetType thumb_type =
+ horz ? MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL : MOZ_GTK_SCROLLBAR_THUMB_VERTICAL;
+ paintScrollbarWidget(gc, rect, thumb_type, 0);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp b/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp
new file mode 100644
index 0000000..0337f63
--- /dev/null
+++ b/WebCore/platform/chromium/ScrollbarThemeChromiumWin.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * 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 "ScrollbarThemeChromium.h"
+
+#include <windows.h>
+#include <vsstyle.h>
+
+#include "ChromiumBridge.h"
+#include "GraphicsContext.h"
+#include "PlatformContextSkia.h"
+#include "PlatformMouseEvent.h"
+#include "Scrollbar.h"
+#include "WindowsVersion.h"
+
+namespace WebCore {
+
+// 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)
+{
+ static int thickness;
+ if (!thickness) {
+ if (ChromiumBridge::layoutTestMode())
+ return kMacScrollbarSize[controlSize];
+ thickness = GetSystemMetrics(SM_CXVSCROLL);
+ }
+ return thickness;
+}
+
+bool ScrollbarThemeChromium::invalidateOnMouseEnterExit()
+{
+ return isVistaOrNewer();
+}
+
+void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart partType)
+{
+ bool horz = scrollbar->orientation() == HorizontalScrollbar;
+
+ int partId;
+ if (partType == BackTrackPart)
+ partId = horz ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
+ else
+ partId = horz ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
+
+ IntRect alignRect = trackRect(scrollbar, false);
+
+ // Draw the track area before/after the thumb on the scroll bar.
+ ChromiumBridge::paintScrollbarTrack(
+ gc,
+ partId,
+ getThemeState(scrollbar, partType),
+ getClassicThemeState(scrollbar, partType),
+ rect,
+ alignRect);
+}
+
+void ScrollbarThemeChromium::paintButton(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
+{
+ bool horz = scrollbar->orientation() == HorizontalScrollbar;
+
+ int partId;
+ if (part == BackButtonStartPart || part == ForwardButtonStartPart)
+ partId = horz ? DFCS_SCROLLLEFT : DFCS_SCROLLUP;
+ else
+ partId = horz ? DFCS_SCROLLRIGHT : DFCS_SCROLLDOWN;
+
+ // Draw the thumb (the box you drag in the scroll bar to scroll).
+ ChromiumBridge::paintScrollbarArrow(
+ gc,
+ getThemeArrowState(scrollbar, part),
+ partId | getClassicThemeState(scrollbar, part),
+ rect);
+}
+
+void ScrollbarThemeChromium::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
+{
+ bool horz = scrollbar->orientation() == HorizontalScrollbar;
+
+ // Draw the thumb (the box you drag in the scroll bar to scroll).
+ ChromiumBridge::paintScrollbarThumb(
+ gc,
+ horz ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT,
+ getThemeState(scrollbar, ThumbPart),
+ getClassicThemeState(scrollbar, ThumbPart),
+ rect);
+
+ // Draw the gripper (the three little lines on the thumb).
+ ChromiumBridge::paintScrollbarThumb(
+ gc,
+ horz ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT,
+ getThemeState(scrollbar, ThumbPart),
+ getClassicThemeState(scrollbar, ThumbPart),
+ rect);
+}
+
+int ScrollbarThemeChromium::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
+ // getThemeArrowState().
+ if (scrollbar->pressedPart() == ThumbPart) {
+ if (part == ThumbPart)
+ return SCRBS_PRESSED;
+ return isVistaOrNewer() ? SCRBS_HOVER : SCRBS_NORMAL;
+ }
+ if (!scrollbar->enabled())
+ return SCRBS_DISABLED;
+ if (scrollbar->hoveredPart() != part || part == BackTrackPart || part == ForwardTrackPart)
+ return (scrollbar->hoveredPart() == NoPart || !isVistaOrNewer()) ? SCRBS_NORMAL : SCRBS_HOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return SCRBS_HOT;
+ return (scrollbar->pressedPart() == part) ? SCRBS_PRESSED : SCRBS_NORMAL;
+}
+
+int ScrollbarThemeChromium::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
+ // clearer and more future-proof.
+ if (part == BackButtonStartPart || part == ForwardButtonStartPart) {
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ if (scrollbar->pressedPart() == ThumbPart)
+ return !isVistaOrNewer() ? ABS_LEFTNORMAL : ABS_LEFTHOVER;
+ if (!scrollbar->enabled())
+ return ABS_LEFTDISABLED;
+ if (scrollbar->hoveredPart() != part)
+ return ((scrollbar->hoveredPart() == NoPart) || !isVistaOrNewer()) ? ABS_LEFTNORMAL : ABS_LEFTHOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return ABS_LEFTHOT;
+ return (scrollbar->pressedPart() == part) ?
+ ABS_LEFTPRESSED : ABS_LEFTNORMAL;
+ }
+ if (scrollbar->pressedPart() == ThumbPart)
+ return !isVistaOrNewer() ? ABS_UPNORMAL : ABS_UPHOVER;
+ if (!scrollbar->enabled())
+ return ABS_UPDISABLED;
+ if (scrollbar->hoveredPart() != part)
+ return ((scrollbar->hoveredPart() == NoPart) || !isVistaOrNewer()) ? ABS_UPNORMAL : ABS_UPHOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return ABS_UPHOT;
+ return (scrollbar->pressedPart() == part) ? ABS_UPPRESSED : ABS_UPNORMAL;
+ }
+ if (scrollbar->orientation() == HorizontalScrollbar) {
+ if (scrollbar->pressedPart() == ThumbPart)
+ return !isVistaOrNewer() ? ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
+ if (!scrollbar->enabled())
+ return ABS_RIGHTDISABLED;
+ if (scrollbar->hoveredPart() != part)
+ return ((scrollbar->hoveredPart() == NoPart) || !isVistaOrNewer()) ? ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return ABS_RIGHTHOT;
+ return (scrollbar->pressedPart() == part) ? ABS_RIGHTPRESSED : ABS_RIGHTNORMAL;
+ }
+ if (scrollbar->pressedPart() == ThumbPart)
+ return !isVistaOrNewer() ? ABS_DOWNNORMAL : ABS_DOWNHOVER;
+ if (!scrollbar->enabled())
+ return ABS_DOWNDISABLED;
+ if (scrollbar->hoveredPart() != part)
+ return ((scrollbar->hoveredPart() == NoPart) || !isVistaOrNewer()) ? ABS_DOWNNORMAL : ABS_DOWNHOVER;
+ if (scrollbar->pressedPart() == NoPart)
+ return ABS_DOWNHOT;
+ return (scrollbar->pressedPart() == part) ? ABS_DOWNPRESSED : ABS_DOWNNORMAL;
+}
+
+int ScrollbarThemeChromium::getClassicThemeState(Scrollbar* scrollbar, ScrollbarPart part) const
+{
+ // When dragging the thumb, draw the buttons normal even when hovered.
+ if (scrollbar->pressedPart() == ThumbPart)
+ return 0;
+ if (!scrollbar->enabled())
+ return DFCS_INACTIVE;
+ if (scrollbar->hoveredPart() != part || part == BackTrackPart || part == ForwardTrackPart)
+ return 0;
+ if (scrollbar->pressedPart() == NoPart)
+ return DFCS_HOT;
+ return (scrollbar->pressedPart() == part) ? (DFCS_PUSHED | DFCS_FLAT) : 0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/SearchPopupMenuChromium.cpp b/WebCore/platform/chromium/SearchPopupMenuChromium.cpp
new file mode 100644
index 0000000..89bfddd
--- /dev/null
+++ b/WebCore/platform/chromium/SearchPopupMenuChromium.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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 "config.h"
+#include "SearchPopupMenu.h"
+
+#include "AtomicString.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+SearchPopupMenu::SearchPopupMenu(PopupMenuClient* client)
+ : PopupMenu(client)
+{
+}
+
+bool SearchPopupMenu::enabled()
+{
+ return false;
+}
+
+void SearchPopupMenu::saveRecentSearches(const AtomicString& name, const Vector<String>& searchItems)
+{
+ notImplemented();
+}
+
+void SearchPopupMenu::loadRecentSearches(const AtomicString& name, Vector<String>& searchItems)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/gtk/SystemTimeLinux.cpp b/WebCore/platform/chromium/SharedTimerChromium.cpp
index 45caddd..5a6a000 100644
--- a/WebCore/platform/gtk/SystemTimeLinux.cpp
+++ b/WebCore/platform/chromium/SharedTimerChromium.cpp
@@ -1,7 +1,5 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- * 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
@@ -22,23 +20,29 @@
* 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.
*/
#include "config.h"
-#include "SystemTime.h"
+#include "SharedTimer.h"
-#include <sys/time.h>
+#include "ChromiumBridge.h"
namespace WebCore {
-double currentTime()
-{
- struct timeval aTimeval;
- struct timezone aTimezone;
+void setSharedTimerFiredFunction(void (*f)())
+{
+ ChromiumBridge::setSharedTimerFiredFunction(f);
+}
- gettimeofday( &aTimeval, &aTimezone );
- return (double)aTimeval.tv_sec + (double)(aTimeval.tv_usec / 1000000.0 );
+void setSharedTimerFireTime(double fireTime)
+{
+ ChromiumBridge::setSharedTimerFireTime(fireTime);
}
+void stopSharedTimer()
+{
+ ChromiumBridge::stopSharedTimer();
}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/SoundChromiumPosix.cpp b/WebCore/platform/chromium/SoundChromiumPosix.cpp
new file mode 100644
index 0000000..2767d76
--- /dev/null
+++ b/WebCore/platform/chromium/SoundChromiumPosix.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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 "config.h"
+#include "Sound.h"
+
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+void systemBeep()
+{
+ notImplemented();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/wx/SystemTimeWx.cpp b/WebCore/platform/chromium/SoundChromiumWin.cpp
index 41e6ad7..e145477 100644
--- a/WebCore/platform/wx/SystemTimeWx.cpp
+++ b/WebCore/platform/chromium/SoundChromiumWin.cpp
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2007 Robin Dunn. All rights reserved.
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,16 +25,15 @@
*/
#include "config.h"
-#include "SystemTime.h"
+#include "Sound.h"
-#include <wx/datetime.h>
+#include <windows.h>
namespace WebCore {
-double currentTime()
+void systemBeep()
{
- wxDateTime now = wxDateTime::UNow();
- return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0);
+ MessageBeep(static_cast<UINT>(-1));
}
-}
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/SystemTimeChromium.cpp b/WebCore/platform/chromium/SystemTimeChromium.cpp
new file mode 100644
index 0000000..52ac262
--- /dev/null
+++ b/WebCore/platform/chromium/SystemTimeChromium.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 "config.h"
+#include "SystemTime.h"
+
+#include "ChromiumBridge.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+// Get the current time in seconds since epoch.
+double currentTime()
+{
+ return ChromiumBridge::currentTime();
+}
+
+float userIdleTime()
+{
+ // Needed for back/forward cache, which we currently have disabled.
+ notImplemented();
+ return 0.0F;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/TemporaryLinkStubs.cpp b/WebCore/platform/chromium/TemporaryLinkStubs.cpp
new file mode 100644
index 0000000..4a028da
--- /dev/null
+++ b/WebCore/platform/chromium/TemporaryLinkStubs.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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 "config.h"
+
+#include "KURL.h"
+#include "NotImplemented.h"
+#include "SharedBuffer.h"
+
+namespace WebCore {
+
+String signedPublicKeyAndChallengeString(unsigned, const String&, const KURL&) { notImplemented(); return String(); }
+void getSupportedKeySizes(Vector<String>&) { notImplemented(); }
+
+String KURL::fileSystemPath() const { notImplemented(); return String(); }
+
+PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String&) { notImplemented(); return 0; }
+
+} // namespace WebCore
+
+namespace WTF {
+
+#if !defined(__linux__)
+void scheduleDispatchFunctionsOnMainThread() { notImplemented(); }
+#endif
+
+} // namespace WTF
diff --git a/WebCore/platform/chromium/WidgetChromium.cpp b/WebCore/platform/chromium/WidgetChromium.cpp
new file mode 100644
index 0000000..4e16e68
--- /dev/null
+++ b/WebCore/platform/chromium/WidgetChromium.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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 "config.h"
+#include "Widget.h"
+
+#include "Assertions.h"
+#include "ChromiumBridge.h"
+
+namespace WebCore {
+
+Widget::Widget(PlatformWidget widget)
+{
+ init(widget);
+}
+
+Widget::~Widget()
+{
+ ASSERT(!parent());
+}
+
+void Widget::show()
+{
+}
+
+void Widget::hide()
+{
+}
+
+void Widget::setCursor(const Cursor& cursor)
+{
+ ChromiumBridge::widgetSetCursor(this, cursor);
+}
+
+void Widget::paint(GraphicsContext*, const IntRect&)
+{
+}
+
+void Widget::setFocus()
+{
+ ChromiumBridge::widgetSetFocus(this);
+}
+
+void Widget::setIsSelected(bool)
+{
+}
+
+IntRect Widget::frameRect() const
+{
+ return m_frame;
+}
+
+void Widget::setFrameRect(const IntRect& rect)
+{
+ m_frame = rect;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/WindowsVersion.cpp b/WebCore/platform/chromium/WindowsVersion.cpp
new file mode 100644
index 0000000..a9632cb
--- /dev/null
+++ b/WebCore/platform/chromium/WindowsVersion.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2008, Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "config.h"
+#include "WindowsVersion.h"
+
+#include <windows.h>
+
+namespace WebCore {
+
+bool isVistaOrNewer()
+{
+ // Cache the result to avoid asking every time.
+ static bool haveResult = false;
+ static bool result = false;
+ if (!haveResult) {
+ OSVERSIONINFO versionInfo;
+ versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+ GetVersionEx(&versionInfo);
+
+ haveResult = true;
+ result = versionInfo.dwMajorVersion >= 6;
+ }
+ return result;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/chromium/WindowsVersion.h b/WebCore/platform/chromium/WindowsVersion.h
new file mode 100644
index 0000000..3b2010a
--- /dev/null
+++ b/WebCore/platform/chromium/WindowsVersion.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef WindowsVersion_h
+#define WindowsVersion_h
+
+namespace WebCore {
+
+ bool isVistaOrNewer();
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/graphics/BitmapImage.cpp b/WebCore/platform/graphics/BitmapImage.cpp
index 4b21de0..45b32ab 100644
--- a/WebCore/platform/graphics/BitmapImage.cpp
+++ b/WebCore/platform/graphics/BitmapImage.cpp
@@ -30,22 +30,18 @@
#include "FloatRect.h"
#include "ImageObserver.h"
#include "IntRect.h"
+#include "MIMETypeRegistry.h"
#include "PlatformString.h"
-#include "SystemTime.h"
#include "Timer.h"
+#include <wtf/CurrentTime.h>
#include <wtf/Vector.h>
-#include "MIMETypeRegistry.h"
namespace WebCore {
-// Animated images >5MB are considered large enough that we'll only hang on to
-// one frame at a time.
-const unsigned cLargeAnimationCutoff = 5242880;
-
-// When an animated image is more than five minutes out of date, don't try to
-// resync on repaint, so we don't waste CPU cycles on an edge case the user
-// doesn't care about.
-const double cAnimationResyncCutoff = 5 * 60;
+static int frameBytes(const IntSize& frameSize)
+{
+ return frameSize.width() * frameSize.height() * 4;
+}
BitmapImage::BitmapImage(ImageObserver* observer)
: Image(observer)
@@ -75,40 +71,42 @@ BitmapImage::~BitmapImage()
stopAnimation();
}
-void BitmapImage::destroyDecodedData(bool incremental, bool preserveNearbyFrames)
+void BitmapImage::destroyDecodedData(bool destroyAll)
{
- // Destroy the cached images and release them.
- if (m_frames.size()) {
- int sizeChange = 0;
- int frameSize = m_size.width() * m_size.height() * 4;
- const size_t nextFrame = (preserveNearbyFrames && frameCount()) ? ((m_currentFrame + 1) % frameCount()) : 0;
- for (unsigned i = incremental ? m_frames.size() - 1 : 0; i < m_frames.size(); i++) {
- if (m_frames[i].m_frame && (!preserveNearbyFrames || (i != m_currentFrame && i != nextFrame))) {
- sizeChange -= frameSize;
- m_frames[i].clear();
- }
- }
-
- // We just always invalidate our platform data, even in the incremental case.
- // This could be better, but it's not a big deal.
- m_isSolidColor = false;
- invalidatePlatformData();
-
- if (sizeChange) {
- m_decodedSize += sizeChange;
- if (imageObserver())
- imageObserver()->decodedSizeChanged(this, sizeChange);
- }
-
- if (!incremental) {
- // Reset the image source, since Image I/O has an underlying cache that it uses
- // while animating that it seems to never clear.
-#if !PLATFORM(SGL)
- m_source.clear();
- m_source.setData(m_data.get(), m_allDataReceived);
-#endif
- }
+ int framesCleared = 0;
+ const size_t clearBeforeFrame = destroyAll ? m_frames.size() : m_currentFrame;
+ for (size_t i = 0; i < clearBeforeFrame; ++i) {
+ // The underlying frame isn't actually changing (we're just trying to
+ // save the memory for the framebuffer data), so we don't need to clear
+ // the metadata.
+ if (m_frames[i].clear(false))
+ ++framesCleared;
}
+
+ destroyMetadataAndNotify(framesCleared);
+
+ m_source.clear(destroyAll, clearBeforeFrame, m_data.get(), m_allDataReceived);
+ return;
+}
+
+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)
+ destroyDecodedData(destroyAll);
+}
+
+void BitmapImage::destroyMetadataAndNotify(int framesCleared)
+{
+ m_isSolidColor = false;
+ invalidatePlatformData();
+
+ const int deltaBytes = framesCleared * -frameBytes(m_size);
+ m_decodedSize += deltaBytes;
+ if (deltaBytes && imageObserver())
+ imageObserver()->decodedSizeChanged(this, deltaBytes);
}
void BitmapImage::cacheFrame(size_t index)
@@ -129,19 +127,14 @@ void BitmapImage::cacheFrame(size_t index)
m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
- int sizeChange;
- if (index) {
- IntSize frameSize = m_source.frameSizeAtIndex(index);
- if (frameSize != m_size)
- m_hasUniformFrameSize = false;
- sizeChange = m_frames[index].m_frame ? frameSize.width() * frameSize.height() * 4 : 0;
- } else
- sizeChange = m_frames[index].m_frame ? m_size.width() * m_size.height() * 4 : 0;
-
- if (sizeChange) {
- m_decodedSize += sizeChange;
+ const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size);
+ if (frameSize != m_size)
+ m_hasUniformFrameSize = false;
+ if (m_frames[index].m_frame) {
+ const int deltaBytes = frameBytes(frameSize);
+ m_decodedSize += deltaBytes;
if (imageObserver())
- imageObserver()->decodedSizeChanged(this, sizeChange);
+ imageObserver()->decodedSizeChanged(this, deltaBytes);
}
}
@@ -163,7 +156,9 @@ IntSize BitmapImage::currentFrameSize() const
bool BitmapImage::dataChanged(bool allDataReceived)
{
- destroyDecodedData(true);
+ // Because we're modifying the current frame, clear its (now possibly
+ // inaccurate) metadata as well.
+ destroyMetadataAndNotify((!m_frames.isEmpty() && m_frames[m_frames.size() - 1].clear(true)) ? 1 : 0);
// Feed all the data we've seen so far to the image decoder.
m_allDataReceived = allDataReceived;
@@ -179,6 +174,11 @@ bool BitmapImage::dataChanged(bool allDataReceived)
return isSizeAvailable();
}
+String BitmapImage::filenameExtension() const
+{
+ return m_source.filenameExtension();
+}
+
size_t BitmapImage::frameCount()
{
if (!m_haveFrameCount) {
@@ -274,16 +274,18 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary)
m_desiredFrameStartTime = time + currentDuration;
} else {
m_desiredFrameStartTime += currentDuration;
- // If we're too far behind, the user probably doesn't care about
- // resyncing and we could burn a lot of time looping through frames
- // below. Just reset the timings.
+
+ // When an animated image is more than five minutes out of date, the
+ // user probably doesn't care about resyncing and we could burn a lot of
+ // time looping through frames below. Just reset the timings.
+ const double cAnimationResyncCutoff = 5 * 60;
if ((time - m_desiredFrameStartTime) > cAnimationResyncCutoff)
m_desiredFrameStartTime = time + currentDuration;
}
// Don't advance the animation to an incomplete frame.
size_t nextFrame = (m_currentFrame + 1) % frameCount();
- if (!frameIsCompleteAtIndex(nextFrame))
+ if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame))
return;
// Don't advance past the last frame if we haven't decoded the whole image
@@ -369,14 +371,12 @@ void BitmapImage::resetAnimation()
m_repetitionsComplete = 0;
m_desiredFrameStartTime = 0;
m_animationFinished = false;
- int frameSize = m_size.width() * m_size.height() * 4;
-
+
// For extremely large animations, when the animation is reset, we just throw everything away.
- if (frameCount() * frameSize > cLargeAnimationCutoff)
- destroyDecodedData();
+ destroyDecodedDataIfNecessary(true);
}
-void BitmapImage::advanceAnimation(Timer<BitmapImage>* timer)
+void BitmapImage::advanceAnimation(Timer<BitmapImage>*)
{
internalAdvanceAnimation(false);
// At this point the image region has been marked dirty, and if it's
@@ -394,45 +394,32 @@ bool BitmapImage::internalAdvanceAnimation(bool skippingFrames)
if (!skippingFrames && imageObserver()->shouldPauseAnimation(this))
return false;
- m_currentFrame++;
+ ++m_currentFrame;
+ bool advancedAnimation = true;
+ bool destroyAll = false;
if (m_currentFrame >= frameCount()) {
++m_repetitionsComplete;
+
// Get the repetition count again. If we weren't able to get a
// repetition count before, we should have decoded the whole image by
// now, so it should now be available.
if (repetitionCount(true) && m_repetitionsComplete >= m_repetitionCount) {
m_animationFinished = true;
m_desiredFrameStartTime = 0;
- m_currentFrame--;
- if (skippingFrames) {
- // Uh oh. We tried to skip past the end of the animation. We'd
- // better draw this last frame.
- notifyObserverAndTrimDecodedData();
- }
- return false;
+ --m_currentFrame;
+ advancedAnimation = false;
+ } else {
+ m_currentFrame = 0;
+ destroyAll = true;
}
- m_currentFrame = 0;
}
+ destroyDecodedDataIfNecessary(destroyAll);
- if (!skippingFrames)
- notifyObserverAndTrimDecodedData();
-
- return true;
-}
-
-void BitmapImage::notifyObserverAndTrimDecodedData()
-{
- // Notify our observer that the animation has advanced.
- imageObserver()->animationAdvanced(this);
-
- // For large animated images, go ahead and throw away frames as we go to
- // save footprint.
- int frameSize = m_size.width() * m_size.height() * 4;
- if (frameCount() * frameSize > cLargeAnimationCutoff) {
- // Destroy all of our frames and just redecode every time. We save the
- // current frame since we'll need it in draw() anyway.
- destroyDecodedData(false, true);
- }
+ // We need to draw this frame if we advanced to it while not skipping, or if
+ // while trying to skip frames we hit the last frame and thus had to stop.
+ if (skippingFrames != advancedAnimation)
+ imageObserver()->animationAdvanced(this);
+ return advancedAnimation;
}
}
diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h
index c5f2a72..110aec4 100644
--- a/WebCore/platform/graphics/BitmapImage.h
+++ b/WebCore/platform/graphics/BitmapImage.h
@@ -80,10 +80,12 @@ struct FrameData : Noncopyable {
~FrameData()
{
- clear();
+ clear(true);
}
- void clear();
+ // Clear the cached image data on the frame, and (optionally) the metadata.
+ // Returns whether there was cached image data to clear.
+ bool clear(bool clearMetadata);
NativeImagePtr m_frame;
bool m_haveMetadata;
@@ -118,6 +120,7 @@ public:
IntSize currentFrameSize() const;
virtual bool dataChanged(bool allDataReceived);
+ virtual String filenameExtension() const;
// It may look unusual that there is no start animation call as public API. This is because
// we start and stop animating lazily. Animation begins whenever someone draws the image. It will
@@ -164,7 +167,7 @@ protected:
#endif
virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
#if PLATFORM(QT) || PLATFORM(WX)
- virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
+ virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
#endif
size_t currentFrame() const { return m_currentFrame; }
@@ -177,18 +180,22 @@ protected:
// Decodes and caches a frame. Never accessed except internally.
void cacheFrame(size_t index);
- // Called to invalidate all our cached data. If an image is loading
- // incrementally, we only invalidate the last cached frame. For large
- // animated images, where we throw away the decoded data after every frame,
- // |preserveNearbyFrames| can be set to preserve the current frame's data
- // and eliminate some unnecessary duplicated decoding work. This also
- // preserves the next frame's data, if available. In most cases this has no
- // effect; either that frame isn't decoded yet, or it's already been
- // destroyed by a previous call. But when we fall behind on the very first
- // animation loop and startAnimation() needs to "catch up" one or more
- // frames, this briefly preserves some of that decoding work, to ease CPU
- // load and make it less likely that we'll keep falling behind.
- virtual void destroyDecodedData(bool incremental = false, bool preserveNearbyFrames = false);
+ // Called to invalidate cached data. When |destroyAll| is true, we wipe out
+ // the entire frame buffer cache and tell the image source to destroy
+ // everything; this is used when e.g. we want to free some room in the image
+ // cache. If |destroyAll| is false, we only delete frames up to the current
+ // one; this is used while animating large images to keep memory footprint
+ // low without redecoding the whole image on every frame.
+ virtual void destroyDecodedData(bool destroyAll = true);
+
+ // If the image is large enough, calls destroyDecodedData() and passes
+ // |destroyAll| along.
+ void destroyDecodedDataIfNecessary(bool destroyAll);
+
+ // Generally called by destroyDecodedData(), destroys whole-image metadata
+ // and notifies observers that the memory footprint has (hopefully)
+ // decreased by |framesCleared| times the size (in bytes) of a frame.
+ void destroyMetadataAndNotify(int framesCleared);
// Whether or not size is available yet.
bool isSizeAvailable();
@@ -206,9 +213,6 @@ protected:
// Returns whether the animation was advanced.
bool internalAdvanceAnimation(bool skippingFrames);
- // Helper for internalAdvanceAnimation().
- void notifyObserverAndTrimDecodedData();
-
// Handle platform-specific data
void initPlatformData();
void invalidatePlatformData();
diff --git a/WebCore/platform/graphics/Color.cpp b/WebCore/platform/graphics/Color.cpp
index 3ff589d..c7e11ee 100644
--- a/WebCore/platform/graphics/Color.cpp
+++ b/WebCore/platform/graphics/Color.cpp
@@ -38,8 +38,17 @@ using namespace WTF;
namespace WebCore {
-const RGBA32 lightenedBlack = 0xFF545454;
-const RGBA32 darkenedWhite = 0xFFABABAB;
+#if !COMPILER(MSVC)
+const RGBA32 Color::black;
+const RGBA32 Color::white;
+const RGBA32 Color::darkGray;
+const RGBA32 Color::gray;
+const RGBA32 Color::lightGray;
+const RGBA32 Color::transparent;
+#endif
+
+static const RGBA32 lightenedBlack = 0xFF545454;
+static const RGBA32 darkenedWhite = 0xFFABABAB;
RGBA32 makeRGB(int r, int g, int b)
{
@@ -51,7 +60,7 @@ RGBA32 makeRGBA(int r, int g, int b, int a)
return max(0, min(a, 255)) << 24 | max(0, min(r, 255)) << 16 | max(0, min(g, 255)) << 8 | max(0, min(b, 255));
}
-int colorFloatToRGBAByte(float f)
+static int colorFloatToRGBAByte(float f)
{
// We use lroundf and 255 instead of nextafterf(256, 0) to match CG's rounding
return max(0, min(static_cast<int>(lroundf(255.0f * f)), 255));
diff --git a/WebCore/platform/graphics/FloatPoint.cpp b/WebCore/platform/graphics/FloatPoint.cpp
index 3ca0361..564ea86 100644
--- a/WebCore/platform/graphics/FloatPoint.cpp
+++ b/WebCore/platform/graphics/FloatPoint.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "FloatPoint.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatConversion.h"
#include "IntPoint.h"
@@ -37,7 +37,7 @@ FloatPoint::FloatPoint(const IntPoint& p) : m_x(p.x()), m_y(p.y())
{
}
-FloatPoint FloatPoint::matrixTransform(const AffineTransform& transform) const
+FloatPoint FloatPoint::matrixTransform(const TransformationMatrix& transform) const
{
double newX, newY;
transform.map(static_cast<double>(m_x), static_cast<double>(m_y), &newX, &newY);
diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h
index 6b3c769..35b3036 100644
--- a/WebCore/platform/graphics/FloatPoint.h
+++ b/WebCore/platform/graphics/FloatPoint.h
@@ -28,6 +28,8 @@
#define FloatPoint_h
#include "FloatSize.h"
+#include "IntPoint.h"
+#include <wtf/MathExtras.h>
#include <wtf/Platform.h>
#if PLATFORM(CG)
@@ -59,7 +61,7 @@ struct SkPoint;
namespace WebCore {
-class AffineTransform;
+class TransformationMatrix;
class IntPoint;
class FloatPoint {
@@ -102,7 +104,7 @@ public:
FloatPoint(const SkPoint&);
#endif
- FloatPoint matrixTransform(const AffineTransform&) const;
+ FloatPoint matrixTransform(const TransformationMatrix&) const;
private:
float m_x, m_y;
@@ -146,6 +148,11 @@ inline bool operator!=(const FloatPoint& a, const FloatPoint& b)
return a.x() != b.x() || a.y() != b.y();
}
+inline IntPoint roundedIntPoint(const FloatPoint& p)
+{
+ return IntPoint(static_cast<int>(roundf(p.x())), static_cast<int>(roundf(p.y())));
+}
+
}
#endif
diff --git a/WebCore/platform/graphics/FloatPoint3D.cpp b/WebCore/platform/graphics/FloatPoint3D.cpp
index ec52d40..e3ba422 100644
--- a/WebCore/platform/graphics/FloatPoint3D.cpp
+++ b/WebCore/platform/graphics/FloatPoint3D.cpp
@@ -23,14 +23,15 @@
#if ENABLE(SVG)
#include <math.h>
+#include "FloatPoint.h"
#include "FloatPoint3D.h"
namespace WebCore {
FloatPoint3D::FloatPoint3D()
- : m_x(0.f)
- , m_y(0.f)
- , m_z(0.f)
+ : m_x(0)
+ , m_y(0)
+ , m_z(0)
{
}
@@ -41,43 +42,22 @@ FloatPoint3D::FloatPoint3D(float x, float y, float z)
{
}
-float FloatPoint3D::x() const
+FloatPoint3D::FloatPoint3D(const FloatPoint& p)
+ : m_x(p.x())
+ , m_y(p.y())
+ , m_z(0)
{
- return m_x;
-}
-
-void FloatPoint3D::setX(float x)
-{
- m_x = x;
-}
-
-float FloatPoint3D::y() const
-{
- return m_y;
-}
-
-void FloatPoint3D::setY(float y)
-{
- m_y = y;
-}
-
-float FloatPoint3D::z() const
-{
- return m_z;
-}
-
-void FloatPoint3D::setZ(float z)
-{
- m_z = z;
}
void FloatPoint3D::normalize()
{
float length = sqrtf(m_x * m_x + m_y * m_y + m_z * m_z);
- m_x /= length;
- m_y /= length;
- m_z /= length;
+ if (length != 0) {
+ m_x /= length;
+ m_y /= length;
+ m_z /= length;
+ }
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/FloatPoint3D.h b/WebCore/platform/graphics/FloatPoint3D.h
index 55f70e7..184e914 100644
--- a/WebCore/platform/graphics/FloatPoint3D.h
+++ b/WebCore/platform/graphics/FloatPoint3D.h
@@ -26,19 +26,22 @@
namespace WebCore {
+class FloatPoint;
+
class FloatPoint3D {
public:
FloatPoint3D();
FloatPoint3D(float x, float y, float z);
+ FloatPoint3D(const FloatPoint&);
- float x() const;
- void setX(float x);
+ float x() const { return m_x; }
+ void setX(float x) { m_x = x; }
- float y() const;
- void setY(float y);
+ float y() const { return m_y; }
+ void setY(float y) { m_y = y; }
- float z() const;
- void setZ(float z);
+ float z() const { return m_z; }
+ void setZ(float z) { m_z = z; }
void normalize();
diff --git a/WebCore/platform/graphics/FloatQuad.cpp b/WebCore/platform/graphics/FloatQuad.cpp
new file mode 100644
index 0000000..a32d8ab
--- /dev/null
+++ b/WebCore/platform/graphics/FloatQuad.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FloatQuad.h"
+
+#include <algorithm>
+
+using std::max;
+using std::min;
+
+namespace WebCore {
+
+static inline float min4(float a, float b, float c, float d)
+{
+ return min(min(a, b), min(c, d));
+}
+
+static inline float max4(float a, float b, float c, float d)
+{
+ return max(max(a, b), max(c, d));
+}
+
+FloatRect FloatQuad::boundingBox() const
+{
+ float left = min4(m_p1.x(), m_p2.x(), m_p3.x(), m_p4.x());
+ float top = min4(m_p1.y(), m_p2.y(), m_p3.y(), m_p4.y());
+
+ float right = max4(m_p1.x(), m_p2.x(), m_p3.x(), m_p4.x());
+ float bottom = max4(m_p1.y(), m_p2.y(), m_p3.y(), m_p4.y());
+
+ return FloatRect(left, top, right - left, bottom - top);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/FloatQuad.h b/WebCore/platform/graphics/FloatQuad.h
new file mode 100644
index 0000000..e05b27d
--- /dev/null
+++ b/WebCore/platform/graphics/FloatQuad.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FloatQuad_h
+#define FloatQuad_h
+
+#include "FloatPoint.h"
+#include "FloatRect.h"
+#include "IntRect.h"
+
+namespace WebCore {
+
+// A FloatQuad is a collection of 4 points, often representing the result of
+// mapping a rectangle through transforms. When initialized from a rect, the
+// points are in clockwise order from top left.
+class FloatQuad {
+public:
+ FloatQuad()
+ {
+ }
+
+ FloatQuad(const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3, const FloatPoint& p4)
+ : m_p1(p1)
+ , m_p2(p2)
+ , m_p3(p3)
+ , m_p4(p4)
+ {
+ }
+
+ FloatQuad(const FloatRect& inRect)
+ : m_p1(inRect.location())
+ , m_p2(inRect.right(), inRect.y())
+ , m_p3(inRect.right(), inRect.bottom())
+ , m_p4(inRect.x(), inRect.bottom())
+ {
+ }
+
+ FloatPoint p1() const { return m_p1; }
+ FloatPoint p2() const { return m_p2; }
+ FloatPoint p3() const { return m_p3; }
+ FloatPoint p4() const { return m_p4; }
+
+ void setP1(const FloatPoint& p) { m_p1 = p; }
+ void setP2(const FloatPoint& p) { m_p2 = p; }
+ void setP3(const FloatPoint& p) { m_p3 = p; }
+ void setP4(const FloatPoint& p) { m_p4 = p; }
+
+ // isEmpty tests that the bounding box is empty. This will not identify
+ // "slanted" empty quads.
+ bool isEmpty() const { return boundingBox().isEmpty(); }
+
+ FloatRect boundingBox() const;
+ IntRect enclosingBoundingBox() const
+ {
+ return enclosingIntRect(boundingBox());
+ }
+
+ void move(const FloatSize& offset)
+ {
+ m_p1 += offset;
+ m_p2 += offset;
+ m_p3 += offset;
+ m_p4 += offset;
+ }
+
+ void move(float dx, float dy)
+ {
+ m_p1.move(dx, dy);
+ m_p2.move(dx, dy);
+ m_p3.move(dx, dy);
+ m_p4.move(dx, dy);
+ }
+
+private:
+ FloatPoint m_p1;
+ FloatPoint m_p2;
+ FloatPoint m_p3;
+ FloatPoint m_p4;
+};
+
+inline FloatQuad& operator+=(FloatQuad& a, const FloatSize& b)
+{
+ a.move(b);
+ return a;
+}
+
+inline FloatQuad& operator-=(FloatQuad& a, const FloatSize& b)
+{
+ a.move(-b.width(), -b.height());
+ return a;
+}
+
+inline bool operator==(const FloatQuad& a, const FloatQuad& b)
+{
+ return a.p1() == b.p1() &&
+ a.p2() == b.p2() &&
+ a.p3() == b.p3() &&
+ a.p4() == b.p4();
+}
+
+inline bool operator!=(const FloatQuad& a, const FloatQuad& b)
+{
+ return a.p1() != b.p1() ||
+ a.p2() != b.p2() ||
+ a.p3() != b.p3() ||
+ a.p4() != b.p4();
+}
+
+} // namespace WebCore
+
+
+#endif // FloatQuad_h
+
diff --git a/WebCore/platform/graphics/FloatRect.cpp b/WebCore/platform/graphics/FloatRect.cpp
index ec7b3fa..532f719 100644
--- a/WebCore/platform/graphics/FloatRect.cpp
+++ b/WebCore/platform/graphics/FloatRect.cpp
@@ -119,4 +119,16 @@ IntRect enclosingIntRect(const FloatRect& rect)
return IntRect(l, t, r - l, b - t);
}
+FloatRect mapRect(const FloatRect& r, const FloatRect& srcRect, const FloatRect& destRect)
+{
+ if (srcRect.width() == 0 || srcRect.height() == 0)
+ return FloatRect();
+
+ float widthScale = destRect.width() / srcRect.width();
+ float heightScale = destRect.height() / srcRect.height();
+ return FloatRect(destRect.x() + (r.x() - srcRect.x()) * widthScale,
+ destRect.y() + (r.y() - srcRect.y()) * heightScale,
+ r.width() * widthScale, r.height() * heightScale);
+}
+
}
diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h
index 11e3791..a87c949 100644
--- a/WebCore/platform/graphics/FloatRect.h
+++ b/WebCore/platform/graphics/FloatRect.h
@@ -167,6 +167,7 @@ inline FloatRect unionRect(const FloatRect& a, const FloatRect& b)
return c;
}
+
inline bool operator==(const FloatRect& a, const FloatRect& b)
{
return a.location() == b.location() && a.size() == b.size();
@@ -179,6 +180,9 @@ inline bool operator!=(const FloatRect& a, const FloatRect& b)
IntRect enclosingIntRect(const FloatRect&);
+// Map rect r from srcRect to an equivalent rect in destRect.
+FloatRect mapRect(const FloatRect& r, const FloatRect& srcRect, const FloatRect& destRect);
+
}
#endif
diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h
index cf1e1c5..6e792b6 100644
--- a/WebCore/platform/graphics/FloatSize.h
+++ b/WebCore/platform/graphics/FloatSize.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2005 Nokia. All rights reserved.
+ * 2008 Eric Seidel <eric@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -67,6 +68,12 @@ public:
m_height > other.m_height ? m_height : other.m_height);
}
+ FloatSize shrunkTo(const FloatSize& other) const
+ {
+ return FloatSize(m_width < other.m_width ? m_width : other.m_width,
+ m_height < other.m_height ? m_height : other.m_height);
+ }
+
#if PLATFORM(CG)
explicit FloatSize(const CGSize&); // don't do this implicitly since it's lossy
operator CGSize() const;
diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp
index 138e322..f8bec82 100644
--- a/WebCore/platform/graphics/Font.cpp
+++ b/WebCore/platform/graphics/Font.cpp
@@ -38,6 +38,7 @@ using namespace Unicode;
namespace WebCore {
+#if USE(FONT_FAST_PATH)
const uint8_t Font::gRoundingHackCharacterTable[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/,
@@ -50,6 +51,7 @@ const uint8_t Font::gRoundingHackCharacterTable[256] = {
};
Font::CodePath Font::s_codePath = Auto;
+#endif
// ============================================================================================
// Font Implementation (Cross-Platform Portion)
@@ -133,132 +135,6 @@ bool Font::operator==(const Font& other) const
&& (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0);
}
-const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCaps) const
-{
- bool useSmallCapsFont = forceSmallCaps;
- if (m_fontDescription.smallCaps()) {
- UChar32 upperC = Unicode::toUpper(c);
- if (upperC != c) {
- c = upperC;
- useSmallCapsFont = true;
- }
- }
-
- if (mirror)
- c = mirroredChar(c);
-
- unsigned pageNumber = (c / GlyphPage::size);
-
- GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero;
- if (!node) {
- node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
- if (pageNumber)
- m_pages.set(pageNumber, node);
- else
- m_pageZero = node;
- }
-
- GlyphPage* page;
- if (!useSmallCapsFont) {
- // Fastest loop, for the common case (not small caps).
- while (true) {
- page = node->page();
- if (page) {
- const GlyphData& data = page->glyphDataForCharacter(c);
- if (data.fontData)
- return data;
- if (node->isSystemFallback())
- break;
- }
-
- // Proceed with the fallback list.
- node = node->getChild(fontDataAt(node->level()), pageNumber);
- if (pageNumber)
- m_pages.set(pageNumber, node);
- else
- m_pageZero = node;
- }
- } else {
- while (true) {
- page = node->page();
- if (page) {
- const 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.
- const SimpleFontData* smallCapsFontData = data.fontData->smallCapsFontData(m_fontDescription);
- if (!smallCapsFontData)
- return data;
-
- GlyphPageTreeNode* smallCapsNode = GlyphPageTreeNode::getRootChild(smallCapsFontData, pageNumber);
- const GlyphPage* smallCapsPage = smallCapsNode->page();
- if (smallCapsPage) {
- const GlyphData& data = smallCapsPage->glyphDataForCharacter(c);
- if (data.fontData)
- return data;
- }
-
- // Do not attempt system fallback off the smallCapsFontData. This is the very unlikely case that
- // a font has the lowercase character but the small caps font does not have its uppercase version.
- return smallCapsFontData->missingGlyphData();
- }
-
- if (node->isSystemFallback())
- break;
- }
-
- // Proceed with the fallback list.
- node = node->getChild(fontDataAt(node->level()), pageNumber);
- if (pageNumber)
- m_pages.set(pageNumber, node);
- else
- m_pageZero = node;
- }
- }
-
- ASSERT(page);
- ASSERT(node->isSystemFallback());
-
- // System fallback is character-dependent. When we get here, we
- // know that the character in question isn't in the system fallback
- // font's glyph page. Try to lazily create it here.
- UChar codeUnits[2];
- int codeUnitsLength;
- if (c <= 0xFFFF) {
- UChar c16 = c;
- if (Font::treatAsSpace(c16))
- codeUnits[0] = ' ';
- else if (Font::treatAsZeroWidthSpace(c16))
- codeUnits[0] = zeroWidthSpace;
- else
- codeUnits[0] = c16;
- codeUnitsLength = 1;
- } else {
- codeUnits[0] = U16_LEAD(c);
- codeUnits[1] = U16_TRAIL(c);
- codeUnitsLength = 2;
- }
- const SimpleFontData* characterFontData = FontCache::getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
- if (useSmallCapsFont)
- characterFontData = characterFontData->smallCapsFontData(m_fontDescription);
- 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();
- // Cache it so we don't have to do system fallback again next time.
- if (!useSmallCapsFont)
- page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
- return data;
- }
-
- // 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();
- if (!useSmallCapsFont)
- page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
- return data;
-}
-
void Font::cachePrimaryFont() const
{
ASSERT(m_fontList);
@@ -293,184 +169,12 @@ void Font::update(PassRefPtr<FontSelector> fontSelector) const
m_pages.clear();
}
-int Font::width(const TextRun& run) const
-{
- return lroundf(floatWidth(run));
-}
-
-int Font::ascent() const
-{
- return primaryFont()->ascent();
-}
-
-int Font::descent() const
-{
- return primaryFont()->descent();
-}
-
-int Font::lineSpacing() const
-{
- return primaryFont()->lineSpacing();
-}
-
-int Font::lineGap() const
-{
- return primaryFont()->lineGap();
-}
-
-float Font::xHeight() const
-{
- return primaryFont()->xHeight();
-}
-
-unsigned Font::unitsPerEm() const
-{
- return primaryFont()->unitsPerEm();
-}
-
-int Font::spaceWidth() const
-{
- return (int)ceilf(primaryFont()->m_adjustedSpaceWidth + m_letterSpacing);
-}
-
bool Font::isFixedPitch() const
{
ASSERT(m_fontList);
return m_fontList->isFixedPitch(this);
}
-void Font::setCodePath(CodePath p)
-{
- s_codePath = p;
-}
-
-Font::CodePath Font::codePath()
-{
- return s_codePath;
-}
-
-bool Font::canUseGlyphCache(const TextRun& run) const
-{
- switch (s_codePath) {
- case Auto:
- break;
- case Simple:
- return true;
- case Complex:
- return false;
- }
-
- // Start from 0 since drawing and highlighting also measure the characters before run->from
- for (int i = 0; i < run.length(); i++) {
- const UChar c = run[i];
- if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
- continue;
- if (c <= 0x36F)
- return false;
-
- if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
- continue;
- if (c <= 0x05CF)
- return false;
-
- if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
- continue;
- if (c <= 0x1059)
- return false;
-
- if (c < 0x1100) // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A)
- continue;
- if (c <= 0x11FF)
- return false;
-
- if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian
- continue;
- if (c <= 0x18AF)
- return false;
-
- if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
- continue;
- if (c <= 0x194F)
- return false;
-
- if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
- continue;
- if (c <= 0x20FF)
- return false;
-
- if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks
- continue;
- if (c <= 0xFE2F)
- return false;
- }
-
- return true;
-
-}
-
-void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- // This glyph buffer holds our glyphs+advances+font data for each glyph.
- GlyphBuffer glyphBuffer;
-
- float startX = point.x();
- WidthIterator it(this, run);
- it.advance(from);
- float beforeWidth = it.m_runWidthSoFar;
- it.advance(to, &glyphBuffer);
-
- // We couldn't generate any glyphs for the run. Give up.
- if (glyphBuffer.isEmpty())
- return;
-
- float afterWidth = it.m_runWidthSoFar;
-
- if (run.rtl()) {
- float finalRoundingWidth = it.m_finalRoundingWidth;
- it.advance(run.length());
- startX += finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
- } else
- startX += beforeWidth;
-
- // Swap the order of the glyphs if right-to-left.
- if (run.rtl())
- for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
- glyphBuffer.swap(i, end);
-
- // Calculate the starting point of the glyphs to be displayed by adding
- // all the advances up to the first glyph.
- FloatPoint startPoint(startX, point.y());
- drawGlyphBuffer(context, glyphBuffer, run, startPoint);
-}
-
-void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer,
- const TextRun& run, const FloatPoint& point) const
-{
- // Draw each contiguous run of glyphs that use the same font data.
- const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
- FloatSize offset = glyphBuffer.offsetAt(0);
- FloatPoint startPoint(point);
- float nextX = startPoint.x();
- int lastFrom = 0;
- int nextGlyph = 0;
- while (nextGlyph < glyphBuffer.size()) {
- const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
- FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
- if (nextFontData != fontData || nextOffset != offset) {
- drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
-
- lastFrom = nextGlyph;
- fontData = nextFontData;
- offset = nextOffset;
- startPoint.setX(nextX);
- }
- nextX += glyphBuffer.advanceAt(nextGlyph);
- nextGlyph++;
- }
-
- drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
-}
-
void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
// Don't draw anything while we are using custom fonts that are in the process of loading.
@@ -486,10 +190,12 @@ void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoi
}
#endif
+#if USE(FONT_FAST_PATH)
if (canUseGlyphCache(run))
- drawSimpleText(context, run, point, from, to);
- else
- drawComplexText(context, run, point, from, to);
+ return drawSimpleText(context, run, point, from, to);
+#endif
+
+ return drawComplexText(context, run, point, from, to);
}
float Font::floatWidth(const TextRun& run) const
@@ -499,8 +205,11 @@ float Font::floatWidth(const TextRun& run) const
return floatWidthUsingSVGFont(run);
#endif
+#if USE(FONT_FAST_PATH)
if (canUseGlyphCache(run))
return floatWidthForSimpleText(run, 0);
+#endif
+
return floatWidthForComplexText(run);
}
@@ -513,16 +222,13 @@ float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsCo
charsConsumed = run.length();
glyphName = "";
+
+#if USE(FONT_FAST_PATH)
if (canUseGlyphCache(run))
return floatWidthForSimpleText(run, 0);
- return floatWidthForComplexText(run);
-}
+#endif
-float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer) const
-{
- WidthIterator it(this, run);
- it.advance(run.length(), glyphBuffer);
- return it.m_runWidthSoFar;
+ return floatWidthForComplexText(run);
}
FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
@@ -533,27 +239,13 @@ FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point,
#endif
to = (to == -1 ? run.length() : to);
+
+#if USE(FONT_FAST_PATH)
if (canUseGlyphCache(run))
return selectionRectForSimpleText(run, point, h, from, to);
- return selectionRectForComplexText(run, point, h, from, to);
-}
+#endif
-FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
-{
- WidthIterator it(this, run);
- it.advance(from);
- float beforeWidth = it.m_runWidthSoFar;
- it.advance(to);
- float afterWidth = it.m_runWidthSoFar;
-
- // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
- if (run.rtl()) {
- it.advance(run.length());
- float totalWidth = it.m_runWidthSoFar;
- return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
- } else {
- return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
- }
+ return selectionRectForComplexText(run, point, h, from, to);
}
int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const
@@ -563,52 +255,12 @@ int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs
return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs);
#endif
+#if USE(FONT_FAST_PATH)
if (canUseGlyphCache(run))
return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
- return offsetForPositionForComplexText(run, x, includePartialGlyphs);
-}
-
-int Font::offsetForPositionForSimpleText(const TextRun& run, int x, bool includePartialGlyphs) const
-{
- float delta = (float)x;
-
- WidthIterator it(this, run);
- GlyphBuffer localGlyphBuffer;
- unsigned offset;
- if (run.rtl()) {
- delta -= floatWidthForSimpleText(run, 0);
- while (1) {
- offset = it.m_currentCharacter;
- float w;
- if (!it.advanceOneCharacter(w, &localGlyphBuffer))
- break;
- delta += w;
- if (includePartialGlyphs) {
- if (delta - w / 2 >= 0)
- break;
- } else {
- if (delta >= 0)
- break;
- }
- }
- } else {
- while (1) {
- offset = it.m_currentCharacter;
- float w;
- if (!it.advanceOneCharacter(w, &localGlyphBuffer))
- break;
- delta -= w;
- if (includePartialGlyphs) {
- if (delta + w / 2 <= 0)
- break;
- } else {
- if (delta <= 0)
- break;
- }
- }
- }
+#endif
- return offset;
+ return offsetForPositionForComplexText(run, x, includePartialGlyphs);
}
#if ENABLE(SVG_FONTS)
diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h
index a99ce12..1bfee8f 100644
--- a/WebCore/platform/graphics/Font.h
+++ b/WebCore/platform/graphics/Font.h
@@ -3,6 +3,7 @@
* (C) 2000 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2003, 2006, 2007 Apple Computer, Inc.
+ * Copyright (C) 2008 Holger Hans Peter Freyther
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -26,11 +27,12 @@
#include "TextRun.h"
#include "FontDescription.h"
+#include "SimpleFontData.h"
#include <wtf/HashMap.h>
+#include <wtf/MathExtras.h>
#if PLATFORM(QT)
-#include <QtGui/qfont.h>
-#include <QtGui/qfontmetrics.h>
+#include <QFont>
#endif
namespace WebCore {
@@ -45,18 +47,18 @@ class GlyphBuffer;
class GlyphPageTreeNode;
class GraphicsContext;
class IntPoint;
-class SimpleFontData;
class SVGFontElement;
struct GlyphData;
+const unsigned defaultUnitsPerEm = 1000;
+
class Font {
public:
Font();
Font(const FontDescription&, short letterSpacing, short wordSpacing);
-#if !PLATFORM(QT)
- Font(const FontPlatformData&, bool isPrinting); // This constructor is only used if the platform wants to start with a native font.
-#endif
+ // This constructor is only used if the platform wants to start with a native font.
+ Font(const FontPlatformData&, bool isPrinting);
~Font();
Font(const Font&);
@@ -76,7 +78,7 @@ public:
void drawText(GraphicsContext*, const TextRun&, const FloatPoint&, int from = 0, int to = -1) const;
- int width(const TextRun&) const;
+ int width(const TextRun& run) const { return lroundf(floatWidth(run)); }
float floatWidth(const TextRun&) const;
float floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const;
@@ -87,13 +89,8 @@ public:
short wordSpacing() const { return m_wordSpacing; }
short letterSpacing() const { return m_letterSpacing; }
-#if !PLATFORM(QT)
void setWordSpacing(short s) { m_wordSpacing = s; }
void setLetterSpacing(short s) { m_letterSpacing = s; }
-#else
- void setWordSpacing(short s);
- void setLetterSpacing(short s);
-#endif
bool isFixedPitch() const;
bool isPrinterFont() const { return m_fontDescription.usePrinterFont(); }
@@ -105,27 +102,19 @@ public:
bool italic() const { return m_fontDescription.italic(); }
FontWeight weight() const { return m_fontDescription.weight(); }
-#if !PLATFORM(QT)
bool isPlatformFont() const { return m_isPlatformFont; }
-#endif
-
-#if PLATFORM(QT)
- inline const QFont &font() const { return m_font; }
- inline const QFont &scFont() const { return m_scFont; }
-#endif
// Metrics that we query the FontFallbackList for.
- int ascent() const;
- int descent() const;
+ int ascent() const { return primaryFont()->ascent(); }
+ int descent() const { return primaryFont()->descent(); }
int height() const { return ascent() + descent(); }
- int lineSpacing() const;
- int lineGap() const;
- float xHeight() const;
- unsigned unitsPerEm() const;
- int spaceWidth() const;
+ int lineSpacing() const { return primaryFont()->lineSpacing(); }
+ 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 tabWidth() const { return 8 * spaceWidth(); }
-#if !PLATFORM(QT)
const SimpleFontData* primaryFont() const {
if (!m_cachedPrimaryFont)
cachePrimaryFont();
@@ -137,9 +126,11 @@ public:
// Used for complex text, and does not utilize the glyph map cache.
const FontData* fontDataForCharacters(const UChar*, int length) const;
+#if PLATFORM(QT)
+ QFont font() const;
+#endif
+
private:
- bool canUseGlyphCache(const TextRun&) const;
- void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
#if ENABLE(SVG_FONTS)
void drawTextUsingSVGFont(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
float floatWidthUsingSVGFont(const TextRun&) const;
@@ -147,24 +138,28 @@ private:
FloatRect selectionRectForTextUsingSVGFont(const TextRun&, const IntPoint&, int h, int from, int to) const;
int offsetForPositionForTextUsingSVGFont(const TextRun&, int position, bool includePartialGlyphs) const;
#endif
+
+#if USE(FONT_FAST_PATH)
+ bool canUseGlyphCache(const TextRun&) const;
+ 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;
- void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
float floatWidthForSimpleText(const TextRun&, GlyphBuffer*) const;
- float floatWidthForComplexText(const TextRun&) const;
int offsetForPositionForSimpleText(const TextRun&, int position, bool includePartialGlyphs) const;
- int offsetForPositionForComplexText(const TextRun&, int position, bool includePartialGlyphs) const;
FloatRect selectionRectForSimpleText(const TextRun&, const IntPoint&, int h, int from, int to) const;
+#endif
+
+ void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
+ float floatWidthForComplexText(const TextRun&) 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;
-#endif
+
friend struct WidthIterator;
public:
-#if PLATFORM(QT)
- FontSelector* fontSelector() const { return 0; }
-#else
// Useful for debugging the different font rendering code paths.
+#if USE(FONT_FAST_PATH)
enum CodePath { Auto, Simple, Complex };
static void setCodePath(CodePath);
static CodePath codePath();
@@ -175,9 +170,9 @@ public:
{
return (((c & ~0xFF) == 0 && gRoundingHackCharacterTable[c]));
}
+#endif
FontSelector* fontSelector() const;
-#endif
static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0; }
static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == 0x200e || c == 0x200f || (c >= 0x202a && c <= 0x202e) || c == 0xFFFC; }
@@ -188,21 +183,13 @@ public:
private:
FontDescription m_fontDescription;
-#if !PLATFORM(QT)
mutable RefPtr<FontFallbackList> m_fontList;
mutable HashMap<int, GlyphPageTreeNode*> m_pages;
mutable GlyphPageTreeNode* m_pageZero;
mutable const SimpleFontData* m_cachedPrimaryFont;
-#endif
short m_letterSpacing;
short m_wordSpacing;
-#if !PLATFORM(QT)
bool m_isPlatformFont;
-#else
- QFont m_font;
- QFont m_scFont;
- int m_spaceWidth;
-#endif
};
}
diff --git a/WebCore/platform/graphics/FontCache.cpp b/WebCore/platform/graphics/FontCache.cpp
index 1c5a987..2d219be 100644
--- a/WebCore/platform/graphics/FontCache.cpp
+++ b/WebCore/platform/graphics/FontCache.cpp
@@ -37,11 +37,22 @@
#include "StringHash.h"
#include <wtf/HashMap.h>
#include <wtf/ListHashSet.h>
+#include <wtf/StdLibExtras.h>
using namespace WTF;
namespace WebCore {
+FontCache* fontCache()
+{
+ DEFINE_STATIC_LOCAL(FontCache, globalFontCache, ());
+ return &globalFontCache;
+}
+
+FontCache::FontCache()
+{
+}
+
struct FontPlatformDataCacheKey {
FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, unsigned weight = 0, bool italic = false,
bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode)
@@ -104,7 +115,7 @@ struct FontPlatformDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformDataC
static const bool emptyValueIsZero = true;
static const FontPlatformDataCacheKey& emptyValue()
{
- static FontPlatformDataCacheKey key(nullAtom);
+ DEFINE_STATIC_LOCAL(FontPlatformDataCacheKey, key, (nullAtom));
return key;
}
static void constructDeletedValue(FontPlatformDataCacheKey& slot)
@@ -124,21 +135,24 @@ static FontPlatformDataCache* gFontPlatformDataCache = 0;
static const AtomicString& alternateFamilyName(const AtomicString& familyName)
{
// Alias Courier <-> Courier New
- static AtomicString courier("Courier"), courierNew("Courier New");
+ DEFINE_STATIC_LOCAL(AtomicString, courier, ("Courier"));
+ DEFINE_STATIC_LOCAL(AtomicString, courierNew, ("Courier New"));
if (equalIgnoringCase(familyName, courier))
return courierNew;
if (equalIgnoringCase(familyName, courierNew))
return courier;
// Alias Times and Times New Roman.
- static AtomicString times("Times"), timesNewRoman("Times New Roman");
+ DEFINE_STATIC_LOCAL(AtomicString, times, ("Times"));
+ DEFINE_STATIC_LOCAL(AtomicString, timesNewRoman, ("Times New Roman"));
if (equalIgnoringCase(familyName, times))
return timesNewRoman;
if (equalIgnoringCase(familyName, timesNewRoman))
return times;
// Alias Arial and Helvetica
- static AtomicString arial("Arial"), helvetica("Helvetica");
+ DEFINE_STATIC_LOCAL(AtomicString, arial, ("Arial"));
+ DEFINE_STATIC_LOCAL(AtomicString, helvetica, ("Helvetica"));
if (equalIgnoringCase(familyName, arial))
return helvetica;
if (equalIgnoringCase(familyName, helvetica))
@@ -202,7 +216,7 @@ struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> {
static const bool needsDestruction = true;
static const FontPlatformData& emptyValue()
{
- static FontPlatformData key;
+ DEFINE_STATIC_LOCAL(FontPlatformData, key, ());
return key;
}
static void constructDeletedValue(FontPlatformData& slot)
diff --git a/WebCore/platform/graphics/FontCache.h b/WebCore/platform/graphics/FontCache.h
index 816fe64..8820045 100644
--- a/WebCore/platform/graphics/FontCache.h
+++ b/WebCore/platform/graphics/FontCache.h
@@ -51,45 +51,51 @@ class SimpleFontData;
class FontCache {
public:
- static const FontData* getFontData(const Font&, int& familyIndex, FontSelector*);
- static void releaseFontData(const SimpleFontData*);
+ friend FontCache* fontCache();
+
+ const FontData* getFontData(const Font&, int& familyIndex, FontSelector*);
+ void releaseFontData(const SimpleFontData*);
// This method is implemented by the platform.
// FIXME: Font data returned by this method never go inactive because callers don't track and release them.
- static const SimpleFontData* getFontDataForCharacters(const Font&, const UChar* characters, int length);
+ const SimpleFontData* getFontDataForCharacters(const Font&, const UChar* characters, int length);
// Also implemented by the platform.
- static void platformInit();
+ void platformInit();
#if PLATFORM(WIN)
- static IMLangFontLink2* getFontLinkInterface();
+ IMLangFontLink2* getFontLinkInterface();
#endif
- static void getTraitsInFamily(const AtomicString&, Vector<unsigned>&);
+ void getTraitsInFamily(const AtomicString&, Vector<unsigned>&);
- static FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false);
- static SimpleFontData* getCachedFontData(const FontPlatformData*);
- static FontPlatformData* getLastResortFallbackFont(const FontDescription&);
+ FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false);
+ SimpleFontData* getCachedFontData(const FontPlatformData*);
+ FontPlatformData* getLastResortFallbackFont(const FontDescription&);
- static void addClient(FontSelector*);
- static void removeClient(FontSelector*);
+ void addClient(FontSelector*);
+ void removeClient(FontSelector*);
- static unsigned generation();
- static void invalidate();
+ unsigned generation();
+ void invalidate();
- static size_t fontDataCount();
- static size_t inactiveFontDataCount();
- static void purgeInactiveFontData(int count = INT_MAX);
+ size_t fontDataCount();
+ size_t inactiveFontDataCount();
+ void purgeInactiveFontData(int count = INT_MAX);
private:
+ FontCache();
+
// These methods are implemented by each platform.
- static FontPlatformData* getSimilarFontPlatformData(const Font&);
- static FontPlatformData* createFontPlatformData(const FontDescription&, const AtomicString& family);
+ FontPlatformData* getSimilarFontPlatformData(const Font&);
+ FontPlatformData* createFontPlatformData(const FontDescription&, const AtomicString& family);
friend class SimpleFontData;
friend class FontFallbackList;
};
+// Get the global fontCache.
+FontCache* fontCache();
}
#endif
diff --git a/WebCore/platform/graphics/FontFallbackList.cpp b/WebCore/platform/graphics/FontFallbackList.cpp
index ef59c2f..06d52d7 100644
--- a/WebCore/platform/graphics/FontFallbackList.cpp
+++ b/WebCore/platform/graphics/FontFallbackList.cpp
@@ -40,7 +40,7 @@ FontFallbackList::FontFallbackList()
, m_pitch(UnknownPitch)
, m_loadingCustomFonts(false)
, m_fontSelector(0)
- , m_generation(FontCache::generation())
+ , m_generation(fontCache()->generation())
{
}
@@ -52,7 +52,7 @@ void FontFallbackList::invalidate(PassRefPtr<FontSelector> fontSelector)
m_pitch = UnknownPitch;
m_loadingCustomFonts = false;
m_fontSelector = fontSelector;
- m_generation = FontCache::generation();
+ m_generation = fontCache()->generation();
}
void FontFallbackList::releaseFontData()
@@ -61,7 +61,7 @@ void FontFallbackList::releaseFontData()
for (unsigned i = 0; i < numFonts; ++i) {
if (!m_fontList[i].second) {
ASSERT(!m_fontList[i].first->isSegmented());
- FontCache::releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].first));
+ fontCache()->releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].first));
}
}
}
@@ -96,8 +96,8 @@ const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realized
// We are obtaining this font for the first time. We keep track of the families we've looked at before
// in |m_familyIndex|, so that we never scan the same spot in the list twice. getFontData will adjust our
// |m_familyIndex| as it scans for the right font to make.
- ASSERT(FontCache::generation() == m_generation);
- const FontData* result = FontCache::getFontData(*font, m_familyIndex, m_fontSelector.get());
+ ASSERT(fontCache()->generation() == m_generation);
+ const FontData* result = fontCache()->getFontData(*font, m_familyIndex, m_fontSelector.get());
if (result) {
m_fontList.append(pair<const FontData*, bool>(result, result->isCustomFont()));
if (result->isLoading())
@@ -116,8 +116,8 @@ const FontData* FontFallbackList::fontDataForCharacters(const Font* font, const
fontData = fontDataAt(font, ++realizedFontIndex);
if (!fontData) {
- ASSERT(FontCache::generation() == m_generation);
- fontData = FontCache::getFontDataForCharacters(*font, characters, length);
+ ASSERT(fontCache()->generation() == m_generation);
+ fontData = fontCache()->getFontDataForCharacters(*font, characters, length);
}
return fontData;
@@ -126,8 +126,8 @@ const FontData* FontFallbackList::fontDataForCharacters(const Font* font, const
void FontFallbackList::setPlatformFont(const FontPlatformData& platformData)
{
m_familyIndex = cAllFamiliesScanned;
- ASSERT(FontCache::generation() == m_generation);
- const FontData* fontData = FontCache::getCachedFontData(&platformData);
+ ASSERT(fontCache()->generation() == m_generation);
+ const FontData* fontData = fontCache()->getCachedFontData(&platformData);
m_fontList.append(pair<const FontData*, bool>(fontData, fontData->isCustomFont()));
}
diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp
new file mode 100644
index 0000000..635aba9
--- /dev/null
+++ b/WebCore/platform/graphics/FontFastPath.cpp
@@ -0,0 +1,367 @@
+/**
+ * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ * Copyright (C) 2008 Holger Hans Peter Freyther
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Font.h"
+
+#include "CharacterNames.h"
+#include "FontCache.h"
+#include "FloatRect.h"
+#include "GlyphBuffer.h"
+#include "GlyphPageTreeNode.h"
+#include "IntPoint.h"
+#include "SimpleFontData.h"
+#include "WidthIterator.h"
+
+#include <wtf/unicode/Unicode.h>
+#include <wtf/MathExtras.h>
+
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCaps) const
+{
+ bool useSmallCapsFont = forceSmallCaps;
+ if (m_fontDescription.smallCaps()) {
+ UChar32 upperC = Unicode::toUpper(c);
+ if (upperC != c) {
+ c = upperC;
+ useSmallCapsFont = true;
+ }
+ }
+
+ if (mirror)
+ c = mirroredChar(c);
+
+ unsigned pageNumber = (c / GlyphPage::size);
+
+ GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero;
+ if (!node) {
+ node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
+ if (pageNumber)
+ m_pages.set(pageNumber, node);
+ else
+ m_pageZero = node;
+ }
+
+ GlyphPage* page;
+ if (!useSmallCapsFont) {
+ // Fastest loop, for the common case (not small caps).
+ while (true) {
+ page = node->page();
+ if (page) {
+ const GlyphData& data = page->glyphDataForCharacter(c);
+ if (data.fontData)
+ return data;
+ if (node->isSystemFallback())
+ break;
+ }
+
+ // Proceed with the fallback list.
+ node = node->getChild(fontDataAt(node->level()), pageNumber);
+ if (pageNumber)
+ m_pages.set(pageNumber, node);
+ else
+ m_pageZero = node;
+ }
+ } else {
+ while (true) {
+ page = node->page();
+ if (page) {
+ const 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.
+ const SimpleFontData* smallCapsFontData = data.fontData->smallCapsFontData(m_fontDescription);
+ if (!smallCapsFontData)
+ return data;
+
+ GlyphPageTreeNode* smallCapsNode = GlyphPageTreeNode::getRootChild(smallCapsFontData, pageNumber);
+ const GlyphPage* smallCapsPage = smallCapsNode->page();
+ if (smallCapsPage) {
+ const GlyphData& data = smallCapsPage->glyphDataForCharacter(c);
+ if (data.fontData)
+ return data;
+ }
+
+ // Do not attempt system fallback off the smallCapsFontData. This is the very unlikely case that
+ // a font has the lowercase character but the small caps font does not have its uppercase version.
+ return smallCapsFontData->missingGlyphData();
+ }
+
+ if (node->isSystemFallback())
+ break;
+ }
+
+ // Proceed with the fallback list.
+ node = node->getChild(fontDataAt(node->level()), pageNumber);
+ if (pageNumber)
+ m_pages.set(pageNumber, node);
+ else
+ m_pageZero = node;
+ }
+ }
+
+ ASSERT(page);
+ ASSERT(node->isSystemFallback());
+
+ // System fallback is character-dependent. When we get here, we
+ // know that the character in question isn't in the system fallback
+ // font's glyph page. Try to lazily create it here.
+ UChar codeUnits[2];
+ int codeUnitsLength;
+ if (c <= 0xFFFF) {
+ UChar c16 = c;
+ if (Font::treatAsSpace(c16))
+ codeUnits[0] = ' ';
+ else if (Font::treatAsZeroWidthSpace(c16))
+ codeUnits[0] = zeroWidthSpace;
+ else
+ codeUnits[0] = c16;
+ codeUnitsLength = 1;
+ } else {
+ codeUnits[0] = U16_LEAD(c);
+ codeUnits[1] = U16_TRAIL(c);
+ codeUnitsLength = 2;
+ }
+ const SimpleFontData* characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
+ if (useSmallCapsFont && characterFontData)
+ characterFontData = characterFontData->smallCapsFontData(m_fontDescription);
+ 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();
+ // Cache it so we don't have to do system fallback again next time.
+ if (!useSmallCapsFont)
+ page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
+ return data;
+ }
+
+ // 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();
+ if (!useSmallCapsFont)
+ page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
+ return data;
+}
+
+void Font::setCodePath(CodePath p)
+{
+ s_codePath = p;
+}
+
+Font::CodePath Font::codePath()
+{
+ return s_codePath;
+}
+
+bool Font::canUseGlyphCache(const TextRun& run) const
+{
+ switch (s_codePath) {
+ case Auto:
+ break;
+ case Simple:
+ return true;
+ case Complex:
+ return false;
+ }
+
+ // Start from 0 since drawing and highlighting also measure the characters before run->from
+ for (int i = 0; i < run.length(); i++) {
+ const UChar c = run[i];
+ if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
+ continue;
+ if (c <= 0x36F)
+ return false;
+
+ if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
+ continue;
+ if (c <= 0x05CF)
+ return false;
+
+ if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
+ continue;
+ if (c <= 0x1059)
+ return false;
+
+ if (c < 0x1100) // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A)
+ continue;
+ if (c <= 0x11FF)
+ return false;
+
+ if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian
+ continue;
+ if (c <= 0x18AF)
+ return false;
+
+ if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
+ continue;
+ if (c <= 0x194F)
+ return false;
+
+ if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
+ continue;
+ if (c <= 0x20FF)
+ return false;
+
+ if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks
+ continue;
+ if (c <= 0xFE2F)
+ return false;
+ }
+
+ return true;
+
+}
+
+void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ // This glyph buffer holds our glyphs+advances+font data for each glyph.
+ GlyphBuffer glyphBuffer;
+
+ float startX = point.x();
+ WidthIterator it(this, run);
+ it.advance(from);
+ float beforeWidth = it.m_runWidthSoFar;
+ it.advance(to, &glyphBuffer);
+
+ // We couldn't generate any glyphs for the run. Give up.
+ if (glyphBuffer.isEmpty())
+ return;
+
+ float afterWidth = it.m_runWidthSoFar;
+
+ if (run.rtl()) {
+ float finalRoundingWidth = it.m_finalRoundingWidth;
+ it.advance(run.length());
+ startX += finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
+ } else
+ startX += beforeWidth;
+
+ // Swap the order of the glyphs if right-to-left.
+ if (run.rtl())
+ for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
+ glyphBuffer.swap(i, end);
+
+ // Calculate the starting point of the glyphs to be displayed by adding
+ // all the advances up to the first glyph.
+ FloatPoint startPoint(startX, point.y());
+ drawGlyphBuffer(context, glyphBuffer, run, startPoint);
+}
+
+void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const TextRun&, const FloatPoint& point) const
+{
+ // Draw each contiguous run of glyphs that use the same font data.
+ const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
+ FloatSize offset = glyphBuffer.offsetAt(0);
+ FloatPoint startPoint(point);
+ float nextX = startPoint.x();
+ int lastFrom = 0;
+ int nextGlyph = 0;
+ while (nextGlyph < glyphBuffer.size()) {
+ const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
+ FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
+ if (nextFontData != fontData || nextOffset != offset) {
+ drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+
+ lastFrom = nextGlyph;
+ fontData = nextFontData;
+ offset = nextOffset;
+ startPoint.setX(nextX);
+ }
+ nextX += glyphBuffer.advanceAt(nextGlyph);
+ nextGlyph++;
+ }
+
+ drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+}
+
+float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer) const
+{
+ WidthIterator it(this, run);
+ it.advance(run.length(), glyphBuffer);
+ return it.m_runWidthSoFar;
+}
+
+FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
+{
+ WidthIterator it(this, run);
+ it.advance(from);
+ float beforeWidth = it.m_runWidthSoFar;
+ it.advance(to);
+ float afterWidth = it.m_runWidthSoFar;
+
+ // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
+ if (run.rtl()) {
+ it.advance(run.length());
+ float totalWidth = it.m_runWidthSoFar;
+ return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
+ } else {
+ return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
+ }
+}
+
+int Font::offsetForPositionForSimpleText(const TextRun& run, int x, bool includePartialGlyphs) const
+{
+ float delta = (float)x;
+
+ WidthIterator it(this, run);
+ GlyphBuffer localGlyphBuffer;
+ unsigned offset;
+ if (run.rtl()) {
+ delta -= floatWidthForSimpleText(run, 0);
+ while (1) {
+ offset = it.m_currentCharacter;
+ float w;
+ if (!it.advanceOneCharacter(w, &localGlyphBuffer))
+ break;
+ delta += w;
+ if (includePartialGlyphs) {
+ if (delta - w / 2 >= 0)
+ break;
+ } else {
+ if (delta >= 0)
+ break;
+ }
+ }
+ } else {
+ while (1) {
+ offset = it.m_currentCharacter;
+ float w;
+ if (!it.advanceOneCharacter(w, &localGlyphBuffer))
+ break;
+ delta -= w;
+ if (includePartialGlyphs) {
+ if (delta + w / 2 <= 0)
+ break;
+ } else {
+ if (delta <= 0)
+ break;
+ }
+ }
+ }
+
+ return offset;
+}
+
+}
diff --git a/WebCore/platform/graphics/GeneratedImage.cpp b/WebCore/platform/graphics/GeneratedImage.cpp
index 5e50959..15e27d7 100644
--- a/WebCore/platform/graphics/GeneratedImage.cpp
+++ b/WebCore/platform/graphics/GeneratedImage.cpp
@@ -47,7 +47,7 @@ void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, co
context->restore();
}
-void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
+void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect)
{
// Create a BitmapImage and call drawPattern on it.
diff --git a/WebCore/platform/graphics/GeneratedImage.h b/WebCore/platform/graphics/GeneratedImage.h
index fb0661b..dea0c54 100644
--- a/WebCore/platform/graphics/GeneratedImage.h
+++ b/WebCore/platform/graphics/GeneratedImage.h
@@ -53,15 +53,14 @@ public:
virtual IntSize size() const { return m_size; }
// Assume that generated content has no decoded data we need to worry about
- virtual void destroyDecodedData(bool incremental = false, bool preserveNearbyFrames = false) { }
+ virtual void destroyDecodedData(bool /*destroyAll*/ = true) { }
virtual unsigned decodedSize() const { return 0; }
protected:
virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
- virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
+ virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
-protected:
GeneratedImage(PassRefPtr<Generator> generator, const IntSize& size)
: m_generator(generator)
, m_size(size)
diff --git a/WebCore/platform/graphics/GlyphBuffer.h b/WebCore/platform/graphics/GlyphBuffer.h
index 18957d5..fdb306f 100644
--- a/WebCore/platform/graphics/GlyphBuffer.h
+++ b/WebCore/platform/graphics/GlyphBuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 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
@@ -30,14 +30,16 @@
#define GlyphBuffer_h
#include "FloatSize.h"
+#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
#if PLATFORM(CG)
#include <ApplicationServices/ApplicationServices.h>
-#elif PLATFORM(CAIRO)
-#include <cairo.h>
#endif
-#include <wtf/Vector.h>
+#if PLATFORM(CAIRO)
+#include <cairo.h>
+#endif
namespace WebCore {
@@ -125,6 +127,7 @@ public:
#if PLATFORM(WIN)
return m_offsets[index];
#else
+ UNUSED_PARAM(index);
return FloatSize();
#endif
}
@@ -132,6 +135,7 @@ public:
void add(Glyph glyph, const SimpleFontData* font, float width, const FloatSize* offset = 0)
{
m_fontData.append(font);
+
#if PLATFORM(CAIRO)
cairo_glyph_t cairoGlyph;
cairoGlyph.index = glyph;
@@ -152,6 +156,8 @@ public:
m_offsets.append(*offset);
else
m_offsets.append(FloatSize());
+#else
+ UNUSED_PARAM(offset);
#endif
}
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index 9cd2969..8426011 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -109,17 +109,6 @@ void GraphicsContext::restore()
restorePlatformState();
}
-const Font& GraphicsContext::font() const
-{
- return m_common->state.font;
-}
-
-void GraphicsContext::setFont(const Font& aFont)
-{
- m_common->state.font = aFont;
- setPlatformFont(aFont);
-}
-
void GraphicsContext::setStrokeThickness(float thickness)
{
m_common->state.strokeThickness = thickness;
@@ -211,6 +200,17 @@ Color GraphicsContext::fillColor() const
return m_common->state.fillColor;
}
+void GraphicsContext::setShouldAntialias(bool b)
+{
+ m_common->state.shouldAntialias = b;
+ setPlatformShouldAntialias(b);
+}
+
+bool GraphicsContext::shouldAntialias() const
+{
+ return m_common->state.shouldAntialias;
+}
+
void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
{
ASSERT(pattern);
@@ -255,6 +255,11 @@ void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
m_common->state.fillGradient = gradient;
}
+void GraphicsContext::setShadowsIgnoreTransforms(bool ignoreTransforms)
+{
+ m_common->state.shadowsIgnoreTransforms = ignoreTransforms;
+}
+
bool GraphicsContext::updatingControlTints() const
{
return m_common->m_updatingControlTints;
@@ -296,15 +301,15 @@ void GraphicsContext::drawImage(Image* image, const IntRect& dest, const IntRect
drawImage(image, FloatRect(dest), srcRect, op, useLowQualityScale);
}
-void GraphicsContext::drawText(const TextRun& run, const IntPoint& point, int from, int to)
+void GraphicsContext::drawText(const Font& font, const TextRun& run, const IntPoint& point, int from, int to)
{
if (paintingDisabled())
return;
- font().drawText(this, run, point, from, to);
+ font.drawText(this, run, point, from, to);
}
-void GraphicsContext::drawBidiText(const TextRun& run, const FloatPoint& point)
+void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const FloatPoint& point)
{
if (paintingDisabled())
return;
@@ -329,23 +334,23 @@ void GraphicsContext::drawBidiText(const TextRun& run, const FloatPoint& point)
subrun.setRTL(bidiRun->level() % 2);
subrun.setDirectionalOverride(bidiRun->dirOverride(false));
- font().drawText(this, subrun, currPoint);
+ font.drawText(this, subrun, currPoint);
bidiRun = bidiRun->next();
// FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here.
if (bidiRun)
- currPoint.move(font().floatWidth(subrun), 0.f);
+ currPoint.move(font.floatWidth(subrun), 0.f);
}
bidiResolver.deleteRuns();
}
-void GraphicsContext::drawHighlightForText(const TextRun& run, const IntPoint& point, int h, const Color& backgroundColor, int from, int to)
+void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const IntPoint& point, int h, const Color& backgroundColor, int from, int to)
{
if (paintingDisabled())
return;
- fillRect(font().selectionRectForText(run, point, h, from, to), backgroundColor);
+ fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor);
}
void GraphicsContext::initFocusRing(int width, int offset)
@@ -498,10 +503,4 @@ void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle&)
}
#endif
-#if !PLATFORM(QT)
-void GraphicsContext::setPlatformFont(const Font&)
-{
-}
-#endif
-
}
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index 95bdc90..c27f38f 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -98,7 +98,7 @@ namespace WebCore {
const int cMisspellingLinePatternWidth = 4;
const int cMisspellingLinePatternGapWidth = 1;
- class AffineTransform;
+ class TransformationMatrix;
class Font;
class Generator;
class Gradient;
@@ -145,9 +145,6 @@ namespace WebCore {
~GraphicsContext();
PlatformGraphicsContext* platformContext() const;
-
- const Font& font() const;
- void setFont(const Font&);
float strokeThickness() const;
void setStrokeThickness(float);
@@ -166,6 +163,15 @@ namespace WebCore {
void setFillColor(const Color&);
void setFillPattern(PassRefPtr<Pattern>);
void setFillGradient(PassRefPtr<Gradient>);
+ void setShadowsIgnoreTransforms(bool);
+
+ void setShouldAntialias(bool);
+ bool shouldAntialias() const;
+
+#if PLATFORM(CG)
+ void applyStrokePattern();
+ void applyFillPattern();
+#endif
#if PLATFORM(SGL)
/* these should be pused to apple. needed for CanvasStyle.cpp */
@@ -183,6 +189,10 @@ namespace WebCore {
bool willFill() const;
// returns true if there is a valid (non-transparent) stroke color
bool willStroke() const;
+
+ // may return NULL, since we lazily allocate the path. This is the path
+ // that is drawn by drawPath()
+ const SkPath* getCurrPath() const;
/** platform-specific factory method to return a bitmap graphicscontext,
called by <canvas> when we need to draw offscreen. Caller is responsible for
@@ -239,14 +249,15 @@ namespace WebCore {
void clipOut(const IntRect&);
void clipOutEllipseInRect(const IntRect&);
void clipOutRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight);
+ void clipPath(WindRule);
void clipToImageBuffer(const FloatRect&, const ImageBuffer*);
int textDrawingMode();
void setTextDrawingMode(int);
- void drawText(const TextRun&, const IntPoint&, int from = 0, int to = -1);
- void drawBidiText(const TextRun&, const FloatPoint&);
- void drawHighlightForText(const TextRun&, const IntPoint&, int h, const Color& backgroundColor, int from = 0, int to = -1);
+ void drawText(const Font&, const TextRun&, const IntPoint&, int from = 0, int to = -1);
+ void drawBidiText(const Font&, const TextRun&, const FloatPoint&);
+ void drawHighlightForText(const Font&, const TextRun&, const IntPoint&, int h, const Color& backgroundColor, int from = 0, int to = -1);
FloatRect roundToDevicePixels(const FloatRect&);
@@ -297,10 +308,8 @@ namespace WebCore {
void setURLForRect(const KURL&, const IntRect&);
- void concatCTM(const AffineTransform&);
- AffineTransform getCTM() const;
-
- void setUseAntialiasing(bool = true);
+ void concatCTM(const TransformationMatrix&);
+ TransformationMatrix getCTM() const;
#if PLATFORM(WIN)
GraphicsContext(HDC, bool hasAlpha = false); // FIXME: To be removed.
@@ -308,6 +317,17 @@ namespace WebCore {
HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true); // The passed in rect is used to create a bitmap for compositing inside transparency layers.
void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true); // The passed in HDC should be the one handed back by getWindowsContext.
+ // When set to true, child windows should be rendered into this context
+ // rather than allowing them just to render to the screen. Defaults to
+ // false.
+ // FIXME: This is a layering violation. GraphicsContext shouldn't know
+ // what a "window" is. It would be much more appropriate for this flag
+ // to be passed as a parameter alongside the GraphicsContext, but doing
+ // that would require lots of changes in cross-platform code that we
+ // aren't sure we want to make.
+ void setShouldIncludeChildWindows(bool);
+ bool shouldIncludeChildWindows() const;
+
class WindowsBitmap : public Noncopyable {
public:
WindowsBitmap(HDC, IntSize);
@@ -341,6 +361,7 @@ namespace WebCore {
#if PLATFORM(QT)
bool inTransparencyLayer() const;
PlatformPath* currentPath();
+ QPen pen();
#endif
#if PLATFORM(GTK)
@@ -362,6 +383,8 @@ namespace WebCore {
void setPlatformFillColor(const Color&);
+ void setPlatformShouldAntialias(bool b);
+
void setPlatformShadow(const IntSize&, int blur, const Color&);
void clearPlatformShadow();
diff --git a/WebCore/platform/graphics/GraphicsContextPrivate.h b/WebCore/platform/graphics/GraphicsContextPrivate.h
index de94527..87123eb 100644
--- a/WebCore/platform/graphics/GraphicsContextPrivate.h
+++ b/WebCore/platform/graphics/GraphicsContextPrivate.h
@@ -26,7 +26,7 @@
#ifndef GraphicsContextPrivate_h
#define GraphicsContextPrivate_h
-#include "Font.h"
+#include "TransformationMatrix.h"
#include "Gradient.h"
#include "GraphicsContext.h"
#include "Pattern.h"
@@ -58,18 +58,21 @@ namespace WebCore {
, fillRule(RULE_NONZERO)
, fillColorSpace(SolidColorSpace)
, fillColor(Color::black)
+ , shouldAntialias(true)
, paintingDisabled(false)
, shadowBlur(0)
+ , shadowsIgnoreTransforms(false)
{
}
- Font font;
int textDrawingMode;
StrokeStyle strokeStyle;
float strokeThickness;
#if PLATFORM(CAIRO)
float globalAlpha;
+#elif PLATFORM(QT)
+ TransformationMatrix pathTransform;
#endif
ColorSpace strokeColorSpace;
Color strokeColor;
@@ -83,11 +86,15 @@ namespace WebCore {
RefPtr<Gradient> fillGradient;
RefPtr<Pattern> fillPattern;
+ bool shouldAntialias;
+
bool paintingDisabled;
IntSize shadowSize;
unsigned shadowBlur;
Color shadowColor;
+
+ bool shadowsIgnoreTransforms;
};
class GraphicsContextPrivate {
diff --git a/WebCore/platform/graphics/Image.cpp b/WebCore/platform/graphics/Image.cpp
index ca6954e..49961e1 100644
--- a/WebCore/platform/graphics/Image.cpp
+++ b/WebCore/platform/graphics/Image.cpp
@@ -27,11 +27,12 @@
#include "config.h"
#include "Image.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "BitmapImage.h"
#include "GraphicsContext.h"
#include "IntRect.h"
#include "MIMETypeRegistry.h"
+#include <wtf/StdLibExtras.h>
#include <math.h>
@@ -52,7 +53,7 @@ Image::~Image()
Image* Image::nullImage()
{
- static RefPtr<Image> nullImage = BitmapImage::create();
+ DEFINE_STATIC_LOCAL(RefPtr<Image>, nullImage, (BitmapImage::create()));;
return nullImage.get();
}
@@ -61,11 +62,6 @@ bool Image::supportsType(const String& type)
return MIMETypeRegistry::isSupportedImageResourceMIMEType(type);
}
-bool Image::isNull() const
-{
- return size().isEmpty();
-}
-
bool Image::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
{
m_data = data;
@@ -79,21 +75,6 @@ bool Image::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
return dataChanged(allDataReceived);
}
-IntRect Image::rect() const
-{
- return IntRect(IntPoint(), size());
-}
-
-int Image::width() const
-{
- return size().width();
-}
-
-int Image::height() const
-{
- return size().height();
-}
-
void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op)
{
if (color.alpha() <= 0)
@@ -138,7 +119,7 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const Fl
FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(),
scaledTileSize.height() / intrinsicTileSize.height());
- AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height());
+ TransformationMatrix patternTransform = TransformationMatrix().scale(scale.width(), scale.height());
FloatRect oneTileRect;
oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width()));
@@ -177,7 +158,7 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const Flo
vRule = RepeatTile;
FloatSize scale = calculatePatternScale(dstRect, srcRect, hRule, vRule);
- AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height());
+ TransformationMatrix patternTransform = TransformationMatrix().scale(scale.width(), scale.height());
// We want to construct the phase such that the pattern is centered (when stretch is not
// set for a particular rule).
diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h
index 1419b2d..c3cf2e7 100644
--- a/WebCore/platform/graphics/Image.h
+++ b/WebCore/platform/graphics/Image.h
@@ -30,6 +30,7 @@
#include "Color.h"
#include "GraphicsTypes.h"
#include "ImageSource.h"
+#include "IntRect.h"
#include <wtf/RefPtr.h>
#include <wtf/PassRefPtr.h>
#include "SharedBuffer.h"
@@ -66,13 +67,11 @@ class SkBitmapRef;
namespace WebCore {
-class AffineTransform;
+class TransformationMatrix;
class FloatPoint;
class FloatRect;
class FloatSize;
class GraphicsContext;
-class IntRect;
-class IntSize;
class SharedBuffer;
class String;
@@ -96,7 +95,7 @@ public:
virtual bool hasSingleSecurityOrigin() const { return false; }
static Image* nullImage();
- bool isNull() const;
+ bool isNull() const { return size().isEmpty(); }
// These are only used for SVGImage right now
virtual void setContainerSize(const IntSize&) { }
@@ -105,14 +104,16 @@ public:
virtual bool hasRelativeHeight() const { return false; }
virtual IntSize size() const = 0;
- IntRect rect() const;
- int width() const;
- int height() const;
+ IntRect rect() const { return IntRect(IntPoint(), size()); }
+ int width() const { return size().width(); }
+ int height() const { return size().height(); }
bool setData(PassRefPtr<SharedBuffer> data, bool allDataReceived);
- virtual bool dataChanged(bool allDataReceived) { return false; }
+ virtual bool dataChanged(bool /*allDataReceived*/) { return false; }
+
+ virtual String filenameExtension() const { return String(); } // null string if unknown
- virtual void destroyDecodedData(bool incremental = false, bool preserveNearbyFrames = false) = 0;
+ virtual void destroyDecodedData(bool destroyAll = true) = 0;
virtual unsigned decodedSize() const = 0;
SharedBuffer* data() { return m_data.get(); }
@@ -166,9 +167,9 @@ protected:
virtual bool mayFillWithSolidColor() const { return false; }
virtual Color solidColor() const { return Color(); }
- virtual void startAnimation() { }
+ virtual void startAnimation(bool /*catchUpIfNecessary*/ = true) { }
- virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
+ virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
#if PLATFORM(CG)
// These are private to CG. Ideally they would be only in the .cpp file, but the callback requires access
diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h
index 7c68fc8..14f7461 100644
--- a/WebCore/platform/graphics/ImageBuffer.h
+++ b/WebCore/platform/graphics/ImageBuffer.h
@@ -27,6 +27,7 @@
#ifndef ImageBuffer_h
#define ImageBuffer_h
+#include "TransformationMatrix.h"
#include "Image.h"
#include "IntSize.h"
#include "ImageBufferData.h"
@@ -67,7 +68,11 @@ namespace WebCore {
void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint);
String toDataURL(const String& mimeType) const;
-
+#if !PLATFORM(CG)
+ TransformationMatrix baseTransform() const { return TransformationMatrix(); }
+#else
+ TransformationMatrix baseTransform() const { return TransformationMatrix(1, 0, 0, -1, 0, m_size.height()); }
+#endif
private:
ImageBufferData m_data;
diff --git a/WebCore/platform/graphics/ImageObserver.h b/WebCore/platform/graphics/ImageObserver.h
index 4be83bd..8b693d9 100644
--- a/WebCore/platform/graphics/ImageObserver.h
+++ b/WebCore/platform/graphics/ImageObserver.h
@@ -29,6 +29,7 @@
namespace WebCore {
class Image;
+class IntRect;
// Interface for notification about changes to an image, including decoding,
// drawing, and animating.
@@ -41,6 +42,8 @@ public:
virtual bool shouldPauseAnimation(const Image*) = 0;
virtual void animationAdvanced(const Image*) = 0;
+
+ virtual void changedInRect(const Image*, const IntRect&) = 0;
};
}
diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h
index a9f346d..55e0c5a 100644
--- a/WebCore/platform/graphics/ImageSource.h
+++ b/WebCore/platform/graphics/ImageSource.h
@@ -55,6 +55,7 @@ namespace WebCore {
class IntSize;
class SharedBuffer;
+class String;
#if PLATFORM(WX)
class ImageDecoder;
@@ -94,22 +95,49 @@ public:
ImageSource();
~ImageSource();
- void clear();
+ // Tells the ImageSource that the Image no longer cares about decoded frame
+ // data -- at all (if |destroyAll| is true), or before frame
+ // |clearBeforeFrame| (if |destroyAll| is false). The ImageSource should
+ // delete cached decoded data for these frames where possible to keep memory
+ // usage low. When |destroyAll| is true, the ImageSource should also reset
+ // any local state so that decoding can begin again.
+ //
+ // Implementations that delete less than what's specified above waste
+ // memory. Implementations that delete more may burn CPU re-decoding frames
+ // that could otherwise have been cached, or encounter errors if they're
+ // asked to decode frames they can't decode due to the loss of previous
+ // decoded frames.
+ //
+ // Callers should not call clear(false, n) and subsequently call
+ // createFrameAtIndex(m) with m < n, unless they first call clear(true).
+ // This ensures that stateful ImageSources/decoders will work properly.
+ //
+ // The |data| and |allDataReceived| parameters should be supplied by callers
+ // who set |destroyAll| to true if they wish to be able to continue using
+ // the ImageSource. This way implementations which choose to destroy their
+ // decoders in some cases can reconstruct them correctly.
+ void clear(bool destroyAll,
+ size_t clearBeforeFrame = 0,
+ SharedBuffer* data = NULL,
+ bool allDataReceived = false);
bool initialized() const;
-
+
void setData(SharedBuffer* data, bool allDataReceived);
+ String filenameExtension() const;
bool isSizeAvailable();
IntSize size() const;
IntSize frameSizeAtIndex(size_t) const;
int repetitionCount();
-
+
size_t frameCount() const;
-
+
+ // Callers should not call this after calling clear() with a higher index;
+ // see comments on clear() above.
NativeImagePtr createFrameAtIndex(size_t);
-
+
float frameDurationAtIndex(size_t);
bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha.
bool frameIsCompleteAtIndex(size_t); // Whether or not the frame is completely decoded.
@@ -119,6 +147,9 @@ public:
void setURL(const String& url);
#endif
private:
+ // FIXME: This is protected only to allow ImageSourceSkia to set ICO decoder
+ // with a preferred size. See ImageSourceSkia.h for discussion.
+protected:
NativeImageSourcePtr m_decoder;
};
diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h
index 7245408..4d36545 100644
--- a/WebCore/platform/graphics/IntSize.h
+++ b/WebCore/platform/graphics/IntSize.h
@@ -67,6 +67,12 @@ public:
bool isEmpty() const { return m_width <= 0 || m_height <= 0; }
+ void expand(int width, int height)
+ {
+ m_width += width;
+ m_height += height;
+ }
+
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.h b/WebCore/platform/graphics/MediaPlayer.h
index 1beab95..203f299 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -67,6 +67,9 @@ public:
void setFrameView(FrameView* frameView) { m_frameView = frameView; }
bool inMediaDocument();
+ // FIXME: it would be better to just have a getter and setter for size.
+ // This is currently an absolute rect, which is not appropriate for
+ // content with transforms
IntRect rect() const { return m_rect; }
void setRect(const IntRect& r);
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
index 06e6ee4..2b0a7d1 100644
--- a/WebCore/platform/graphics/Path.h
+++ b/WebCore/platform/graphics/Path.h
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
- * 2006 Rob Buis <buis@kde.org>
+ * Copyright (C) 2003, 2006, 2009 Apple Inc. All rights reserved.
+ * 2006 Rob Buis <buis@kde.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,6 +27,8 @@
#ifndef Path_h
#define Path_h
+#include <algorithm>
+
#if PLATFORM(CG)
typedef struct CGPath PlatformPath;
#elif PLATFORM(QT)
@@ -55,11 +57,13 @@ typedef void PlatformPath;
namespace WebCore {
- class AffineTransform;
class FloatPoint;
- class FloatSize;
class FloatRect;
+ class FloatSize;
+ class GraphicsContext;
class String;
+ class StrokeStyleApplier;
+ class TransformationMatrix;
enum WindRule {
RULE_NONZERO = 0,
@@ -79,7 +83,7 @@ namespace WebCore {
FloatPoint* points;
};
- typedef void (*PathApplierFunction) (void* info, const PathElement*);
+ typedef void (*PathApplierFunction)(void* info, const PathElement*);
class Path {
public:
@@ -89,8 +93,12 @@ namespace WebCore {
Path(const Path&);
Path& operator=(const Path&);
+ void swap(Path& other) { std::swap(m_path, other.m_path); }
+
bool contains(const FloatPoint&, WindRule rule = RULE_NONZERO) const;
+ bool strokeContains(StrokeStyleApplier*, const FloatPoint&) const;
FloatRect boundingRect() const;
+ FloatRect strokeBoundingRect(StrokeStyleApplier* = 0);
float length();
FloatPoint pointAtLength(float length, bool& ok);
@@ -124,7 +132,7 @@ namespace WebCore {
static Path createLine(const FloatPoint&, const FloatPoint&);
void apply(void* info, PathApplierFunction) const;
- void transform(const AffineTransform&);
+ void transform(const TransformationMatrix&);
private:
PlatformPath* m_path;
diff --git a/WebCore/platform/graphics/Pattern.h b/WebCore/platform/graphics/Pattern.h
index 985c7c0..716a645 100644
--- a/WebCore/platform/graphics/Pattern.h
+++ b/WebCore/platform/graphics/Pattern.h
@@ -54,7 +54,7 @@ typedef wxBrush* PlatformPatternPtr;
#endif
namespace WebCore {
- class AffineTransform;
+ class TransformationMatrix;
class Image;
class Pattern : public RefCounted<Pattern> {
@@ -67,7 +67,7 @@ namespace WebCore {
Image* tileImage() const { return m_tileImage.get(); }
- PlatformPatternPtr createPlatformPattern(const AffineTransform& patternTransform) const;
+ PlatformPatternPtr createPlatformPattern(const TransformationMatrix& patternTransform) const;
private:
Pattern(Image*, bool repeatX, bool repeatY);
diff --git a/WebCore/platform/graphics/SegmentedFontData.cpp b/WebCore/platform/graphics/SegmentedFontData.cpp
index ceefe4f..1731d16 100644
--- a/WebCore/platform/graphics/SegmentedFontData.cpp
+++ b/WebCore/platform/graphics/SegmentedFontData.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
@@ -45,16 +45,27 @@ const SimpleFontData* SegmentedFontData::fontDataForCharacter(UChar32 c) const
return m_ranges[0].fontData();
}
-bool SegmentedFontData::containsCharacters(const UChar* characters, int length) const
+bool SegmentedFontData::containsCharacter(UChar32 c) const
{
Vector<FontDataRange>::const_iterator end = m_ranges.end();
for (Vector<FontDataRange>::const_iterator it = m_ranges.begin(); it != end; ++it) {
- if (it->from() <= characters[0] && it->to() >= characters[0])
+ if (c >= it->from() && c <= it->to())
return true;
}
return false;
}
+bool SegmentedFontData::containsCharacters(const UChar* characters, int length) const
+{
+ UChar32 c;
+ for (int i = 0; i < length; ) {
+ U16_NEXT(characters, i, length, c)
+ if (!containsCharacter(c))
+ return false;
+ }
+ return true;
+}
+
bool SegmentedFontData::isCustomFont() const
{
// All segmented fonts are custom fonts.
diff --git a/WebCore/platform/graphics/SegmentedFontData.h b/WebCore/platform/graphics/SegmentedFontData.h
index 1adec15..0a78321 100644
--- a/WebCore/platform/graphics/SegmentedFontData.h
+++ b/WebCore/platform/graphics/SegmentedFontData.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
@@ -55,6 +55,11 @@ class SegmentedFontData : public FontData {
public:
virtual ~SegmentedFontData();
+ void appendRange(const FontDataRange& range) { m_ranges.append(range); }
+ unsigned numRanges() const { return m_ranges.size(); }
+ const FontDataRange& rangeAt(unsigned i) const { return m_ranges[i]; }
+
+private:
virtual const SimpleFontData* fontDataForCharacter(UChar32) const;
virtual bool containsCharacters(const UChar*, int length) const;
@@ -62,11 +67,8 @@ public:
virtual bool isLoading() const;
virtual bool isSegmented() const;
- void appendRange(const FontDataRange& range) { m_ranges.append(range); }
- unsigned numRanges() const { return m_ranges.size(); }
- const FontDataRange& rangeAt(unsigned i) const { return m_ranges[i]; }
+ bool containsCharacter(UChar32) const;
-private:
Vector<FontDataRange, 1> m_ranges;
};
diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp
index 372fcc8..9670b55 100644
--- a/WebCore/platform/graphics/SimpleFontData.cpp
+++ b/WebCore/platform/graphics/SimpleFontData.cpp
@@ -30,6 +30,7 @@
#include "config.h"
#include "SimpleFontData.h"
+#include "Font.h"
#include "FontCache.h"
#if ENABLE(SVG_FONTS)
#include "SVGFontData.h"
@@ -41,7 +42,8 @@
namespace WebCore {
SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool loading, SVGFontData* svgFontData)
- : m_font(f)
+ : m_unitsPerEm(defaultUnitsPerEm)
+ , m_font(f)
, m_treatAsFixedPitch(false)
#if ENABLE(SVG_FONTS)
, m_svgFontData(svgFontData)
@@ -50,7 +52,7 @@ SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool
, m_isLoading(loading)
, m_smallCapsFontData(0)
{
-#if ENABLE(SVG_FONTS) && !PLATFORM(QT)
+#if ENABLE(SVG_FONTS)
if (SVGFontFaceElement* svgFontFaceElement = svgFontData ? svgFontData->svgFontFaceElement() : 0) {
m_unitsPerEm = svgFontFaceElement->unitsPerEm();
@@ -75,7 +77,12 @@ SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool
#endif
platformInit();
+ platformGlyphInit();
+}
+#if !PLATFORM(QT)
+void SimpleFontData::platformGlyphInit()
+{
GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
if (!glyphPageZero) {
LOG_ERROR("Failed to get glyph page zero.");
@@ -113,21 +120,23 @@ SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool
m_missingGlyphData.fontData = this;
m_missingGlyphData.glyph = 0;
}
+#endif
SimpleFontData::~SimpleFontData()
{
+#if ENABLE(SVG_FONTS)
+ if (!m_svgFontData || !m_svgFontData->svgFontFaceElement())
+#endif
+ platformDestroy();
+
if (!isCustomFont()) {
if (m_smallCapsFontData)
- FontCache::releaseFontData(m_smallCapsFontData);
+ fontCache()->releaseFontData(m_smallCapsFontData);
GlyphPageTreeNode::pruneTreeFontData(this);
}
-
-#if ENABLE(SVG_FONTS) && !PLATFORM(QT)
- if (!m_svgFontData || !m_svgFontData->svgFontFaceElement())
-#endif
- platformDestroy();
}
+#if !PLATFORM(QT)
float SimpleFontData::widthForGlyph(Glyph glyph) const
{
float width = m_glyphToWidthMap.widthForGlyph(glyph);
@@ -139,6 +148,7 @@ float SimpleFontData::widthForGlyph(Glyph glyph) const
return width;
}
+#endif
const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
{
diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h
index 5f26cbf..e572e30 100644
--- a/WebCore/platform/graphics/SimpleFontData.h
+++ b/WebCore/platform/graphics/SimpleFontData.h
@@ -41,6 +41,10 @@ typedef struct OpaqueATSUStyle* ATSUStyle;
#include <cairo.h>
#endif
+#if PLATFORM(QT)
+#include <QFont>
+#endif
+
namespace WebCore {
class FontDescription;
@@ -109,6 +113,10 @@ public:
}
#endif
+#if PLATFORM(QT)
+ QFont getQtFont() const { return m_font.font(); }
+#endif
+
#if PLATFORM(WIN)
bool isSystemFont() const { return m_isSystemFont; }
SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
@@ -128,6 +136,7 @@ public:
private:
void platformInit();
+ void platformGlyphInit();
void platformDestroy();
void commonInit();
diff --git a/WebCore/platform/graphics/StrokeStyleApplier.h b/WebCore/platform/graphics/StrokeStyleApplier.h
new file mode 100644
index 0000000..e40d3d1
--- /dev/null
+++ b/WebCore/platform/graphics/StrokeStyleApplier.h
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef StrokeStyleApplier_h
+#define StrokeStyleApplier_h
+
+namespace WebCore {
+
+ class GraphicsContext;
+
+ class StrokeStyleApplier {
+ public:
+ virtual void strokeStyle(GraphicsContext*) = 0;
+
+ protected:
+ StrokeStyleApplier() {}
+ virtual ~StrokeStyleApplier() {}
+ };
+}
+
+#endif
+
diff --git a/WebCore/platform/graphics/android/FontCacheAndroid.cpp b/WebCore/platform/graphics/android/FontCacheAndroid.cpp
index c257348..0b3655f 100644
--- a/WebCore/platform/graphics/android/FontCacheAndroid.cpp
+++ b/WebCore/platform/graphics/android/FontCacheAndroid.cpp
@@ -113,7 +113,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
if (fontDescription.italic())
style |= SkTypeface::kItalic;
- SkTypeface* tf = SkTypeface::Create(name, (SkTypeface::Style)style);
+ SkTypeface* tf = SkTypeface::CreateFromName(name, (SkTypeface::Style)style);
FontPlatformData* result = new FontPlatformData(tf,
fontDescription.computedSize(),
diff --git a/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
index c2e0f02..40d98ec 100644
--- a/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
+++ b/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
@@ -40,7 +40,7 @@
#include "SkPaint.h"
#include "SkPorterDuff.h"
#include "PlatformGraphicsContext.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "android_graphics.h"
#include "SkGradientShader.h"
@@ -320,7 +320,7 @@ static void extactShader(SkPaint* paint, ColorSpace cs, Pattern* pat,
case PatternColorSpace:
// createPlatformPattern() returns a new inst
paint->setShader(pat->createPlatformPattern(
- AffineTransform()))->safeUnref();
+ TransformationMatrix()))->safeUnref();
break;
case GradientColorSpace: {
// grad->getShader() returns a cached obj
@@ -389,6 +389,10 @@ bool GraphicsContext::willStroke() const {
return m_data->mState->mStrokeColor != 0;
}
+const SkPath* GraphicsContext::getCurrPath() const {
+ return m_data->mState->mPath;
+}
+
// Draws a filled rectangle with a stroked border.
void GraphicsContext::drawRect(const IntRect& rect)
{
@@ -771,19 +775,21 @@ KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext()
}
#endif
+/* These are the flags we need when we call saveLayer for transparency.
+ Since it does not appear that webkit intends this to also save/restore
+ the matrix or clip, I do not give those flags (for performance)
+ */
+#define TRANSPARENCY_SAVEFLAGS \
+ (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | \
+ SkCanvas::kFullColorLayer_SaveFlag)
+
void GraphicsContext::beginTransparencyLayer(float opacity)
{
if (paintingDisabled())
return;
SkCanvas* canvas = GC2Canvas(this);
-
- if (opacity < 1)
- {
- canvas->saveLayerAlpha(NULL, (int)(opacity * 255), SkCanvas::kHasAlphaLayer_SaveFlag);
- }
- else
- canvas->save();
+ canvas->saveLayerAlpha(NULL, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS);
}
void GraphicsContext::endTransparencyLayer()
@@ -976,7 +982,7 @@ void GraphicsContext::translate(float x, float y)
GC2Canvas(this)->translate(SkFloatToScalar(x), SkFloatToScalar(y));
}
-void GraphicsContext::concatCTM(const AffineTransform& xform)
+void GraphicsContext::concatCTM(const TransformationMatrix& xform)
{
if (paintingDisabled())
return;
@@ -1026,32 +1032,38 @@ if (urlRef) {
#endif
}
-void GraphicsContext::setUseAntialiasing(bool useAA) {
+void GraphicsContext::setPlatformShouldAntialias(bool useAA)
+{
if (paintingDisabled())
return;
m_data->mState->mUseAA = useAA;
}
-AffineTransform GraphicsContext::getCTM() const {
- return AffineTransform(GC2Canvas(this)->getTotalMatrix());
+TransformationMatrix GraphicsContext::getCTM() const
+{
+ return TransformationMatrix(GC2Canvas(this)->getTotalMatrix());
}
///////////////////////////////////////////////////////////////////////////////
-void GraphicsContext::beginPath() {
+void GraphicsContext::beginPath()
+{
m_data->beginPath();
}
-void GraphicsContext::addPath(const Path& p) {
+void GraphicsContext::addPath(const Path& p)
+{
m_data->addPath(*p.platformPath());
}
-void GraphicsContext::drawPath() {
+void GraphicsContext::drawPath()
+{
this->fillPath();
this->strokePath();
}
-void GraphicsContext::fillPath() {
+void GraphicsContext::fillPath()
+{
SkPath* path = m_data->getPath();
if (paintingDisabled() || !path)
return;
@@ -1075,7 +1087,8 @@ void GraphicsContext::fillPath() {
GC2Canvas(this)->drawPath(*path, paint);
}
-void GraphicsContext::strokePath() {
+void GraphicsContext::strokePath()
+{
const SkPath* path = m_data->getPath();
if (paintingDisabled() || !path || strokeStyle() == NoStroke)
return;
@@ -1112,7 +1125,8 @@ void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode)
///////////////////////////////////////////////////////////////////////////////
-SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc) {
+SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc)
+{
return gc->platformContext()->mCanvas;
}
diff --git a/WebCore/platform/graphics/android/ImageAndroid.cpp b/WebCore/platform/graphics/android/ImageAndroid.cpp
index 04235d5..da52d67 100644
--- a/WebCore/platform/graphics/android/ImageAndroid.cpp
+++ b/WebCore/platform/graphics/android/ImageAndroid.cpp
@@ -25,7 +25,7 @@
*/
#include "config.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "BitmapImage.h"
#include "Image.h"
#include "FloatRect.h"
@@ -59,14 +59,19 @@ android::AssetManager* globalAssetManager() {
namespace WebCore {
-void FrameData::clear()
+bool FrameData::clear(bool clearMetadata)
{
+ if (clearMetadata)
+ m_haveMetadata = false;
+
if (m_frame) {
m_frame->unref();
m_frame = 0;
m_duration = 0.;
m_hasAlpha = true;
+ return true;
}
+ return false;
}
BitmapImage::BitmapImage(SkBitmapRef* ref, ImageObserver* observer)
@@ -211,7 +216,7 @@ void BitmapImage::setURL(const String& str)
///////////////////////////////////////////////////////////////////////////////
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect,
- const AffineTransform& patternTransform,
+ const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator compositeOp,
const FloatRect& destRect)
{
diff --git a/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
index de88b33..7b3e8e8 100644
--- a/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
+++ b/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
@@ -99,8 +99,9 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return 0;
}
- PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
- unsigned char* data = result->data()->data().data();
+ // ! Can't use PassRefPtr<>, otherwise the second access will cause crash.
+ RefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
+ unsigned char* data = result->data()->data()->data();
if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height())
memset(data, 0, result->data()->length());
@@ -190,7 +191,7 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
unsigned srcBytesPerRow = 4 * source->width();
unsigned dstPixelsPerRow = dst.rowBytesAsPixels();
- unsigned char* srcRows = source->data()->data().data() + originy * srcBytesPerRow + originx * 4;
+ unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
SkPMColor* dstRows = dst.getAddr32(destx, desty);
for (int y = 0; y < numRows; ++y) {
for (int x = 0; x < numColumns; x++) {
diff --git a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
index a6bf6c6..c8fe8dd 100644
--- a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
+++ b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
@@ -347,7 +347,7 @@ bool ImageSource::frameIsCompleteAtIndex(size_t index)
return m_decoder.m_image && m_decoder.m_image->fAllDataReceived;
}
-void ImageSource::clear()
+void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
{
// do nothing, since the cache is managed elsewhere
}
@@ -358,4 +358,10 @@ IntSize ImageSource::frameSizeAtIndex(size_t index) const
return this->size();
}
+String ImageSource::filenameExtension() const
+{
+ // FIXME: need to add virtual to our decoders to return "jpg/png/gif/..."
+ return String();
+}
+
}
diff --git a/WebCore/platform/graphics/android/PathAndroid.cpp b/WebCore/platform/graphics/android/PathAndroid.cpp
index 819173b..cfcd2bc 100644
--- a/WebCore/platform/graphics/android/PathAndroid.cpp
+++ b/WebCore/platform/graphics/android/PathAndroid.cpp
@@ -26,7 +26,10 @@
#include "config.h"
#include "Path.h"
#include "FloatRect.h"
-#include "AffineTransform.h"
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
+#include "StrokeStyleApplier.h"
+#include "TransformationMatrix.h"
#include "SkPath.h"
#include "SkRegion.h"
@@ -260,9 +263,54 @@ void Path::apply(void* info, PathApplierFunction function) const
}
}
-void Path::transform(const AffineTransform& xform)
+void Path::transform(const TransformationMatrix& xform)
{
m_path->transform(xform);
}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Computes the bounding box for the stroke and style currently selected into
+// the given bounding box. This also takes into account the stroke width.
+static FloatRect boundingBoxForCurrentStroke(GraphicsContext* context)
+{
+ const SkPath* path = context->getCurrPath();
+ if (NULL == path) {
+ return FloatRect();
+ }
+
+ SkPaint paint;
+ context->setupStrokePaint(&paint);
+ SkPath fillPath;
+ paint.getFillPath(*path, &fillPath);
+ SkRect r;
+ fillPath.computeBounds(&r, SkPath::kExact_BoundsType);
+ return FloatRect(r.fLeft, r.fTop, r.width(), r.height());
+}
+
+static GraphicsContext* scratchContext()
+{
+ static ImageBuffer* scratch = 0;
+ if (!scratch)
+ scratch = ImageBuffer::create(IntSize(1, 1), false).release();
+ // We don't bother checking for failure creating the ImageBuffer, since our
+ // ImageBuffer initializer won't fail.
+ return scratch->context();
+}
+
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+{
+ GraphicsContext* scratch = scratchContext();
+ scratch->save();
+ scratch->beginPath();
+ scratch->addPath(*this);
+
+ if (applier)
+ applier->strokeStyle(scratch);
+
+ FloatRect r = boundingBoxForCurrentStroke(scratch);
+ scratch->restore();
+ return r;
+}
}
diff --git a/WebCore/platform/graphics/android/PatternAndroid.cpp b/WebCore/platform/graphics/android/PatternAndroid.cpp
index 2840faa..ffdbbb1 100644
--- a/WebCore/platform/graphics/android/PatternAndroid.cpp
+++ b/WebCore/platform/graphics/android/PatternAndroid.cpp
@@ -40,7 +40,7 @@ static SkShader::TileMode toTileMode(bool doRepeat) {
return doRepeat ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
}
-SkShader* Pattern::createPlatformPattern(const AffineTransform& transform) const
+SkShader* Pattern::createPlatformPattern(const TransformationMatrix& transform) const
{
SkBitmapRef* ref = tileImage()->nativeImageForCurrentFrame();
SkShader* s = SkShader::CreateBitmapShader(ref->bitmap(),
diff --git a/WebCore/platform/graphics/android/AffineTransformAndroid.cpp b/WebCore/platform/graphics/android/TransformationMatrixAndroid.cpp
index c01d078..154d4f3 100644
--- a/WebCore/platform/graphics/android/AffineTransformAndroid.cpp
+++ b/WebCore/platform/graphics/android/TransformationMatrixAndroid.cpp
@@ -24,7 +24,7 @@
*/
#include "config.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatRect.h"
#include "IntRect.h"
@@ -35,14 +35,14 @@ namespace WebCore {
static const double deg2rad = 0.017453292519943295769; // pi/180
-AffineTransform::AffineTransform()
+TransformationMatrix::TransformationMatrix()
{
m_transform.reset();
}
-AffineTransform::AffineTransform(const SkMatrix& mat) : m_transform(mat) {}
+TransformationMatrix::TransformationMatrix(const SkMatrix& mat) : m_transform(mat) {}
-AffineTransform::AffineTransform(double a, double b, double c, double d, double tx, double ty)
+TransformationMatrix::TransformationMatrix(double a, double b, double c, double d, double tx, double ty)
{
m_transform.reset();
@@ -55,7 +55,7 @@ AffineTransform::AffineTransform(double a, double b, double c, double d, double
m_transform.set(SkMatrix::kMTransX, SkDoubleToScalar(ty));
}
-void AffineTransform::setMatrix(double a, double b, double c, double d, double tx, double ty)
+void TransformationMatrix::setMatrix(double a, double b, double c, double d, double tx, double ty)
{
m_transform.set(SkMatrix::kMScaleX, SkDoubleToScalar(a));
m_transform.set(SkMatrix::kMSkewX, SkDoubleToScalar(b));
@@ -66,150 +66,164 @@ void AffineTransform::setMatrix(double a, double b, double c, double d, double t
m_transform.set(SkMatrix::kMTransX, SkDoubleToScalar(ty));
}
-void AffineTransform::map(double x, double y, double *x2, double *y2) const
+void TransformationMatrix::map(double x, double y, double *x2, double *y2) const
{
- SkPoint src, dst;
- src.set(SkDoubleToScalar(x), SkDoubleToScalar(y));
- m_transform.mapPoints(&dst, &src, 1);
+ SkPoint pt;
- *x2 = SkScalarToDouble(dst.fX);
- *y2 = SkScalarToDouble(dst.fY);
+ m_transform.mapXY(SkDoubleToScalar(x), SkDoubleToScalar(y), &pt);
+ *x2 = SkScalarToDouble(pt.fX);
+ *y2 = SkScalarToDouble(pt.fY);
}
-IntRect AffineTransform::mapRect(const IntRect &rect) const
+IntRect TransformationMatrix::mapRect(const IntRect &rect) const
{
SkRect src, dst;
SkIRect ir;
android_setrect(&src, rect);
m_transform.mapRect(&dst, src);
- dst.round(&ir);
+ // we round out to mimic enclosingIntRect()
+ dst.roundOut(&ir);
return IntRect(ir.fLeft, ir.fTop, ir.width(), ir.height());
}
-FloatRect AffineTransform::mapRect(const FloatRect &rect) const
+FloatRect TransformationMatrix::mapRect(const FloatRect &rect) const
{
- SkRect src, dst;
- SkIRect ir;
+ SkRect r;
- android_setrect(&src, rect);
- m_transform.mapRect(&dst, src);
- dst.round(&ir);
+ android_setrect(&r, rect);
+ m_transform.mapRect(&r);
- return IntRect(ir.fLeft, ir.fTop, ir.width(), ir.height());
+ return FloatRect(r.fLeft, r.fTop, r.width(), r.height());
}
-bool AffineTransform::isIdentity() const
+bool TransformationMatrix::isIdentity() const
{
return m_transform.isIdentity();
}
-void AffineTransform::reset()
+void TransformationMatrix::reset()
{
m_transform.reset();
}
- double AffineTransform::a() const {
- return SkScalarToDouble(m_transform[0]);
- }
- void AffineTransform::setA(double a) {
- m_transform.set(0, SkDoubleToScalar(a));
- }
+double TransformationMatrix::a() const
+{
+ return SkScalarToDouble(m_transform[0]);
+}
- double AffineTransform::b() const {
- return SkScalarToDouble(m_transform[1]);
- }
- void AffineTransform::setB(double b) {
- m_transform.set(1, SkDoubleToScalar(b));
- }
-
- double AffineTransform::c() const {
- return SkScalarToDouble(m_transform[3]);
- }
- void AffineTransform::setC(double c) {
- m_transform.set(3, SkDoubleToScalar(c));
- }
-
- double AffineTransform::d() const {
- return SkScalarToDouble(m_transform[4]);
- }
- void AffineTransform::setD(double d) {
- m_transform.set(4, SkDoubleToScalar(d));
- }
-
- double AffineTransform::e() const {
- return SkScalarToDouble(m_transform[2]);
- }
- void AffineTransform::setE(double e) {
- m_transform.set(2, SkDoubleToScalar(e));
- }
-
- double AffineTransform::f() const {
- return SkScalarToDouble(m_transform[5]);
- }
- void AffineTransform::setF(double f) {
- m_transform.set(5, SkDoubleToScalar(f));
- }
+void TransformationMatrix::setA(double a)
+{
+ m_transform.set(0, SkDoubleToScalar(a));
+}
+
+double TransformationMatrix::b() const
+{
+ return SkScalarToDouble(m_transform[1]);
+}
+
+void TransformationMatrix::setB(double b)
+{
+ m_transform.set(1, SkDoubleToScalar(b));
+}
+
+double TransformationMatrix::c() const
+{
+ return SkScalarToDouble(m_transform[3]);
+}
+
+void TransformationMatrix::setC(double c)
+{
+ m_transform.set(3, SkDoubleToScalar(c));
+}
+
+double TransformationMatrix::d() const {
+ return SkScalarToDouble(m_transform[4]);
+}
+
+void TransformationMatrix::setD(double d)
+{
+ m_transform.set(4, SkDoubleToScalar(d));
+}
+
+double TransformationMatrix::e() const
+{
+ return SkScalarToDouble(m_transform[2]);
+}
+
+void TransformationMatrix::setE(double e)
+{
+ m_transform.set(2, SkDoubleToScalar(e));
+}
+
+double TransformationMatrix::f() const {
+ return SkScalarToDouble(m_transform[5]);
+}
+void TransformationMatrix::setF(double f) {
+ m_transform.set(5, SkDoubleToScalar(f));
+}
-AffineTransform &AffineTransform::scale(double sx, double sy)
+TransformationMatrix &TransformationMatrix::scale(double sx, double sy)
{
m_transform.preScale(SkDoubleToScalar(sx), SkDoubleToScalar(sy));
return *this;
}
-AffineTransform &AffineTransform::rotate(double d)
+TransformationMatrix &TransformationMatrix::rotate(double d)
{
m_transform.preRotate(SkDoubleToScalar(d));
return *this;
}
-AffineTransform &AffineTransform::translate(double tx, double ty)
+TransformationMatrix &TransformationMatrix::translate(double tx, double ty)
{
m_transform.preTranslate(SkDoubleToScalar(tx), SkDoubleToScalar(ty));
return *this;
}
-AffineTransform &AffineTransform::shear(double sx, double sy)
+TransformationMatrix &TransformationMatrix::shear(double sx, double sy)
{
m_transform.preSkew(SkDoubleToScalar(sx), SkDoubleToScalar(sy));
return *this;
}
-double AffineTransform::det() const
+double TransformationMatrix::det() const
{
return SkScalarToDouble(m_transform[SkMatrix::kMScaleX]) * SkScalarToDouble(m_transform[SkMatrix::kMScaleY]) -
SkScalarToDouble(m_transform[SkMatrix::kMSkewX]) * SkScalarToDouble(m_transform[SkMatrix::kMSkewY]);
}
-AffineTransform AffineTransform::inverse() const
+TransformationMatrix TransformationMatrix::inverse() const
{
- AffineTransform inverse;
+ // the constructor initializes inverse to the identity
+ TransformationMatrix inverse;
+ // if we are not invertible, inverse will stay identity
m_transform.invert(&inverse.m_transform);
return inverse;
}
-AffineTransform::operator SkMatrix() const
+TransformationMatrix::operator SkMatrix() const
{
return m_transform;
}
-bool AffineTransform::operator==(const AffineTransform &m2) const
+bool TransformationMatrix::operator==(const TransformationMatrix &m2) const
{
return m_transform == m2.m_transform;
}
-AffineTransform &AffineTransform::operator*= (const AffineTransform &m2)
+TransformationMatrix &TransformationMatrix::operator*= (const TransformationMatrix &m2)
{
m_transform.setConcat(m2.m_transform, m_transform);
return *this;
}
-AffineTransform AffineTransform::operator* (const AffineTransform &m2)
+TransformationMatrix TransformationMatrix::operator* (const TransformationMatrix &m2)
{
- AffineTransform cat;
+ TransformationMatrix cat;
cat.m_transform.setConcat(m2.m_transform, m_transform);
return cat;
diff --git a/WebCore/platform/graphics/android/android_graphics.cpp b/WebCore/platform/graphics/android/android_graphics.cpp
index 2bc0c8f..1decfd8 100644
--- a/WebCore/platform/graphics/android/android_graphics.cpp
+++ b/WebCore/platform/graphics/android/android_graphics.cpp
@@ -98,7 +98,7 @@ static const struct CompositOpToPorterDuffMode {
uint8_t mPorterDuffMode;
} gMapCompositOpsToPorterDuffModes[] = {
{ WebCore::CompositeClear, SkPorterDuff::kClear_Mode },
- { WebCore::CompositeCopy, SkPorterDuff::kSrcOver_Mode }, // TODO
+ { WebCore::CompositeCopy, SkPorterDuff::kSrc_Mode },
{ WebCore::CompositeSourceOver, SkPorterDuff::kSrcOver_Mode },
{ WebCore::CompositeSourceIn, SkPorterDuff::kSrcIn_Mode },
{ WebCore::CompositeSourceOut, SkPorterDuff::kSrcOut_Mode },
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index c403f44..ef748cf 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -31,7 +31,7 @@
#if PLATFORM(CAIRO)
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "CairoPath.h"
#include "FloatRect.h"
#include "Font.h"
@@ -62,6 +62,15 @@
namespace WebCore {
+static const unsigned aquaFocusRingColor = 0xFF7DADD9;
+
+Color focusRingColor()
+{
+ static Color focusRingColor = aquaFocusRingColor;
+
+ return focusRingColor;
+}
+
static inline void setColor(cairo_t* cr, const Color& col)
{
float red, green, blue, alpha;
@@ -90,9 +99,6 @@ static inline cairo_pattern_t* applySpreadMethod(cairo_pattern_t* pattern, Gradi
case SpreadMethodRepeat:
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
break;
- default:
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE);
- break;
}
return pattern;
}
@@ -111,7 +117,7 @@ GraphicsContext::~GraphicsContext()
delete m_data;
}
-AffineTransform GraphicsContext::getCTM() const
+TransformationMatrix GraphicsContext::getCTM() const
{
cairo_t* cr = platformContext();
cairo_matrix_t m;
@@ -444,19 +450,19 @@ void GraphicsContext::fillPath()
cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
switch (m_common->state.fillColorSpace) {
case SolidColorSpace:
- if (fillColor().alpha()) {
- setColor(cr, fillColor());
- cairo_clip(cr);
- cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
- }
+ setColor(cr, fillColor());
+ cairo_clip(cr);
+ cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
break;
- case PatternColorSpace:
- cairo_set_source(cr, m_common->state.fillPattern.get()->createPlatformPattern(getCTM()));
+ case PatternColorSpace: {
+ TransformationMatrix affine;
+ cairo_set_source(cr, m_common->state.fillPattern->createPlatformPattern(affine));
cairo_clip(cr);
cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
break;
+ }
case GradientColorSpace:
- cairo_pattern_t* pattern = m_common->state.fillGradient.get()->platformGradient();
+ cairo_pattern_t* pattern = m_common->state.fillGradient->platformGradient();
pattern = applySpreadMethod(pattern, spreadMethod());
cairo_set_source(cr, pattern);
cairo_clip(cr);
@@ -475,18 +481,16 @@ void GraphicsContext::strokePath()
cairo_save(cr);
switch (m_common->state.strokeColorSpace) {
case SolidColorSpace:
- if (strokeColor().alpha()) {
- setColor(cr, strokeColor());
- if (m_common->state.globalAlpha < 1.0f) {
- cairo_push_group(cr);
- cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
- cairo_pop_group_to_source(cr);
- }
- cairo_stroke(cr);
- }
+ float red, green, blue, alpha;
+ strokeColor().getRGBA(red, green, blue, alpha);
+ if (m_common->state.globalAlpha < 1.0f)
+ alpha *= m_common->state.globalAlpha;
+ cairo_set_source_rgba(cr, red, green, blue, alpha);
+ cairo_stroke(cr);
break;
- case PatternColorSpace:
- cairo_set_source(cr, m_common->state.strokePattern.get()->createPlatformPattern(getCTM()));
+ case PatternColorSpace: {
+ TransformationMatrix affine;
+ cairo_set_source(cr, m_common->state.strokePattern->createPlatformPattern(affine));
if (m_common->state.globalAlpha < 1.0f) {
cairo_push_group(cr);
cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
@@ -494,8 +498,9 @@ void GraphicsContext::strokePath()
}
cairo_stroke(cr);
break;
+ }
case GradientColorSpace:
- cairo_pattern_t* pattern = m_common->state.strokeGradient.get()->platformGradient();
+ cairo_pattern_t* pattern = m_common->state.strokeGradient->platformGradient();
pattern = applySpreadMethod(pattern, spreadMethod());
cairo_set_source(cr, pattern);
if (m_common->state.globalAlpha < 1.0f) {
@@ -548,6 +553,16 @@ void GraphicsContext::clip(const FloatRect& rect)
m_data->clip(rect);
}
+void GraphicsContext::clipPath(WindRule clipRule)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_set_fill_rule(cr, clipRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
+ cairo_clip(cr);
+}
+
void GraphicsContext::drawFocusRing(const Color& color)
{
if (paintingDisabled())
@@ -729,7 +744,7 @@ void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
notImplemented();
}
-void GraphicsContext::concatCTM(const AffineTransform& transform)
+void GraphicsContext::concatCTM(const TransformationMatrix& transform)
{
if (paintingDisabled())
return;
@@ -1079,7 +1094,7 @@ GdkDrawable* GraphicsContext::gdkDrawable() const
}
#endif
-void GraphicsContext::setUseAntialiasing(bool enable)
+void GraphicsContext::setPlatformShouldAntialias(bool enable)
{
if (paintingDisabled())
return;
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
index 9a14555..535f70d 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
+++ b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
@@ -69,7 +69,7 @@ public:
void scale(const FloatSize&);
void rotate(float);
void translate(float, float);
- void concatCTM(const AffineTransform&);
+ void concatCTM(const TransformationMatrix&);
void beginTransparencyLayer() { m_transparencyCount++; }
void endTransparencyLayer() { m_transparencyCount--; }
#else
@@ -81,7 +81,7 @@ public:
void scale(const FloatSize&) {}
void rotate(float) {}
void translate(float, float) {}
- void concatCTM(const AffineTransform&) {}
+ void concatCTM(const TransformationMatrix&) {}
void beginTransparencyLayer() {}
void endTransparencyLayer() {}
#endif
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 5f65ed2..3e06669 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -94,7 +94,7 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
unsigned char* dataSrc = cairo_image_surface_get_data(m_data.m_surface);
- unsigned char* dataDst = result->data()->data().data();
+ unsigned char* dataDst = result->data()->data()->data();
if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height())
memset(dataSrc, 0, result->data()->length());
@@ -179,7 +179,7 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
unsigned srcBytesPerRow = 4 * source->width();
int stride = cairo_image_surface_get_stride(m_data.m_surface);
- unsigned char* srcRows = source->data()->data().data() + originy * srcBytesPerRow + originx * 4;
+ unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
for (int y = 0; y < numRows; ++y) {
unsigned char *row = dataDst + stride * (y + desty);
for (int x = 0; x < numColumns; x++) {
diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp
index 0a35cf2..2850488 100644
--- a/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -29,7 +29,7 @@
#if PLATFORM(CAIRO)
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "ImageObserver.h"
@@ -38,15 +38,17 @@
namespace WebCore {
-void FrameData::clear()
+bool FrameData::clear(bool clearMetadata)
{
+ if (clearMetadata)
+ m_haveMetadata = false;
+
if (m_frame) {
cairo_surface_destroy(m_frame);
m_frame = 0;
- // NOTE: We purposefully don't reset metadata here, so that even if we
- // throw away previously-decoded data, animation loops can still access
- // properties like frame durations without re-decoding.
+ return true;
}
+ return false;
}
BitmapImage::BitmapImage(cairo_surface_t* surface, ImageObserver* observer)
@@ -139,7 +141,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
imageObserver()->didDraw(this);
}
-void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform,
+void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
{
cairo_surface_t* image = nativeImageForCurrentFrame();
diff --git a/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp b/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
index b7a4cbb..6841599 100644
--- a/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
@@ -97,13 +97,21 @@ ImageSource::ImageSource()
ImageSource::~ImageSource()
{
- clear();
+ clear(true);
}
-void ImageSource::clear()
+void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
{
+ if (!destroyAll) {
+ if (m_decoder)
+ m_decoder->clearFrameBufferCache(clearBeforeFrame);
+ return;
+ }
+
delete m_decoder;
m_decoder = 0;
+ if (data)
+ setData(data, allDataReceived);
}
bool ImageSource::initialized() const
@@ -126,6 +134,14 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
m_decoder->setData(data, allDataReceived);
}
+String ImageSource::filenameExtension() const
+{
+ if (!m_decoder)
+ return String();
+
+ return m_decoder->filenameExtension();
+}
+
bool ImageSource::isSizeAvailable()
{
if (!m_decoder)
diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp
index 3f8d588..24354d2 100644
--- a/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -4,6 +4,7 @@
2004, 2005, 2006 Rob Buis <buis@kde.org>
2005, 2007 Apple Inc. All Rights reserved.
2007 Alp Toker <alp@atoker.com>
+ 2008 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
@@ -24,11 +25,13 @@
#include "config.h"
#include "Path.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "CairoPath.h"
#include "FloatRect.h"
+#include "GraphicsContext.h"
#include "NotImplemented.h"
#include "PlatformString.h"
+#include "StrokeStyleApplier.h"
#include <cairo.h>
#include <math.h>
@@ -153,9 +156,78 @@ void Path::addArc(const FloatPoint& p, float r, float sa, float ea, bool anticlo
void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
{
- // FIXME: cairo_arc_to not yet in cairo see cairo.h
- // cairo_arc_to(m_cr, p1.x(), p1.y(), p2.x(), p2.y());
- notImplemented();
+ if (isEmpty())
+ return;
+
+ cairo_t* cr = platformPath()->m_cr;
+
+ double x0, y0;
+ cairo_get_current_point(cr, &x0, &y0);
+ FloatPoint p0(x0, y0);
+ if ((p1.x() == p0.x() && p1.y() == p0.y()) || (p1.x() == p2.x() && p1.y() == p2.y()) || radius == 0.f) {
+ cairo_line_to(cr, p1.x(), p1.y());
+ return;
+ }
+
+ FloatPoint p1p0((p0.x() - p1.x()),(p0.y() - p1.y()));
+ FloatPoint p1p2((p2.x() - p1.x()),(p2.y() - p1.y()));
+ float p1p0_length = sqrtf(p1p0.x() * p1p0.x() + p1p0.y() * p1p0.y());
+ float p1p2_length = sqrtf(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y());
+
+ double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / (p1p0_length * p1p2_length);
+ // all points on a line logic
+ if (cos_phi == -1) {
+ cairo_line_to(cr, p1.x(), p1.y());
+ return;
+ }
+ if (cos_phi == 1) {
+ // add infinite far away point
+ unsigned int max_length = 65535;
+ double factor_max = max_length / p1p0_length;
+ FloatPoint ep((p0.x() + factor_max * p1p0.x()), (p0.y() + factor_max * p1p0.y()));
+ cairo_line_to(cr, ep.x(), ep.y());
+ return;
+ }
+
+ float tangent = radius / tan(acos(cos_phi) / 2);
+ float factor_p1p0 = tangent / p1p0_length;
+ FloatPoint t_p1p0((p1.x() + factor_p1p0 * p1p0.x()), (p1.y() + factor_p1p0 * p1p0.y()));
+
+ FloatPoint orth_p1p0(p1p0.y(), -p1p0.x());
+ float orth_p1p0_length = sqrt(orth_p1p0.x() * orth_p1p0.x() + orth_p1p0.y() * orth_p1p0.y());
+ float factor_ra = radius / orth_p1p0_length;
+
+ // angle between orth_p1p0 and p1p2 to get the right vector orthographic to p1p0
+ double cos_alpha = (orth_p1p0.x() * p1p2.x() + orth_p1p0.y() * p1p2.y()) / (orth_p1p0_length * p1p2_length);
+ if (cos_alpha < 0.f)
+ orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y());
+
+ FloatPoint p((t_p1p0.x() + factor_ra * orth_p1p0.x()), (t_p1p0.y() + factor_ra * orth_p1p0.y()));
+
+ // calculate angles for addArc
+ orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y());
+ float sa = acos(orth_p1p0.x() / orth_p1p0_length);
+ if (orth_p1p0.y() < 0.f)
+ sa = 2 * piDouble - sa;
+
+ // anticlockwise logic
+ bool anticlockwise = false;
+
+ float factor_p1p2 = tangent / p1p2_length;
+ FloatPoint t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 * p1p2.y()));
+ FloatPoint orth_p1p2((t_p1p2.x() - p.x()),(t_p1p2.y() - p.y()));
+ float orth_p1p2_length = sqrtf(orth_p1p2.x() * orth_p1p2.x() + orth_p1p2.y() * orth_p1p2.y());
+ float ea = acos(orth_p1p2.x() / orth_p1p2_length);
+ if (orth_p1p2.y() < 0)
+ ea = 2 * piDouble - ea;
+ if ((sa > ea) && ((sa - ea) < piDouble))
+ anticlockwise = true;
+ if ((sa < ea) && ((ea - sa) > piDouble))
+ anticlockwise = true;
+
+ cairo_line_to(cr, t_p1p0.x(), t_p1p0.y());
+
+ addArc(p, radius, sa, ea, anticlockwise);
}
void Path::addEllipse(const FloatRect& rect)
@@ -188,6 +260,19 @@ FloatRect Path::boundingRect() const
return FloatRect(x0, y0, x1 - x0, y1 - y0);
}
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+{
+ cairo_t* cr = platformPath()->m_cr;
+ if (applier) {
+ GraphicsContext gc(cr);
+ applier->strokeStyle(&gc);
+ }
+
+ double x0, x1, y0, y1;
+ cairo_stroke_extents(cr, &x0, &y0, &x1, &y1);
+ return FloatRect(x0, y0, x1 - x0, y1 - y0);
+}
+
bool Path::contains(const FloatPoint& point, WindRule rule) const
{
if (!boundingRect().contains(point))
@@ -201,6 +286,16 @@ bool Path::contains(const FloatPoint& point, WindRule rule) const
return contains;
}
+bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
+{
+ ASSERT(applier);
+ cairo_t* cr = platformPath()->m_cr;
+ GraphicsContext gc(cr);
+ applier->strokeStyle(&gc);
+
+ return cairo_in_stroke(cr, point.x(), point.y());
+}
+
void Path::apply(void* info, PathApplierFunction function) const
{
cairo_t* cr = platformPath()->m_cr;
@@ -239,7 +334,7 @@ void Path::apply(void* info, PathApplierFunction function) const
cairo_path_destroy(path);
}
-void Path::transform(const AffineTransform& trans)
+void Path::transform(const TransformationMatrix& trans)
{
cairo_t* m_cr = platformPath()->m_cr;
cairo_matrix_t c_matrix = cairo_matrix_t(trans);
@@ -249,37 +344,39 @@ void Path::transform(const AffineTransform& trans)
String Path::debugString() const
{
- String string = "";
+ if (isEmpty())
+ return String();
+
+ String pathString;
cairo_path_t* path = cairo_copy_path(platformPath()->m_cr);
cairo_path_data_t* data;
- if (!path->num_data )
- string = "EMPTY";
-
for (int i = 0; i < path->num_data; i += path->data[i].header.length) {
data = &path->data[i];
switch (data->header.type) {
case CAIRO_PATH_MOVE_TO:
- string += String::format("M %.2f,%.2f",
+ if (i < (path->num_data - path->data[i].header.length))
+ pathString += String::format("M%.2f,%.2f ",
data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_LINE_TO:
- string += String::format("L %.2f,%.2f",
+ pathString += String::format("L%.2f,%.2f ",
data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_CURVE_TO:
- string += String::format("C %.2f,%.2f,%.2f,%.2f,%.2f,%.2f",
+ pathString += String::format("C%.2f,%.2f,%.2f,%.2f,%.2f,%.2f ",
data[1].point.x, data[1].point.y,
data[2].point.x, data[2].point.y,
data[3].point.x, data[3].point.y);
break;
case CAIRO_PATH_CLOSE_PATH:
- string += "X";
+ pathString += "Z ";
break;
}
}
+
cairo_path_destroy(path);
- return string;
+ return pathString.simplifyWhiteSpace();
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/cairo/PatternCairo.cpp b/WebCore/platform/graphics/cairo/PatternCairo.cpp
index 16cebf8..7d75db3 100644
--- a/WebCore/platform/graphics/cairo/PatternCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PatternCairo.cpp
@@ -26,21 +26,22 @@
#include "config.h"
#include "Pattern.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "GraphicsContext.h"
#include <cairo.h>
namespace WebCore {
-cairo_pattern_t* Pattern::createPlatformPattern(const AffineTransform& patternTransform) const
+cairo_pattern_t* Pattern::createPlatformPattern(const TransformationMatrix& patternTransform) const
{
cairo_surface_t* surface = tileImage()->nativeImageForCurrentFrame();
if (!surface)
return 0;
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
- const cairo_matrix_t* pattern_matrix = reinterpret_cast<const cairo_matrix_t*>(&patternTransform);
+ const TransformationMatrix& inverse = patternTransform.inverse();
+ const cairo_matrix_t* pattern_matrix = reinterpret_cast<const cairo_matrix_t*>(&inverse);
cairo_pattern_set_matrix(pattern, pattern_matrix);
if (m_repeatX || m_repeatY)
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
diff --git a/WebCore/platform/graphics/cairo/AffineTransformCairo.cpp b/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp
index 0f2fccd..b78620f 100644
--- a/WebCore/platform/graphics/cairo/AffineTransformCairo.cpp
+++ b/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp
@@ -23,7 +23,7 @@
*/
#include "config.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "IntRect.h"
#include "FloatRect.h"
@@ -34,34 +34,34 @@ namespace WebCore {
static const double deg2rad = 0.017453292519943295769; // pi/180
-AffineTransform::AffineTransform()
+TransformationMatrix::TransformationMatrix()
{
cairo_matrix_init_identity(&m_transform);
}
-AffineTransform::AffineTransform(double a, double b, double c, double d, double tx, double ty)
+TransformationMatrix::TransformationMatrix(double a, double b, double c, double d, double tx, double ty)
{
cairo_matrix_init(&m_transform, a, b, c, d, tx, ty);
}
-AffineTransform::AffineTransform(const PlatformAffineTransform& matrix)
+TransformationMatrix::TransformationMatrix(const PlatformTransformationMatrix& matrix)
{
m_transform = matrix;
}
-void AffineTransform::setMatrix(double a, double b, double c, double d, double tx, double ty)
+void TransformationMatrix::setMatrix(double a, double b, double c, double d, double tx, double ty)
{
cairo_matrix_init(&m_transform, a, b, c, d, tx, ty);
}
-void AffineTransform::map(double x, double y, double* x2, double* y2) const
+void TransformationMatrix::map(double x, double y, double* x2, double* y2) const
{
*x2 = x;
*y2 = y;
cairo_matrix_transform_point(&m_transform, x2, y2);
}
-IntRect AffineTransform::mapRect(const IntRect &rect) const
+IntRect TransformationMatrix::mapRect(const IntRect &rect) const
{
FloatRect floatRect(rect);
FloatRect enclosingFloatRect = this->mapRect(floatRect);
@@ -69,7 +69,7 @@ IntRect AffineTransform::mapRect(const IntRect &rect) const
return enclosingIntRect(enclosingFloatRect);
}
-FloatRect AffineTransform::mapRect(const FloatRect &rect) const
+FloatRect TransformationMatrix::mapRect(const FloatRect &rect) const
{
double rectMinX = rect.x();
double rectMaxX = rect.x() + rect.width();
@@ -128,97 +128,97 @@ FloatRect AffineTransform::mapRect(const FloatRect &rect) const
return FloatRect(enclosingRectMinX, enclosingRectMinY, enclosingRectWidth, enclosingRectHeight);
}
-bool AffineTransform::isIdentity() const
+bool TransformationMatrix::isIdentity() const
{
return ((m_transform.xx == 1) && (m_transform.yy == 1)
&& (m_transform.xy == 0) && (m_transform.yx == 0)
&& (m_transform.x0 == 0) && (m_transform.y0 == 0));
}
-double AffineTransform::a() const
+double TransformationMatrix::a() const
{
return m_transform.xx;
}
-void AffineTransform::setA(double a)
+void TransformationMatrix::setA(double a)
{
m_transform.xx = a;
}
-double AffineTransform::b() const
+double TransformationMatrix::b() const
{
return m_transform.yx;
}
-void AffineTransform::setB(double b)
+void TransformationMatrix::setB(double b)
{
m_transform.yx = b;
}
-double AffineTransform::c() const
+double TransformationMatrix::c() const
{
return m_transform.xy;
}
-void AffineTransform::setC(double c)
+void TransformationMatrix::setC(double c)
{
m_transform.xy = c;
}
-double AffineTransform::d() const
+double TransformationMatrix::d() const
{
return m_transform.yy;
}
-void AffineTransform::setD(double d)
+void TransformationMatrix::setD(double d)
{
m_transform.yy = d;
}
-double AffineTransform::e() const
+double TransformationMatrix::e() const
{
return m_transform.x0;
}
-void AffineTransform::setE(double e)
+void TransformationMatrix::setE(double e)
{
m_transform.x0 = e;
}
-double AffineTransform::f() const
+double TransformationMatrix::f() const
{
return m_transform.y0;
}
-void AffineTransform::setF(double f)
+void TransformationMatrix::setF(double f)
{
m_transform.y0 = f;
}
-void AffineTransform::reset()
+void TransformationMatrix::reset()
{
cairo_matrix_init_identity(&m_transform);
}
-AffineTransform &AffineTransform::scale(double sx, double sy)
+TransformationMatrix &TransformationMatrix::scale(double sx, double sy)
{
cairo_matrix_scale(&m_transform, sx, sy);
return *this;
}
-AffineTransform &AffineTransform::rotate(double d)
+TransformationMatrix &TransformationMatrix::rotate(double d)
{
cairo_matrix_rotate(&m_transform, d * deg2rad);
return *this;
}
-AffineTransform &AffineTransform::translate(double tx, double ty)
+TransformationMatrix &TransformationMatrix::translate(double tx, double ty)
{
cairo_matrix_translate(&m_transform, tx, ty);
return *this;
}
-AffineTransform &AffineTransform::shear(double sx, double sy)
+TransformationMatrix &TransformationMatrix::shear(double sx, double sy)
{
cairo_matrix_t shear;
cairo_matrix_init(&shear, 1, sy, sx, 1, 0, 0);
@@ -230,26 +230,26 @@ AffineTransform &AffineTransform::shear(double sx, double sy)
return *this;
}
-double AffineTransform::det() const
+double TransformationMatrix::det() const
{
return m_transform.xx * m_transform.yy - m_transform.xy * m_transform.yx;
}
-AffineTransform AffineTransform::inverse() const
+TransformationMatrix TransformationMatrix::inverse() const
{
- if (!isInvertible()) return AffineTransform();
+ if (!isInvertible()) return TransformationMatrix();
cairo_matrix_t result = m_transform;
cairo_matrix_invert(&result);
- return AffineTransform(result);
+ return TransformationMatrix(result);
}
-AffineTransform::operator cairo_matrix_t() const
+TransformationMatrix::operator cairo_matrix_t() const
{
return m_transform;
}
-bool AffineTransform::operator== (const AffineTransform &m2) const
+bool TransformationMatrix::operator== (const TransformationMatrix &m2) const
{
return ((m_transform.xx == m2.m_transform.xx)
&& (m_transform.yy == m2.m_transform.yy)
@@ -260,7 +260,7 @@ bool AffineTransform::operator== (const AffineTransform &m2) const
}
-AffineTransform &AffineTransform::operator*= (const AffineTransform &m2)
+TransformationMatrix &TransformationMatrix::operator*= (const TransformationMatrix &m2)
{
cairo_matrix_t result;
cairo_matrix_multiply(&result, &m_transform, &m2.m_transform);
@@ -269,7 +269,7 @@ AffineTransform &AffineTransform::operator*= (const AffineTransform &m2)
return *this;
}
-AffineTransform AffineTransform::operator* (const AffineTransform &m2)
+TransformationMatrix TransformationMatrix::operator* (const TransformationMatrix &m2)
{
cairo_matrix_t result;
cairo_matrix_multiply(&result, &m_transform, &m2.m_transform);
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index 3f0e6e7..1cc55a4 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -28,7 +28,7 @@
#include "config.h"
#include "GraphicsContext.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatConversion.h"
#include "GraphicsContextPrivate.h"
#include "GraphicsContextPlatformPrivateCG.h"
@@ -191,11 +191,13 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
}
CGContextRef context = platformContext();
- CGContextSaveGState(context);
-
- CGContextSetShouldAntialias(context, false);
+
+ if (shouldAntialias())
+ CGContextSetShouldAntialias(context, false);
if (patWidth) {
+ CGContextSaveGState(context);
+
// Do a rect fill of our endpoints. This ensures we always have the
// appearance of being a border. We then draw the actual dotted/dashed line.
setCGFillColor(context, strokeColor()); // The save/restore make it safe to mutate the fill color here without setting it back to the old color.
@@ -245,7 +247,11 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
CGContextStrokePath(context);
- CGContextRestoreGState(context);
+ if (patWidth)
+ CGContextRestoreGState(context);
+
+ if (shouldAntialias())
+ CGContextSetShouldAntialias(context, true);
}
// This method is only used to draw the little circles used in lists.
@@ -358,7 +364,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
CGContextRestoreGState(context);
}
-void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
+void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool antialiased)
{
if (paintingDisabled() || !fillColor().alpha() && (strokeThickness() <= 0 || strokeStyle() == NoStroke))
return;
@@ -368,9 +374,8 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
CGContextRef context = platformContext();
- CGContextSaveGState(context);
-
- CGContextSetShouldAntialias(context, shouldAntialias);
+ if (antialiased != shouldAntialias())
+ CGContextSetShouldAntialias(context, antialiased);
CGContextBeginPath(context);
CGContextMoveToPoint(context, points[0].x(), points[0].y());
@@ -379,15 +384,16 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
CGContextClosePath(context);
drawPath();
-
- CGContextRestoreGState(context);
+
+ if (antialiased != shouldAntialias())
+ CGContextSetShouldAntialias(context, shouldAntialias());
}
-static void applyStrokePattern(GraphicsContext* context, Pattern* pattern)
+void GraphicsContext::applyStrokePattern()
{
- CGContextRef cgContext = context->platformContext();
+ CGContextRef cgContext = platformContext();
- CGPatternRef platformPattern = pattern->createPlatformPattern(context->getCTM());
+ CGPatternRef platformPattern = m_common->state.strokePattern.get()->createPlatformPattern(getCTM());
if (!platformPattern)
return;
@@ -400,11 +406,11 @@ static void applyStrokePattern(GraphicsContext* context, Pattern* pattern)
CGPatternRelease(platformPattern);
}
-static void applyFillPattern(GraphicsContext* context, Pattern* pattern)
+void GraphicsContext::applyFillPattern()
{
- CGContextRef cgContext = context->platformContext();
+ CGContextRef cgContext = platformContext();
- CGPatternRef platformPattern = pattern->createPlatformPattern(context->getCTM());
+ CGPatternRef platformPattern = m_common->state.fillPattern.get()->createPlatformPattern(getCTM());
if (!platformPattern)
return;
@@ -460,9 +466,9 @@ void GraphicsContext::drawPath()
}
if (state.fillColorSpace == PatternColorSpace)
- applyFillPattern(this, m_common->state.fillPattern.get());
+ applyFillPattern();
if (state.strokeColorSpace == PatternColorSpace)
- applyStrokePattern(this, m_common->state.strokePattern.get());
+ applyStrokePattern();
CGPathDrawingMode drawingMode;
if (calculateDrawingMode(state, drawingMode))
@@ -489,7 +495,7 @@ void GraphicsContext::fillPath()
fillPathWithFillRule(context, fillRule());
break;
case PatternColorSpace:
- applyFillPattern(this, m_common->state.fillPattern.get());
+ applyFillPattern();
fillPathWithFillRule(context, fillRule());
break;
case GradientColorSpace:
@@ -512,11 +518,11 @@ void GraphicsContext::strokePath()
CGContextRef context = platformContext();
switch (m_common->state.strokeColorSpace) {
case SolidColorSpace:
- if (fillColor().alpha())
+ if (strokeColor().alpha())
CGContextStrokePath(context);
break;
case PatternColorSpace:
- applyStrokePattern(this, m_common->state.strokePattern.get());
+ applyStrokePattern();
CGContextStrokePath(context);
break;
case GradientColorSpace:
@@ -540,7 +546,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
CGContextFillRect(context, rect);
break;
case PatternColorSpace:
- applyFillPattern(this, m_common->state.fillPattern.get());
+ applyFillPattern();
CGContextFillRect(context, rect);
break;
case GradientColorSpace:
@@ -614,6 +620,21 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
CGContextEOClip(platformContext());
}
+void GraphicsContext::clipPath(WindRule clipRule)
+{
+ if (paintingDisabled())
+ return;
+
+ CGContextRef context = platformContext();
+
+ if (!CGContextIsPathEmpty(context)) {
+ if (clipRule == RULE_EVENODD)
+ CGContextEOClip(context);
+ else
+ CGContextClip(context);
+ }
+}
+
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
{
if (paintingDisabled())
@@ -670,23 +691,30 @@ void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Col
{
if (paintingDisabled())
return;
+ CGFloat width = size.width();
+ CGFloat height = size.height();
+ CGFloat blurRadius = blur;
CGContextRef context = platformContext();
- CGAffineTransform transform = CGContextGetCTM(context);
- CGFloat A = transform.a * transform.a + transform.b * transform.b;
- CGFloat B = transform.a * transform.c + transform.b * transform.d;
- CGFloat C = B;
- CGFloat D = transform.c * transform.c + transform.d * transform.d;
+ if (!m_common->state.shadowsIgnoreTransforms) {
+ CGAffineTransform transform = CGContextGetCTM(context);
- CGFloat smallEigenvalue = narrowPrecisionToCGFloat(sqrt(0.5 * ((A + D) - sqrt(4 * B * C + (A - D) * (A - D)))));
+ CGFloat A = transform.a * transform.a + transform.b * transform.b;
+ CGFloat B = transform.a * transform.c + transform.b * transform.d;
+ CGFloat C = B;
+ CGFloat D = transform.c * transform.c + transform.d * transform.d;
- // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp
- CGFloat blurRadius = min(blur * smallEigenvalue, narrowPrecisionToCGFloat(1000.0));
+ CGFloat smallEigenvalue = narrowPrecisionToCGFloat(sqrt(0.5 * ((A + D) - sqrt(4 * B * C + (A - D) * (A - D)))));
- CGSize sizeInDeviceSpace = CGSizeApplyAffineTransform(size, transform);
+ // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp
+ blurRadius = min(blur * smallEigenvalue, narrowPrecisionToCGFloat(1000.0));
- CGFloat width = sizeInDeviceSpace.width;
- CGFloat height = sizeInDeviceSpace.height;
+ CGSize sizeInDeviceSpace = CGSizeApplyAffineTransform(size, transform);
+
+ width = sizeInDeviceSpace.width;
+ height = sizeInDeviceSpace.height;
+
+ }
// Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated
// to the desired integer.
@@ -747,7 +775,27 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
{
if (paintingDisabled())
return;
- CGContextStrokeRectWithWidth(platformContext(), r, lineWidth);
+
+ CGContextRef context = platformContext();
+ switch (m_common->state.strokeColorSpace) {
+ case SolidColorSpace:
+ if (strokeColor().alpha())
+ CGContextStrokeRectWithWidth(context, r, lineWidth);
+ break;
+ case PatternColorSpace:
+ applyStrokePattern();
+ CGContextStrokeRectWithWidth(context, r, lineWidth);
+ break;
+ case GradientColorSpace:
+ CGContextSaveGState(context);
+ setStrokeThickness(lineWidth);
+ CGContextAddRect(context, r);
+ CGContextReplacePathWithStrokedPath(context);
+ CGContextClip(context);
+ CGContextDrawShading(context, m_common->state.strokeGradient->platformGradient());
+ CGContextRestoreGState(context);
+ break;
+ }
}
void GraphicsContext::setLineCap(LineCap cap)
@@ -848,7 +896,7 @@ void GraphicsContext::translate(float x, float y)
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
}
-void GraphicsContext::concatCTM(const AffineTransform& transform)
+void GraphicsContext::concatCTM(const TransformationMatrix& transform)
{
if (paintingDisabled())
return;
@@ -857,7 +905,7 @@ void GraphicsContext::concatCTM(const AffineTransform& transform)
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
}
-AffineTransform GraphicsContext::getCTM() const
+TransformationMatrix GraphicsContext::getCTM() const
{
return CGContextGetCTM(platformContext());
}
@@ -909,8 +957,6 @@ void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool pri
if (width <= 0)
return;
- CGContextSaveGState(platformContext());
-
float x = point.x();
float y = point.y();
float lineLength = width;
@@ -919,6 +965,8 @@ void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool pri
// See http://bugs.webkit.org/show_bug.cgi?id=4255 for details of why 0.5 is the right minimum thickness to use.
float thickness = max(strokeThickness(), 0.5f);
+ bool restoreAntialiasMode = false;
+
if (!printing) {
// On screen, use a minimum thickness of 1.0 in user space (later rounded to an integral number in device space).
float adjustedThickness = max(thickness, 1.0f);
@@ -933,15 +981,21 @@ void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool pri
y = lineRect.origin.y;
lineLength = lineRect.size.width;
thickness = lineRect.size.height;
- CGContextSetShouldAntialias(platformContext(), false);
+ if (shouldAntialias()) {
+ CGContextSetShouldAntialias(platformContext(), false);
+ restoreAntialiasMode = true;
+ }
}
}
if (fillColor() != strokeColor())
setCGFillColor(platformContext(), strokeColor());
CGContextFillRect(platformContext(), CGRectMake(x, y, lineLength, thickness));
-
- CGContextRestoreGState(platformContext());
+ if (fillColor() != strokeColor())
+ setCGFillColor(platformContext(), fillColor());
+
+ if (restoreAntialiasMode)
+ CGContextSetShouldAntialias(platformContext(), true);
}
void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
@@ -1078,7 +1132,7 @@ void GraphicsContext::setPlatformFillColor(const Color& color)
setCGFillColor(platformContext(), color);
}
-void GraphicsContext::setUseAntialiasing(bool enable)
+void GraphicsContext::setPlatformShouldAntialias(bool enable)
{
if (paintingDisabled())
return;
diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
index 8827ff7..beee660 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
+++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -34,6 +34,7 @@ public:
#if PLATFORM(WIN)
, m_hdc(0)
, m_transparencyCount(0)
+ , m_shouldIncludeChildWindows(false)
#endif
, m_userToDeviceTransformKnownToBeIdentity(false)
{
@@ -54,7 +55,7 @@ public:
void scale(const FloatSize&) {}
void rotate(float) {}
void translate(float, float) {}
- void concatCTM(const AffineTransform&) {}
+ void concatCTM(const TransformationMatrix&) {}
void beginTransparencyLayer() {}
void endTransparencyLayer() {}
#endif
@@ -68,12 +69,13 @@ public:
void scale(const FloatSize&);
void rotate(float);
void translate(float, float);
- void concatCTM(const AffineTransform&);
+ void concatCTM(const TransformationMatrix&);
void beginTransparencyLayer() { m_transparencyCount++; }
void endTransparencyLayer() { m_transparencyCount--; }
HDC m_hdc;
unsigned m_transparencyCount;
+ bool m_shouldIncludeChildWindows;
#endif
CGContextRef m_cgContext;
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 502313b..96e5604 100644
--- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -107,7 +107,7 @@ Image* ImageBuffer::image() const
PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
{
PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
- unsigned char* data = result->data()->data().data();
+ unsigned char* data = result->data()->data()->data();
if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height())
memset(data, 0, result->data()->length());
@@ -188,7 +188,7 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
unsigned srcBytesPerRow = 4 * source->width();
unsigned destBytesPerRow = 4 * m_size.width();
- unsigned char* srcRows = source->data()->data().data() + originy * srcBytesPerRow + originx * 4;
+ unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
unsigned char* destRows = reinterpret_cast<unsigned char*>(m_data.m_data) + desty * destBytesPerRow + destx * 4;
for (int y = 0; y < numRows; ++y) {
for (int x = 0; x < numColumns; x++) {
diff --git a/WebCore/platform/graphics/cg/ImageCG.cpp b/WebCore/platform/graphics/cg/ImageCG.cpp
index 8609c46..13c8c07 100644
--- a/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -28,7 +28,7 @@
#if PLATFORM(CG)
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatConversion.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
@@ -47,15 +47,17 @@
namespace WebCore {
-void FrameData::clear()
+bool FrameData::clear(bool clearMetadata)
{
+ if (clearMetadata)
+ m_haveMetadata = false;
+
if (m_frame) {
CGImageRelease(m_frame);
m_frame = 0;
- // NOTE: We purposefully don't reset metadata here, so that even if we
- // throw away previously-decoded data, animation loops can still access
- // properties like frame durations without re-decoding.
+ return true;
}
+ return false;
}
// ================================================
@@ -207,7 +209,7 @@ void Image::drawPatternCallback(void* info, CGContextRef context)
CGContextDrawImage(context, GraphicsContext(context).roundToDevicePixels(FloatRect(0, 0, CGImageGetWidth(image), CGImageGetHeight(image))), image);
}
-void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
+void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
{
if (!nativeImageForCurrentFrame())
@@ -251,9 +253,14 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
// its buffer is the same size as the overall image. Because a partially decoded CGImageRef with a smaller width or height than the
// overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case.
// FIXME: Could create WebKitSystemInterface SPI for CGCreatePatternWithImage2 and probably make Tiger tile faster as well.
+ // FIXME: We cannot use CGContextDrawTiledImage with scaled tiles on Leopard, because it suffers from rounding errors. Snow Leopard is ok.
float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a());
float w = CGImageGetWidth(tileImage);
+#ifdef BUILDING_ON_LEOPARD
+ if (w == size().width() && h == size().height() && scaledTileWidth == tileRect.width() && scaledTileHeight == tileRect.height())
+#else
if (w == size().width() && h == size().height())
+#endif
CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage);
else {
#endif
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index 73907c9..0b276cc 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -27,8 +27,10 @@
#include "ImageSource.h"
#if PLATFORM(CG)
+#include "ImageSourceCG.h"
#include "IntSize.h"
+#include "MIMETypeRegistry.h"
#include "SharedBuffer.h"
#include <ApplicationServices/ApplicationServices.h>
@@ -43,18 +45,23 @@ ImageSource::ImageSource()
ImageSource::~ImageSource()
{
- clear();
+ clear(true);
}
-void ImageSource::clear()
+void ImageSource::clear(bool, 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 (m_decoder) {
CFRelease(m_decoder);
m_decoder = 0;
}
+ if (data)
+ setData(data, allDataReceived);
}
-CFDictionaryRef imageSourceOptions()
+static CFDictionaryRef imageSourceOptions()
{
static CFDictionaryRef options;
@@ -89,6 +96,14 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
CFRelease(cfData);
}
+String ImageSource::filenameExtension() const
+{
+ if (!m_decoder)
+ return String();
+ CFStringRef imageSourceType = CGImageSourceGetType(m_decoder);
+ return WebCore::preferredExtensionForImageSourceType(imageSourceType);
+}
+
bool ImageSource::isSizeAvailable()
{
bool result = false;
@@ -210,7 +225,7 @@ float ImageSource::frameDurationAtIndex(size_t index)
return duration;
}
-bool ImageSource::frameHasAlphaAtIndex(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.
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.h b/WebCore/platform/graphics/cg/ImageSourceCG.h
new file mode 100644
index 0000000..d5b4b5a
--- /dev/null
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ImageSourceCG_h
+#define ImageSourceCG_h
+
+#include "ImageSource.h"
+
+namespace WebCore {
+
+class String;
+
+String preferredExtensionForImageSourceType(const String& type);
+
+String MIMETypeForImageSourceType(const String& type);
+
+}
+
+#endif // ImageSourceCG_h
diff --git a/WebCore/platform/graphics/cg/ImageSourceCGMac.mm b/WebCore/platform/graphics/cg/ImageSourceCGMac.mm
new file mode 100644
index 0000000..297e30a
--- /dev/null
+++ b/WebCore/platform/graphics/cg/ImageSourceCGMac.mm
@@ -0,0 +1,48 @@
+/*
+ * 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
+ * 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.
+ */
+
+#import "config.h"
+#import "ImageSourceCG.h"
+
+#import "PlatformString.h"
+#import "wtf/RetainPtr.h"
+
+namespace WebCore {
+
+String MIMETypeForImageSourceType(const String& uti)
+{
+ RetainPtr<CFStringRef> utiref(AdoptCF, uti.createCFString());
+ RetainPtr<CFStringRef> mime(AdoptCF, UTTypeCopyPreferredTagWithClass(utiref.get(), kUTTagClassMIMEType));
+ return mime.get();
+}
+
+String preferredExtensionForImageSourceType(const String& uti)
+{
+ RetainPtr<CFStringRef> type(AdoptCF, uti.createCFString());
+ RetainPtr<CFStringRef> extension(AdoptCF, UTTypeCopyPreferredTagWithClass(type.get(), kUTTagClassFilenameExtension));
+ return extension.get();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp b/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp
new file mode 100644
index 0000000..c7d9a0b
--- /dev/null
+++ b/WebCore/platform/graphics/cg/ImageSourceCGWin.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ImageSourceCG.h"
+
+#include "StdLibExtras.h"
+#include "StringHash.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+String MIMETypeForImageSourceType(const String& type)
+{
+ String mimeType;
+ // FIXME: This approach of taking a UTI like public.type and giving back
+ // a MIME type like image/type will work for common image UTIs like jpeg,
+ // png, tiff, gif but won't work for UTIs like: public.jpeg-2000,
+ // public.xbitmap-image, com.apple.quicktime-image, and others.
+ if (int dotLocation = type.reverseFind('.'))
+ mimeType = "image/" + type.substring(dotLocation + 1);
+ return mimeType;
+}
+
+String preferredExtensionForImageSourceType(const String& type)
+{
+ if (type.isEmpty())
+ return String();
+
+ typedef HashMap<String, String> StringMap;
+ DEFINE_STATIC_LOCAL(StringMap, UTIMap, ());
+ if (UTIMap.isEmpty()) {
+ UTIMap.add("public.html", "html");
+ UTIMap.add("public.jpeg", "jpeg");
+ UTIMap.add("public.jpeg-2000", "jp2");
+ UTIMap.add("public.plain-text", "txt");
+ UTIMap.add("public.png", "png");
+ UTIMap.add("public.tiff", "tiff");
+ UTIMap.add("public.xbitmap-image", "xbm");
+ UTIMap.add("public.xml", "xml");
+ UTIMap.add("com.adobe.illustrator.ai-image", "ai");
+ UTIMap.add("com.adobe.pdf", "pdf");
+ UTIMap.add("com.adobe.photoshop-image", "psd");
+ UTIMap.add("com.adobe.postscript", "ps");
+ UTIMap.add("com.apple.icns", "icns");
+ UTIMap.add("com.apple.macpaint-image", "pntg");
+ UTIMap.add("com.apple.pict", "pict");
+ UTIMap.add("com.apple.quicktime-image", "qtif");
+ UTIMap.add("com.apple.webarchive", "webarchive");
+ UTIMap.add("com.compuserve.gif", "gif");
+ UTIMap.add("com.ilm.openexr-image", "exr");
+ UTIMap.add("com.kodak.flashpix-image", "fpx");
+ UTIMap.add("com.microsoft.bmp", "bmp");
+ UTIMap.add("com.microsoft.ico", "ico");
+ UTIMap.add("com.netscape.javascript-source", "js");
+ UTIMap.add("com.sgi.sgi-image", "sgi");
+ UTIMap.add("com.truevision.tga-image", "tga");
+ }
+ return UTIMap.get(type);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.h b/WebCore/platform/graphics/cg/PDFDocumentImage.h
index 5c9d4e1..130c12c 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.h
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.h
@@ -42,7 +42,9 @@ namespace WebCore {
{
return adoptRef(new PDFDocumentImage);
}
- ~PDFDocumentImage();
+
+ private:
+ virtual ~PDFDocumentImage();
virtual bool hasSingleSecurityOrigin() const { return true; }
@@ -50,12 +52,11 @@ namespace WebCore {
// FIXME: PDF Images are underreporting decoded sizes and will be unable
// to prune because these functions are not implemented yet.
- virtual void destroyDecodedData(bool incremental = false, bool preserveNearbyFrames = false) { }
+ virtual void destroyDecodedData(bool /*destroyAll*/ = true) { }
virtual unsigned decodedSize() const { return 0; }
virtual IntSize size() const;
- private:
PDFDocumentImage();
virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
diff --git a/WebCore/platform/graphics/cg/PathCG.cpp b/WebCore/platform/graphics/cg/PathCG.cpp
index 1382589..ebd0359 100644
--- a/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/WebCore/platform/graphics/cg/PathCG.cpp
@@ -29,16 +29,43 @@
#if PLATFORM(CG)
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include <ApplicationServices/ApplicationServices.h>
#include "FloatRect.h"
+#include "GraphicsContext.h"
#include "IntRect.h"
#include "PlatformString.h"
+#include "StrokeStyleApplier.h"
#include <wtf/MathExtras.h>
namespace WebCore {
+static size_t putBytesNowhere(void*, const void*, size_t count)
+{
+ return count;
+}
+
+static CGContextRef createScratchContext()
+{
+ CGDataConsumerCallbacks callbacks = { putBytesNowhere, 0 };
+ CGDataConsumerRef consumer = CGDataConsumerCreate(0, &callbacks);
+ CGContextRef context = CGPDFContextCreate(consumer, 0, 0);
+ CGDataConsumerRelease(consumer);
+
+ CGFloat black[4] = { 0, 0, 0, 1 };
+ CGContextSetFillColor(context, black);
+ CGContextSetStrokeColor(context, black);
+
+ return context;
+}
+
+static inline CGContextRef scratchContext()
+{
+ static CGContextRef context = createScratchContext();
+ return context;
+}
+
Path::Path()
: m_path(CGPathCreateMutable())
{
@@ -62,7 +89,6 @@ Path& Path::operator=(const Path& other)
return *this;
}
-
static void copyClosingSubpathsApplierFunction(void* info, const CGPathElement* element)
{
CGMutablePathRef path = static_cast<CGMutablePathRef>(info);
@@ -109,6 +135,25 @@ bool Path::contains(const FloatPoint &point, WindRule rule) const
return ret;
}
+bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
+{
+ ASSERT(applier);
+
+ CGContextRef context = scratchContext();
+
+ CGContextSaveGState(context);
+ CGContextBeginPath(context);
+ CGContextAddPath(context, platformPath());
+
+ GraphicsContext gc(context);
+ applier->strokeStyle(&gc);
+
+ bool hitSuccess = CGContextPathContainsPoint(context, point, kCGPathStroke);
+ CGContextRestoreGState(context);
+
+ return hitSuccess;
+}
+
void Path::translate(const FloatSize& size)
{
CGAffineTransform translation = CGAffineTransformMake(1, 0, 0, 1, size.width(), size.height());
@@ -123,6 +168,26 @@ FloatRect Path::boundingRect() const
return CGPathGetBoundingBox(m_path);
}
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+{
+ CGContextRef context = scratchContext();
+
+ CGContextSaveGState(context);
+ CGContextBeginPath(context);
+ CGContextAddPath(context, platformPath());
+
+ if (applier) {
+ GraphicsContext graphicsContext(context);
+ applier->strokeStyle(&graphicsContext);
+ }
+
+ CGContextReplacePathWithStrokedPath(context);
+ CGRect box = CGContextIsPathEmpty(context) ? CGRectZero : CGContextGetPathBoundingBox(context);
+ CGContextRestoreGState(context);
+
+ return box;
+}
+
void Path::moveTo(const FloatPoint& point)
{
CGPathMoveToPoint(m_path, 0, point.x(), point.y());
@@ -184,8 +249,8 @@ bool Path::isEmpty() const
static void CGPathToCFStringApplierFunction(void* info, const CGPathElement *element)
{
- CFMutableStringRef string = (CFMutableStringRef)info;
- CFStringRef typeString = CFSTR("");
+ CFMutableStringRef string = static_cast<CFMutableStringRef>(info);
+
CGPoint* points = element->points;
switch (element->type) {
case kCGPathElementMoveToPoint:
@@ -204,7 +269,8 @@ static void CGPathToCFStringApplierFunction(void* info, const CGPathElement *ele
points[2].x, points[2].y);
break;
case kCGPathElementCloseSubpath:
- typeString = CFSTR("X"); break;
+ CFStringAppendFormat(string, 0, CFSTR("Z "));
+ break;
}
}
@@ -241,7 +307,7 @@ struct PathApplierInfo {
PathApplierFunction function;
};
-void CGPathApplierToPathApplier(void *info, const CGPathElement *element)
+static void CGPathApplierToPathApplier(void *info, const CGPathElement *element)
{
PathApplierInfo* pinfo = (PathApplierInfo*)info;
FloatPoint points[3];
@@ -277,7 +343,7 @@ void Path::apply(void* info, PathApplierFunction function) const
CGPathApply(m_path, &pinfo, CGPathApplierToPathApplier);
}
-void Path::transform(const AffineTransform& transform)
+void Path::transform(const TransformationMatrix& transform)
{
CGMutablePathRef path = CGPathCreateMutable();
CGAffineTransform transformCG = transform;
diff --git a/WebCore/platform/graphics/cg/PatternCG.cpp b/WebCore/platform/graphics/cg/PatternCG.cpp
index e1f7a69..2b9c12f 100644
--- a/WebCore/platform/graphics/cg/PatternCG.cpp
+++ b/WebCore/platform/graphics/cg/PatternCG.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "Pattern.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "GraphicsContext.h"
#include <ApplicationServices/ApplicationServices.h>
@@ -50,11 +50,11 @@ static void patternReleaseCallback(void* info)
static_cast<Image*>(info)->deref();
}
-CGPatternRef Pattern::createPlatformPattern(const AffineTransform& transform) const
+CGPatternRef Pattern::createPlatformPattern(const TransformationMatrix& transform) const
{
IntRect tileRect = tileImage()->rect();
- AffineTransform patternTransform = transform;
+ TransformationMatrix patternTransform = transform;
patternTransform.scale(1, -1);
patternTransform.translate(0, -tileRect.height());
diff --git a/WebCore/platform/graphics/cg/AffineTransformCG.cpp b/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp
index 4f0bca0..9b3181a 100644
--- a/WebCore/platform/graphics/cg/AffineTransformCG.cpp
+++ b/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp
@@ -24,7 +24,7 @@
*/
#include "config.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#if PLATFORM(CG)
@@ -36,12 +36,12 @@
namespace WebCore {
-AffineTransform::AffineTransform()
+TransformationMatrix::TransformationMatrix()
: m_transform(CGAffineTransformIdentity)
{
}
-AffineTransform::AffineTransform(double a, double b, double c, double d, double tx, double ty)
+TransformationMatrix::TransformationMatrix(double a, double b, double c, double d, double tx, double ty)
{
m_transform = CGAffineTransformMake(narrowPrecisionToCGFloat(a),
narrowPrecisionToCGFloat(b),
@@ -51,12 +51,12 @@ AffineTransform::AffineTransform(double a, double b, double c, double d, double
narrowPrecisionToCGFloat(ty));
}
-AffineTransform::AffineTransform(const PlatformAffineTransform& t)
+TransformationMatrix::TransformationMatrix(const PlatformTransformationMatrix& t)
: m_transform(t)
{
}
-void AffineTransform::setMatrix(double a, double b, double c, double d, double tx, double ty)
+void TransformationMatrix::setMatrix(double a, double b, double c, double d, double tx, double ty)
{
m_transform = CGAffineTransformMake(narrowPrecisionToCGFloat(a),
narrowPrecisionToCGFloat(b),
@@ -66,147 +66,147 @@ void AffineTransform::setMatrix(double a, double b, double c, double d, double t
narrowPrecisionToCGFloat(ty));
}
-void AffineTransform::map(double x, double y, double *x2, double *y2) const
+void TransformationMatrix::map(double x, double y, double *x2, double *y2) const
{
CGPoint result = CGPointApplyAffineTransform(CGPointMake(narrowPrecisionToCGFloat(x), narrowPrecisionToCGFloat(y)), m_transform);
*x2 = result.x;
*y2 = result.y;
}
-IntRect AffineTransform::mapRect(const IntRect &rect) const
+IntRect TransformationMatrix::mapRect(const IntRect &rect) const
{
return enclosingIntRect(CGRectApplyAffineTransform(CGRect(rect), m_transform));
}
-FloatRect AffineTransform::mapRect(const FloatRect &rect) const
+FloatRect TransformationMatrix::mapRect(const FloatRect &rect) const
{
return FloatRect(CGRectApplyAffineTransform(CGRect(rect), m_transform));
}
-bool AffineTransform::isIdentity() const
+bool TransformationMatrix::isIdentity() const
{
return CGAffineTransformIsIdentity(m_transform);
}
-double AffineTransform::a() const
+double TransformationMatrix::a() const
{
return m_transform.a;
}
-void AffineTransform::setA(double a)
+void TransformationMatrix::setA(double a)
{
m_transform.a = narrowPrecisionToCGFloat(a);
}
-double AffineTransform::b() const
+double TransformationMatrix::b() const
{
return m_transform.b;
}
-void AffineTransform::setB(double b)
+void TransformationMatrix::setB(double b)
{
m_transform.b = narrowPrecisionToCGFloat(b);
}
-double AffineTransform::c() const
+double TransformationMatrix::c() const
{
return m_transform.c;
}
-void AffineTransform::setC(double c)
+void TransformationMatrix::setC(double c)
{
m_transform.c = narrowPrecisionToCGFloat(c);
}
-double AffineTransform::d() const
+double TransformationMatrix::d() const
{
return m_transform.d;
}
-void AffineTransform::setD(double d)
+void TransformationMatrix::setD(double d)
{
m_transform.d = narrowPrecisionToCGFloat(d);
}
-double AffineTransform::e() const
+double TransformationMatrix::e() const
{
return m_transform.tx;
}
-void AffineTransform::setE(double e)
+void TransformationMatrix::setE(double e)
{
m_transform.tx = narrowPrecisionToCGFloat(e);
}
-double AffineTransform::f() const
+double TransformationMatrix::f() const
{
return m_transform.ty;
}
-void AffineTransform::setF(double f)
+void TransformationMatrix::setF(double f)
{
m_transform.ty = narrowPrecisionToCGFloat(f);
}
-void AffineTransform::reset()
+void TransformationMatrix::reset()
{
m_transform = CGAffineTransformIdentity;
}
-AffineTransform &AffineTransform::scale(double sx, double sy)
+TransformationMatrix &TransformationMatrix::scale(double sx, double sy)
{
m_transform = CGAffineTransformScale(m_transform, narrowPrecisionToCGFloat(sx), narrowPrecisionToCGFloat(sy));
return *this;
}
-AffineTransform &AffineTransform::rotate(double d)
+TransformationMatrix &TransformationMatrix::rotate(double d)
{
m_transform = CGAffineTransformRotate(m_transform, narrowPrecisionToCGFloat(deg2rad(d)));
return *this;
}
-AffineTransform &AffineTransform::translate(double tx, double ty)
+TransformationMatrix &TransformationMatrix::translate(double tx, double ty)
{
m_transform = CGAffineTransformTranslate(m_transform, narrowPrecisionToCGFloat(tx), narrowPrecisionToCGFloat(ty));
return *this;
}
-AffineTransform &AffineTransform::shear(double sx, double sy)
+TransformationMatrix &TransformationMatrix::shear(double sx, double sy)
{
CGAffineTransform shear = CGAffineTransformMake(1.0f, narrowPrecisionToCGFloat(sy), narrowPrecisionToCGFloat(sx), 1.0f, 0.0f, 0.0f);
m_transform = CGAffineTransformConcat(shear, m_transform);
return *this;
}
-double AffineTransform::det() const
+double TransformationMatrix::det() const
{
return m_transform.a * m_transform.d - m_transform.b * m_transform.c;
}
-AffineTransform AffineTransform::inverse() const
+TransformationMatrix TransformationMatrix::inverse() const
{
if (isInvertible())
- return AffineTransform(CGAffineTransformInvert(m_transform));
- return AffineTransform();
+ return TransformationMatrix(CGAffineTransformInvert(m_transform));
+ return TransformationMatrix();
}
-AffineTransform::operator PlatformAffineTransform() const
+TransformationMatrix::operator PlatformTransformationMatrix() const
{
return m_transform;
}
-bool AffineTransform::operator== (const AffineTransform &m2) const
+bool TransformationMatrix::operator== (const TransformationMatrix &m2) const
{
return CGAffineTransformEqualToTransform(m_transform, CGAffineTransform(m2));
}
-AffineTransform &AffineTransform::operator*= (const AffineTransform &m2)
+TransformationMatrix &TransformationMatrix::operator*= (const TransformationMatrix &m2)
{
m_transform = CGAffineTransformConcat(m_transform, CGAffineTransform(m2));
return *this;
}
-AffineTransform AffineTransform::operator* (const AffineTransform &m2)
+TransformationMatrix TransformationMatrix::operator* (const TransformationMatrix &m2)
{
return CGAffineTransformConcat(m_transform, CGAffineTransform(m2));
}
diff --git a/WebCore/platform/graphics/chromium/ColorChromium.cpp b/WebCore/platform/graphics/chromium/ColorChromium.cpp
new file mode 100644
index 0000000..16ca17d
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/ColorChromium.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "Color.h"
+
+namespace WebCore {
+
+Color focusRingColor()
+{
+// FIXME: This should be split up to ColorChromiumWin and ColorChromiumMac.
+#if PLATFORM(DARWIN)
+ // To avoid the Mac Chromium build having to rebasline 500+ layout tests and
+ // continue to do this w/ new tests that get landed in WebKit, we want to
+ // run the layout tests w/ the same color that stock WebKit uses.
+ //
+ // TODO: For now we've hard coded the color that WebKit uses for layout
+ // tests. We need to revisit this and do either of the following:
+ // A. Fully honor the color from the UI, which means collecting the color
+ // (and change notifications) in the browser process, and messaging the
+ // color to the render process.
+ // B. Adding a "layout tests" flag, to control the orage vs. blue colors
+ // depending if we're running layout tests.
+ // To see the WebKit implementation of using the UI color and/or a flag for
+ // layout tests see WebKit/WebCore/platform/graphics/mac/ColorMac.mm.
+ // (Reality is we just need an api to override the focus color and both
+ // of the above are covered for what this file needs to provide, the
+ // two options would be details that happen in other places.)
+
+ // From WebKit:
+ // static RGBA32 oldAquaFocusRingColorRGBA = 0xFF7DADD9;
+ static Color oldAquaFocusRingColor(0x7D, 0xAD, 0xD9, 0xFF);
+ return oldAquaFocusRingColor;
+#else
+ static Color focusRingColor(229, 151, 0, 255);
+ return focusRingColor;
+#endif
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
new file mode 100644
index 0000000..03583a0
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -0,0 +1,602 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, Inc.
+ * Copyright (c) 2006, 2007, 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 "config.h"
+#include "FontCache.h"
+
+#include "ChromiumBridge.h"
+#include "Font.h"
+#include "FontUtilsChromiumWin.h"
+#include "HashMap.h"
+#include "HashSet.h"
+#include "SimpleFontData.h"
+#include "StringHash.h"
+#include <unicode/uniset.h>
+
+#include <windows.h>
+#include <objidl.h>
+#include <mlang.h>
+
+using std::min;
+
+namespace WebCore
+{
+
+void FontCache::platformInit()
+{
+ // Not needed on Windows.
+}
+
+// FIXME: consider adding to WebKit String class
+static bool charactersAreAllASCII(const String& s)
+{
+ return charactersAreAllASCII(s.characters(), s.length());
+}
+
+// When asked for a CJK font with a native name under a non-CJK locale or
+// asked for a CJK font with a Romanized name under a CJK locale,
+// |GetTextFace| (after |CreateFont*|) returns a 'bogus' value (e.g. Arial).
+// This is not consistent with what MSDN says !!
+// Therefore, before we call |CreateFont*|, we have to map a Romanized name to
+// the corresponding native name under a CJK locale and vice versa
+// under a non-CJK locale.
+// See the corresponding gecko bugs at
+// https://bugzilla.mozilla.org/show_bug.cgi?id=373952
+// https://bugzilla.mozilla.org/show_bug.cgi?id=231426
+static bool LookupAltName(const String& name, String& altName)
+{
+ struct FontCodepage {
+ WCHAR* name;
+ int codePage;
+ };
+
+ struct NamePair {
+ WCHAR* name;
+ FontCodepage altNameCodepage;
+ };
+
+ const int japaneseCodepage = 932;
+ const int simplifiedChineseCodepage = 936;
+ const int koreanCodepage = 949;
+ const int traditionalChineseCodepage = 950;
+
+ // FIXME(jungshik) : This list probably covers 99% of cases.
+ // To cover the remaining 1% and cut down the file size,
+ // consider accessing 'NAME' table of a truetype font
+ // using |GetFontData| and caching the mapping.
+ // In the table below, the ASCII keys are all lower-cased for
+ // case-insensitive matching.
+ static const NamePair namePairs[] = {
+ // MS Pゴシック, MS PGothic
+ {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", {L"MS PGothic", japaneseCodepage}},
+ {L"ms pgothic", {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", japaneseCodepage}},
+ // MS P明朝, MS PMincho
+ {L"\xFF2D\xFF33 \xFF30\x660E\x671D", {L"MS PMincho", japaneseCodepage}},
+ {L"ms pmincho", {L"\xFF2D\xFF33 \xFF30\x660E\x671D", japaneseCodepage}},
+ // MSゴシック, MS Gothic
+ {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", {L"MS Gothic", japaneseCodepage}},
+ {L"ms gothic", {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", japaneseCodepage}},
+ // MS 明朝, MS Mincho
+ {L"\xFF2D\xFF33 \x660E\x671D", {L"MS Mincho", japaneseCodepage}},
+ {L"ms mincho", {L"\xFF2D\xFF33 \x660E\x671D", japaneseCodepage}},
+ // メイリオ, Meiryo
+ {L"\x30E1\x30A4\x30EA\x30AA", {L"Meiryo", japaneseCodepage}},
+ {L"meiryo", {L"\x30E1\x30A4\x30EA\x30AA", japaneseCodepage}},
+ // 바탕, Batang
+ {L"\xBC14\xD0D5", {L"Batang", koreanCodepage}},
+ {L"batang", {L"\xBC14\xD0D5", koreanCodepage}},
+ // 바탕체, Batangche
+ {L"\xBC14\xD0D5\xCCB4", {L"Batangche", koreanCodepage}},
+ {L"batangche", {L"\xBC14\xD0D5\xCCB4", koreanCodepage}},
+ // 굴림, Gulim
+ {L"\xAD74\xB9BC", {L"Gulim", koreanCodepage}},
+ {L"gulim", {L"\xAD74\xB9BC", koreanCodepage}},
+ // 굴림체, Gulimche
+ {L"\xAD74\xB9BC\xCCB4", {L"Gulimche", koreanCodepage}},
+ {L"gulimche", {L"\xAD74\xB9BC\xCCB4", koreanCodepage}},
+ // 돋움, Dotum
+ {L"\xB3CB\xC6C0", {L"Dotum", koreanCodepage}},
+ {L"dotum", {L"\xB3CB\xC6C0", koreanCodepage}},
+ // 돋움체, Dotumche
+ {L"\xB3CB\xC6C0\xCCB4", {L"Dotumche", koreanCodepage}},
+ {L"dotumche", {L"\xB3CB\xC6C0\xCCB4", koreanCodepage}},
+ // 궁서, Gungsuh
+ {L"\xAD81\xC11C", {L"Gungsuh", koreanCodepage}},
+ {L"gungsuh", {L"\xAD81\xC11C", koreanCodepage}},
+ // 궁서체, Gungsuhche
+ {L"\xAD81\xC11C\xCCB4", {L"Gungsuhche", koreanCodepage}},
+ {L"gungsuhche", {L"\xAD81\xC11C\xCCB4", koreanCodepage}},
+ // 맑은 고딕, Malgun Gothic
+ {L"\xB9D1\xC740 \xACE0\xB515", {L"Malgun Gothic", koreanCodepage}},
+ {L"malgun gothic", {L"\xB9D1\xC740 \xACE0\xB515", koreanCodepage}},
+ // 宋体, SimSun
+ {L"\x5B8B\x4F53", {L"SimSun", simplifiedChineseCodepage}},
+ {L"simsun", {L"\x5B8B\x4F53", simplifiedChineseCodepage}},
+ // 黑体, SimHei
+ {L"\x9ED1\x4F53", {L"SimHei", simplifiedChineseCodepage}},
+ {L"simhei", {L"\x9ED1\x4F53", simplifiedChineseCodepage}},
+ // 新宋体, NSimSun
+ {L"\x65B0\x5B8B\x4F53", {L"NSimSun", simplifiedChineseCodepage}},
+ {L"nsimsun", {L"\x65B0\x5B8B\x4F53", simplifiedChineseCodepage}},
+ // 微软雅黑, Microsoft Yahei
+ {L"\x5FAE\x8F6F\x96C5\x9ED1", {L"Microsoft Yahei", simplifiedChineseCodepage}},
+ {L"microsoft yahei", {L"\x5FAE\x8F6F\x96C5\x9ED1", simplifiedChineseCodepage}},
+ // 仿宋, FangSong
+ {L"\x4EFF\x5B8B", {L"FangSong", simplifiedChineseCodepage}},
+ {L"fangsong", {L"\x4EFF\x5B8B", simplifiedChineseCodepage}},
+ // 楷体, KaiTi
+ {L"\x6977\x4F53", {L"KaiTi", simplifiedChineseCodepage}},
+ {L"kaiti", {L"\x6977\x4F53", simplifiedChineseCodepage}},
+ // 仿宋_GB2312, FangSong_GB2312
+ {L"\x4EFF\x5B8B_GB2312", {L"FangSong_GB2312", simplifiedChineseCodepage}},
+ {L"fangsong_gb2312", {L"\x4EFF\x5B8B_gb2312", simplifiedChineseCodepage}},
+ // 楷体_GB2312, KaiTi_GB2312
+ {L"\x6977\x4F53", {L"KaiTi_GB2312", simplifiedChineseCodepage}},
+ {L"kaiti_gb2312", {L"\x6977\x4F53_gb2312", simplifiedChineseCodepage}},
+ // 新細明體, PMingLiu
+ {L"\x65B0\x7D30\x660E\x9AD4", {L"PMingLiu", traditionalChineseCodepage}},
+ {L"pmingliu", {L"\x65B0\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
+ // 細明體, MingLiu
+ {L"\x7D30\x660E\x9AD4", {L"MingLiu", traditionalChineseCodepage}},
+ {L"mingliu", {L"\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
+ // 微軟正黑體, Microsoft JhengHei
+ {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", {L"Microsoft JhengHei", traditionalChineseCodepage}},
+ {L"microsoft jhengHei", {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", traditionalChineseCodepage}},
+ // 標楷體, DFKai-SB
+ {L"\x6A19\x6977\x9AD4", {L"DFKai-SB", traditionalChineseCodepage}},
+ {L"dfkai-sb", {L"\x6A19\x6977\x9AD4", traditionalChineseCodepage}},
+ // WenQuanYi Zen Hei
+ {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", {L"WenQuanYi Zen Hei", traditionalChineseCodepage}},
+ {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", traditionalChineseCodepage}},
+ // WenQuanYi Zen Hei
+ {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", {L"WenQuanYi Zen Hei", simplifiedChineseCodepage}},
+ {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", simplifiedChineseCodepage}},
+ // AR PL ShanHeiSun Uni,
+ {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069",
+ {L"AR PL ShanHeiSun Uni", traditionalChineseCodepage}},
+ {L"ar pl shanheisun uni",
+ {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", traditionalChineseCodepage}},
+ // AR PL ShanHeiSun Uni,
+ {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069",
+ {L"AR PL ShanHeiSun Uni", simplifiedChineseCodepage}},
+ {L"ar pl shanheisun uni",
+ {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", simplifiedChineseCodepage}},
+ // AR PL ZenKai Uni
+ // Traditional Chinese and Simplified Chinese names are
+ // identical.
+ {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", traditionalChineseCodepage}},
+ {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", traditionalChineseCodepage}},
+ {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", simplifiedChineseCodepage}},
+ {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", simplifiedChineseCodepage}},
+ };
+
+ typedef HashMap<String, const FontCodepage*> NameMap;
+ static NameMap* fontNameMap = 0;
+
+ if (!fontNameMap) {
+ size_t numElements = sizeof(namePairs) / sizeof(NamePair);
+ fontNameMap = new NameMap;
+ for (size_t i = 0; i < numElements; ++i)
+ fontNameMap->set(String(namePairs[i].name), &(namePairs[i].altNameCodepage));
+ }
+
+ bool isAscii = false;
+ String n;
+ // use |lower| only for ASCII names
+ // For non-ASCII names, we don't want to invoke an expensive
+ // and unnecessary |lower|.
+ if (charactersAreAllASCII(name)) {
+ isAscii = true;
+ n = name.lower();
+ } else
+ n = name;
+
+ NameMap::iterator iter = fontNameMap->find(n);
+ if (iter == fontNameMap->end())
+ return false;
+
+ static int systemCp = ::GetACP();
+ int fontCp = iter->second->codePage;
+
+ if ((isAscii && systemCp == fontCp) || (!isAscii && systemCp != fontCp)) {
+ altName = String(iter->second->name);
+ return true;
+ }
+
+ return false;
+}
+
+static HFONT createFontIndirectAndGetWinName(const String& family, LOGFONT* winfont, String* winName)
+{
+ int len = min(static_cast<int>(family.length()), LF_FACESIZE - 1);
+ memcpy(winfont->lfFaceName, family.characters(), len * sizeof(WORD));
+ winfont->lfFaceName[len] = '\0';
+
+ HFONT hfont = CreateFontIndirect(winfont);
+ if (!hfont)
+ return 0;
+
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont));
+ WCHAR name[LF_FACESIZE];
+ unsigned resultLength = GetTextFace(dc, LF_FACESIZE, name);
+ if (resultLength > 0)
+ resultLength--; // ignore the null terminator
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ *winName = String(name, resultLength);
+ return hfont;
+}
+
+// This maps font family names to their repertoires of supported Unicode
+// characters. Because it's family names rather than font faces we use
+// as keys, there might be edge cases where one face of a font family
+// has a different repertoire from another face of the same family.
+typedef HashMap<const wchar_t*, UnicodeSet*> FontCmapCache;
+
+static bool fontContainsCharacter(const FontPlatformData* fontData,
+ const wchar_t* family, UChar32 character)
+{
+ // FIXME: For non-BMP characters, GetFontUnicodeRanges is of
+ // no use. We have to read directly from the cmap table of a font.
+ // Return true for now.
+ if (character > 0xFFFF)
+ return true;
+
+ // This cache is just leaked on shutdown.
+ static FontCmapCache* fontCmapCache = 0;
+ if (!fontCmapCache)
+ fontCmapCache = new FontCmapCache;
+
+ HashMap<const wchar_t*, UnicodeSet*>::iterator it = fontCmapCache->find(family);
+ if (it != fontCmapCache->end())
+ return it->second->contains(character);
+
+ HFONT hfont = fontData->hfont();
+ HDC hdc = GetDC(0);
+ HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont));
+ int count = GetFontUnicodeRanges(hdc, 0);
+ if (count == 0 && ChromiumBridge::ensureFontLoaded(hfont))
+ count = GetFontUnicodeRanges(hdc, 0);
+ if (count == 0) {
+ ASSERT_NOT_REACHED();
+ SelectObject(hdc, oldFont);
+ ReleaseDC(0, hdc);
+ return true;
+ }
+
+ static Vector<char, 512> glyphsetBuffer;
+ glyphsetBuffer.resize(GetFontUnicodeRanges(hdc, 0));
+ GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(glyphsetBuffer.data());
+ // In addition, refering to the OS/2 table and converting the codepage list
+ // to the coverage map might be faster.
+ count = GetFontUnicodeRanges(hdc, glyphset);
+ ASSERT(count > 0);
+ SelectObject(hdc, oldFont);
+ ReleaseDC(0, hdc);
+
+ // FIXME: consider doing either of the following two:
+ // 1) port back ICU 4.0's faster look-up code for UnicodeSet
+ // 2) port Mozilla's CompressedCharMap or gfxSparseBitset
+ unsigned i = 0;
+ UnicodeSet* cmap = new UnicodeSet;
+ while (i < glyphset->cRanges) {
+ WCHAR start = glyphset->ranges[i].wcLow;
+ cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1);
+ i++;
+ }
+ cmap->freeze();
+ // We don't lowercase |family| because all of them are under our control
+ // and they're already lowercased.
+ fontCmapCache->set(family, cmap);
+ return cmap->contains(character);
+}
+
+// Given the desired base font, this will create a SimpleFontData for a specific
+// font that can be used to render the given range of characters.
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
+{
+ // FIXME: Consider passing fontDescription.dominantScript()
+ // to GetFallbackFamily here.
+ FontDescription fontDescription = font.fontDescription();
+ UChar32 c;
+ UScriptCode script;
+ const wchar_t* family = getFallbackFamily(characters, length,
+ fontDescription.genericFamily(), &c, &script);
+ FontPlatformData* data = 0;
+ if (family)
+ data = getCachedFontPlatformData(font.fontDescription(), AtomicString(family, wcslen(family)), false);
+
+ // Last resort font list : PanUnicode. CJK fonts have a pretty
+ // large repertoire. Eventually, we need to scan all the fonts
+ // on the system to have a Firefox-like coverage.
+ // Make sure that all of them are lowercased.
+ const static wchar_t* const cjkFonts[] = {
+ L"arial unicode ms",
+ L"ms pgothic",
+ L"simsun",
+ L"gulim",
+ L"pmingliu",
+ L"wenquanyi zen hei", // partial CJK Ext. A coverage but more
+ // widely known to Chinese users.
+ L"ar pl shanheisun uni",
+ L"ar pl zenkai uni",
+ L"han nom a", // Complete CJK Ext. A coverage
+ L"code2000", // Complete CJK Ext. A coverage
+ // CJK Ext. B fonts are not listed here because it's of no use
+ // with our current non-BMP character handling because we use
+ // Uniscribe for it and that code path does not go through here.
+ };
+
+ const static wchar_t* const commonFonts[] = {
+ L"tahoma",
+ L"arial unicode ms",
+ L"lucida sans unicode",
+ L"microsoft sans serif",
+ L"palatino linotype",
+ // Four fonts below (and code2000 at the end) are not from MS, but
+ // once installed, cover a very wide range of characters.
+ L"freeserif",
+ L"freesans",
+ L"gentium",
+ L"gentiumalt",
+ L"ms pgothic",
+ L"simsun",
+ L"gulim",
+ L"pmingliu",
+ L"code2000",
+ };
+
+ const wchar_t* const* panUniFonts = 0;
+ int numFonts = 0;
+ if (script == USCRIPT_HAN) {
+ panUniFonts = cjkFonts;
+ numFonts = ARRAYSIZE(cjkFonts);
+ } else {
+ panUniFonts = commonFonts;
+ numFonts = ARRAYSIZE(commonFonts);
+ }
+ // Font returned from GetFallbackFamily may not cover |characters|
+ // because it's based on script to font mapping. This problem is
+ // critical enough for non-Latin scripts (especially Han) to
+ // warrant an additional (real coverage) check with fontCotainsCharacter.
+ int i;
+ for (i = 0; (!data || !fontContainsCharacter(data, family, c)) && i < numFonts; ++i) {
+ family = panUniFonts[i];
+ data = getCachedFontPlatformData(font.fontDescription(), AtomicString(family, wcslen(family)));
+ }
+ if (i < numFonts) // we found the font that covers this character !
+ return getCachedFontData(data);
+
+ return 0;
+
+}
+
+const AtomicString& FontCache::alternateFamilyName(const AtomicString& familyName)
+{
+ // Note that mapping to Courier is removed because
+ // because it's a bitmap font on Windows.
+ // Alias Courier -> Courier New
+ static AtomicString courier("Courier"), courierNew("Courier New");
+ if (equalIgnoringCase(familyName, courier))
+ return courierNew;
+
+ // Alias Times <-> Times New Roman.
+ static AtomicString times("Times"), timesNewRoman("Times New Roman");
+ if (equalIgnoringCase(familyName, times))
+ return timesNewRoman;
+ if (equalIgnoringCase(familyName, timesNewRoman))
+ return times;
+
+ // Alias Helvetica <-> Arial
+ static AtomicString arial("Arial"), helvetica("Helvetica");
+ if (equalIgnoringCase(familyName, helvetica))
+ return arial;
+ if (equalIgnoringCase(familyName, arial))
+ return helvetica;
+
+ // We block bitmap fonts altogether so that we have to
+ // alias MS Sans Serif (bitmap font) -> Microsoft Sans Serif (truetype font)
+ static AtomicString msSans("MS Sans Serif");
+ static AtomicString microsoftSans("Microsoft Sans Serif");
+ if (equalIgnoringCase(familyName, msSans))
+ return microsoftSans;
+
+ // Alias MS Serif (bitmap) -> Times New Roman (truetype font). There's no
+ // 'Microsoft Sans Serif-equivalent' for Serif.
+ static AtomicString msSerif("MS Serif");
+ if (equalIgnoringCase(familyName, msSerif))
+ return timesNewRoman;
+
+ // FIXME: should we map 'system' to something ('Tahoma') ?
+ return emptyAtom;
+}
+
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ return 0;
+}
+
+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
+ // any prefs.
+ static AtomicString timesStr("Times New Roman");
+ static AtomicString courierStr("Courier New");
+ static AtomicString arialStr("Arial");
+
+ AtomicString& fontStr = timesStr;
+ if (generic == FontDescription::SansSerifFamily)
+ fontStr = arialStr;
+ else if (generic == FontDescription::MonospaceFamily)
+ fontStr = courierStr;
+
+ return getCachedFontPlatformData(description, fontStr);
+}
+
+static LONG toGDIFontWeight(FontWeight fontWeight)
+{
+ static LONG gdiFontWeights[] = {
+ FW_THIN, // FontWeight100
+ FW_EXTRALIGHT, // FontWeight200
+ FW_LIGHT, // FontWeight300
+ FW_NORMAL, // FontWeight400
+ FW_MEDIUM, // FontWeight500
+ FW_SEMIBOLD, // FontWeight600
+ FW_BOLD, // FontWeight700
+ FW_EXTRABOLD, // FontWeight800
+ FW_HEAVY // FontWeight900
+ };
+ 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.
+ // 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.
+ winfont->lfHeight = -fontDescription.computedPixelSize();
+ winfont->lfWidth = 0;
+ winfont->lfEscapement = 0;
+ winfont->lfOrientation = 0;
+ winfont->lfUnderline = false;
+ winfont->lfStrikeOut = false;
+ winfont->lfCharSet = DEFAULT_CHARSET;
+ winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
+ winfont->lfQuality = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
+ winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ winfont->lfItalic = fontDescription.italic();
+ winfont->lfWeight = toGDIFontWeight(fontDescription.weight());
+}
+
+struct TraitsInFamilyProcData {
+ TraitsInFamilyProcData(const AtomicString& familyName)
+ : m_familyName(familyName)
+ {
+ }
+
+ const AtomicString& m_familyName;
+ HashSet<unsigned> m_traitsMasks;
+};
+
+static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
+{
+ TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
+
+ unsigned traitsMask = 0;
+ traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
+ traitsMask |= FontVariantNormalMask;
+ LONG weight = logFont->lfWeight;
+ traitsMask |= weight == FW_THIN ? FontWeight100Mask :
+ weight == FW_EXTRALIGHT ? FontWeight200Mask :
+ weight == FW_LIGHT ? FontWeight300Mask :
+ weight == FW_NORMAL ? FontWeight400Mask :
+ weight == FW_MEDIUM ? FontWeight500Mask :
+ weight == FW_SEMIBOLD ? FontWeight600Mask :
+ weight == FW_BOLD ? FontWeight700Mask :
+ weight == FW_EXTRABOLD ? FontWeight800Mask :
+ FontWeight900Mask;
+ procData->m_traitsMasks.add(traitsMask);
+ return 1;
+}
+
+void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
+{
+ HDC hdc = GetDC(0);
+
+ LOGFONT logFont;
+ logFont.lfCharSet = DEFAULT_CHARSET;
+ unsigned familyLength = min(familyName.length(), static_cast<unsigned>(LF_FACESIZE - 1));
+ memcpy(logFont.lfFaceName, familyName.characters(), familyLength * sizeof(UChar));
+ logFont.lfFaceName[familyLength] = 0;
+ logFont.lfPitchAndFamily = 0;
+
+ TraitsInFamilyProcData procData(familyName);
+ EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0);
+ copyToVector(procData.m_traitsMasks, traitsMasks);
+
+ ReleaseDC(0, hdc);
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+ LOGFONT winfont = {0};
+ FillLogFont(fontDescription, &winfont);
+
+ // Windows will always give us a valid pointer here, even if the face name
+ // is non-existent. We have to double-check and see if the family name was
+ // really used.
+ String winName;
+ HFONT hfont = createFontIndirectAndGetWinName(family, &winfont, &winName);
+ if (!hfont)
+ return 0;
+
+ // FIXME: Do we need to use predefined fonts "guaranteed" to exist
+ // when we're running in layout-test mode?
+ if (!equalIgnoringCase(family, winName)) {
+ // For CJK fonts with both English and native names,
+ // GetTextFace returns a native name under the font's "locale"
+ // and an English name under other locales regardless of
+ // lfFaceName field of LOGFONT. As a result, we need to check
+ // if a font has an alternate name. If there is, we need to
+ // compare it with what's requested in the first place.
+ String altName;
+ if (!LookupAltName(family, altName) ||
+ !equalIgnoringCase(altName, winName)) {
+ DeleteObject(hfont);
+ return 0;
+ }
+ }
+
+ return new FontPlatformData(hfont,
+ fontDescription.computedPixelSize());
+}
+
+}
diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
new file mode 100644
index 0000000..f187c55
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2006, 2007, 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 "config.h"
+#include "FontCache.h"
+
+#include <fontconfig/fontconfig.h>
+
+#include "AtomicString.h"
+#include "CString.h"
+#include "Font.h"
+#include "FontDescription.h"
+#include "FontPlatformData.h"
+#include "Logging.h"
+#include "NotImplemented.h"
+#include "SimpleFontData.h"
+
+#include "SkPaint.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
+
+namespace WebCore {
+
+void FontCache::platformInit()
+{
+}
+
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font,
+ const UChar* characters,
+ int length)
+{
+ FcCharSet* cset = FcCharSetCreate();
+ for (int i = 0; i < length; ++i)
+ FcCharSetAddChar(cset, characters[i]);
+
+ FcPattern* pattern = FcPatternCreate();
+
+ FcValue fcvalue;
+ fcvalue.type = FcTypeCharSet;
+ fcvalue.u.c = cset;
+ FcPatternAdd(pattern, FC_CHARSET, fcvalue, 0);
+
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcResult result;
+ FcPattern* match = FcFontMatch(0, pattern, &result);
+ FcPatternDestroy(pattern);
+
+ SimpleFontData* ret = 0;
+
+ if (match) {
+ FcChar8* family;
+ if (FcPatternGetString(match, FC_FAMILY, 0, &family) == FcResultMatch) {
+ FontPlatformData* fpd =
+ createFontPlatformData(font.fontDescription(), AtomicString((char*) family));
+ ret = new SimpleFontData(*fpd);
+ }
+ FcPatternDestroy(match);
+ }
+
+ FcCharSetDestroy(cset);
+
+ return ret;
+}
+
+const AtomicString& FontCache::alternateFamilyName(const AtomicString& familyName)
+{
+ notImplemented();
+
+ // This is just to stop GCC emitting a warning about returning a reference
+ // to a temporary variable
+ static AtomicString a;
+ return a;
+}
+
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ return 0;
+}
+
+FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description)
+{
+ static AtomicString arialStr("Arial");
+ return getCachedFontPlatformData(description, arialStr);
+}
+
+void FontCache::getTraitsInFamily(const AtomicString& familyName,
+ Vector<unsigned>& traitsMasks)
+{
+ notImplemented();
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription,
+ const AtomicString& family)
+{
+ const char* name = 0;
+ CString s;
+
+ if (family.length() == 0) {
+ static const struct {
+ FontDescription::GenericFamilyType mType;
+ const char* mName;
+ } fontDescriptions[] = {
+ { FontDescription::SerifFamily, "serif" },
+ { FontDescription::SansSerifFamily, "sans-serif" },
+ { FontDescription::MonospaceFamily, "monospace" },
+ { FontDescription::CursiveFamily, "cursive" },
+ { FontDescription::FantasyFamily, "fantasy" }
+ };
+
+ FontDescription::GenericFamilyType type = fontDescription.genericFamily();
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(fontDescriptions); i++) {
+ if (type == fontDescriptions[i].mType) {
+ name = fontDescriptions[i].mName;
+ break;
+ }
+ }
+ // if we fall out of the loop, it's ok for name to still be 0
+ }
+ else { // convert the name to utf8
+ s = family.string().utf8();
+ name = s.data();
+ }
+
+ int style = SkTypeface::kNormal;
+ if (fontDescription.weight() >= FontWeightBold)
+ style |= SkTypeface::kBold;
+ if (fontDescription.italic())
+ style |= SkTypeface::kItalic;
+
+ SkTypeface* tf = SkTypeface::Create(name, static_cast<SkTypeface::Style>(style));
+ if (!tf)
+ return 0;
+
+ FontPlatformData* result =
+ new FontPlatformData(tf,
+ fontDescription.computedSize(),
+ (style & SkTypeface::kBold) && !tf->isBold(),
+ (style & SkTypeface::kItalic) && !tf->isItalic());
+ tf->unref();
+ 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
new file mode 100644
index 0000000..3cf18a6
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, Inc.
+ * Copyright (c) 2006, 2007, 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 "config.h"
+#include "Font.h"
+
+#include "TransformationMatrix.h"
+#include "ChromiumBridge.h"
+#include "FontFallbackList.h"
+#include "GlyphBuffer.h"
+#include "PlatformContextSkia.h"
+#include "SimpleFontData.h"
+#include "SkiaFontWin.h"
+#include "SkiaUtils.h"
+#include "UniscribeHelperTextRun.h"
+
+#include "skia/ext/platform_canvas_win.h"
+#include "skia/ext/skia_utils_win.h" // FIXME: remove this dependency.
+
+#include <windows.h>
+
+namespace WebCore {
+
+static bool windowsCanHandleTextDrawing(GraphicsContext* context)
+{
+ // Check for non-translation transforms. Sometimes zooms will look better in
+ // Skia, and sometimes better in Windows. The main problem is that zooming
+ // in using Skia will show you the hinted outlines for the smaller size,
+ // which look weird. All else being equal, it's better to use Windows' text
+ // drawing, so we don't check for zooms.
+ const TransformationMatrix& matrix = context->getCTM();
+ if (matrix.b() != 0 || matrix.c() != 0) // Check for skew.
+ return false;
+
+ // Check for stroke effects.
+ if (context->platformContext()->getTextDrawingMode() != cTextFill)
+ return false;
+
+ // Check for shadow effects.
+ if (context->platformContext()->getDrawLooper())
+ return false;
+
+ return true;
+}
+
+// Skia equivalents to Windows text drawing functions. They
+// will get the outlines from Windows and draw then using Skia using the given
+// parameters in the paint arguments. This allows more complex effects and
+// transforms to be drawn than Windows allows.
+//
+// These functions will be significantly slower than Windows GDI, and the text
+// will look different (no ClearType), so use only when necessary.
+//
+// When you call a Skia* text drawing function, various glyph outlines will be
+// cached. As a result, you should call SkiaWinOutlineCache::removePathsForFont
+// when the font is destroyed so that the cache does not outlive the font (since
+// the HFONTs are recycled).
+
+// Analog of the Windows GDI function DrawText, except using the given SkPaint
+// attributes for the text. See above for more.
+//
+// Returns true of the text was drawn successfully. False indicates an error
+// from Windows.
+static bool skiaDrawText(HFONT hfont,
+ SkCanvas* canvas,
+ const SkPoint& point,
+ SkPaint* paint,
+ const WORD* glyphs,
+ const int* advances,
+ int numGlyphs)
+{
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, hfont);
+
+ canvas->save();
+ canvas->translate(point.fX, point.fY);
+
+ for (int i = 0; i < numGlyphs; i++) {
+ const SkPath* path = SkiaWinOutlineCache::lookupOrCreatePathForGlyph(dc, hfont, glyphs[i]);
+ if (!path)
+ return false;
+ canvas->drawPath(*path, *paint);
+ canvas->translate(advances[i], 0);
+ }
+
+ canvas->restore();
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ return true;
+}
+
+static bool paintSkiaText(PlatformContextSkia* platformContext,
+ HFONT hfont,
+ int numGlyphs,
+ const WORD* glyphs,
+ const int* advances,
+ const SkPoint& origin)
+{
+ int textMode = platformContext->getTextDrawingMode();
+
+ // Filling (if necessary). This is the common case.
+ SkPaint paint;
+ platformContext->setupPaintForFilling(&paint);
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ bool didFill = false;
+ if ((textMode & cTextFill) && SkColorGetA(paint.getColor())) {
+ if (!skiaDrawText(hfont, platformContext->canvas(), origin, &paint, &glyphs[0], &advances[0], numGlyphs))
+ return false;
+ didFill = true;
+ }
+
+ // Stroking on top (if necessary).
+ if ((textMode & WebCore::cTextStroke)
+ && platformContext->getStrokeStyle() != NoStroke
+ && platformContext->getStrokeThickness() > 0) {
+
+ paint.reset();
+ platformContext->setupPaintForStroking(&paint, 0, 0);
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ if (didFill) {
+ // If there is a shadow and we filled above, there will already be
+ // a shadow. We don't want to draw it again or it will be too dark
+ // and it will go on top of the fill.
+ //
+ // Note that this isn't strictly correct, since the stroke could be
+ // very thick and the shadow wouldn't account for this. The "right"
+ // thing would be to draw to a new layer and then draw that layer
+ // with a shadow. But this is a lot of extra work for something
+ // that isn't normally an issue.
+ paint.setLooper(0)->safeUnref();
+ }
+
+ if (!skiaDrawText(hfont, platformContext->canvas(), origin, &paint, &glyphs[0], &advances[0], numGlyphs))
+ return false;
+ }
+ return true;
+}
+
+void Font::drawGlyphs(GraphicsContext* graphicsContext,
+ const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer,
+ int from,
+ int numGlyphs,
+ const FloatPoint& point) const
+{
+ PlatformGraphicsContext* context = graphicsContext->platformContext();
+
+ // Max buffer length passed to the underlying windows API.
+ const int kMaxBufferLength = 1024;
+ // Default size for the buffer. It should be enough for most of cases.
+ const int kDefaultBufferLength = 256;
+
+ SkColor color = context->fillColor();
+ unsigned char alpha = SkColorGetA(color);
+ // Skip 100% transparent text; no need to draw anything.
+ if (!alpha && context->getStrokeStyle() == NoStroke)
+ return;
+
+ // Set up our graphics context.
+ HDC hdc = context->canvas()->beginPlatformPaint();
+ HGDIOBJ oldFont = SelectObject(hdc, font->platformData().hfont());
+
+ // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
+ // Enforce non-transparent color.
+ color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
+ SetTextColor(hdc, skia::SkColorToCOLORREF(color));
+ SetBkMode(hdc, TRANSPARENT);
+
+ // Windows needs the characters and the advances in nice contiguous
+ // buffers, which we build here.
+ Vector<WORD, kDefaultBufferLength> glyphs;
+ Vector<int, kDefaultBufferLength> advances;
+
+ // Compute the coordinate. The 'origin' represents the baseline, so we need
+ // to move it up to the top of the bounding square.
+ int x = static_cast<int>(point.x());
+ int lineTop = static_cast<int>(point.y()) - font->ascent();
+
+ bool canUseGDI = windowsCanHandleTextDrawing(graphicsContext);
+
+ // We draw the glyphs in chunks to avoid having to do a heap allocation for
+ // the arrays of characters and advances. Since ExtTextOut is the
+ // lowest-level text output function on Windows, there should be little
+ // penalty for splitting up the text. On the other hand, the buffer cannot
+ // be bigger than 4094 or the function will fail.
+ int glyphIndex = 0;
+ while (glyphIndex < numGlyphs) {
+ // how many chars will be in this chunk?
+ int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
+
+ glyphs.resize(curLen);
+ advances.resize(curLen);
+
+ int curWidth = 0;
+ for (int i = 0; i < curLen; ++i, ++glyphIndex) {
+ glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
+ advances[i] = static_cast<int>(glyphBuffer.advanceAt(from + glyphIndex));
+ curWidth += advances[i];
+ }
+
+ bool success = false;
+ for (int executions = 0; executions < 2; ++executions) {
+ if (canUseGDI)
+ success = !!ExtTextOut(hdc, x, lineTop, ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), curLen, &advances[0]);
+ else {
+ // Skia's text draing origin is the baseline, like WebKit, not
+ // the top, like Windows.
+ SkPoint origin = { x, point.y() };
+ success = paintSkiaText(context, font->platformData().hfont(), numGlyphs, reinterpret_cast<const WORD*>(&glyphs[0]), &advances[0], origin);
+ }
+
+ if (!success && executions == 0) {
+ // Ask the browser to load the font for us and retry.
+ ChromiumBridge::ensureFontLoaded(font->platformData().hfont());
+ continue;
+ }
+ break;
+ }
+
+ ASSERT(success);
+
+ x += curWidth;
+ }
+
+ SelectObject(hdc, oldFont);
+ context->canvas()->endPlatformPaint();
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run,
+ const IntPoint& point,
+ int h,
+ int from,
+ int to) const
+{
+ UniscribeHelperTextRun state(run, *this);
+ float left = static_cast<float>(point.x() + state.characterToX(from));
+ float right = static_cast<float>(point.x() + state.characterToX(to));
+
+ // If the text is RTL, left will actually be after right.
+ if (left < right)
+ return FloatRect(left, static_cast<float>(point.y()),
+ right - left, static_cast<float>(h));
+
+ return FloatRect(right, static_cast<float>(point.y()),
+ left - right, static_cast<float>(h));
+}
+
+void Font::drawComplexText(GraphicsContext* graphicsContext,
+ const TextRun& run,
+ const FloatPoint& point,
+ int from,
+ int to) const
+{
+ PlatformGraphicsContext* context = graphicsContext->platformContext();
+ UniscribeHelperTextRun state(run, *this);
+
+ SkColor color = context->fillColor();
+ unsigned char alpha = SkColorGetA(color);
+ // Skip 100% transparent text; no need to draw anything.
+ if (!alpha)
+ return;
+
+ HDC hdc = context->canvas()->beginPlatformPaint();
+
+ // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
+ // Enforce non-transparent color.
+ color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
+ SetTextColor(hdc, skia::SkColorToCOLORREF(color));
+ SetBkMode(hdc, TRANSPARENT);
+
+ // Uniscribe counts the coordinates from the upper left, while WebKit uses
+ // the baseline, so we have to subtract off the ascent.
+ state.draw(hdc, static_cast<int>(point.x()), static_cast<int>(point.y() - ascent()), from, to);
+ context->canvas()->endPlatformPaint();
+}
+
+float Font::floatWidthForComplexText(const TextRun& run) const
+{
+ UniscribeHelperTextRun state(run, *this);
+ return static_cast<float>(state.width());
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, int x,
+ bool includePartialGlyphs) const
+{
+ // Mac code ignores includePartialGlyphs, and they don't know what it's
+ // supposed to do, so we just ignore it as well.
+ UniscribeHelperTextRun state(run, *this);
+ int charIndex = state.xToCharacter(x);
+
+ // XToCharacter will return -1 if the position is before the first
+ // character (we get called like this sometimes).
+ if (charIndex < 0)
+ charIndex = 0;
+ return charIndex;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
new file mode 100644
index 0000000..8f8df88
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2007 Apple Computer, Inc.
+ * Copyright (c) 2007, 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 "config.h"
+#include "FontCustomPlatformData.h"
+
+#if PLATFORM(WIN_OS)
+#include "Base64.h"
+#include "ChromiumBridge.h"
+#include "OpenTypeUtilities.h"
+#endif
+
+#include "FontPlatformData.h"
+#include "NotImplemented.h"
+#include "SharedBuffer.h"
+
+#if PLATFORM(WIN_OS)
+#include <objbase.h>
+#include <t2embapi.h>
+#pragma comment(lib, "t2embed")
+#endif
+
+namespace WebCore {
+
+FontCustomPlatformData::~FontCustomPlatformData()
+{
+#if PLATFORM(WIN_OS)
+ if (m_fontReference) {
+ if (m_name.isNull()) {
+ ULONG status;
+ TTDeleteEmbeddedFont(m_fontReference, 0, &status);
+ } else
+ RemoveFontMemResourceEx(m_fontReference);
+ }
+#endif
+}
+
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontRenderingMode mode)
+{
+#if PLATFORM(WIN_OS)
+ ASSERT(m_fontReference);
+
+ LOGFONT logFont;
+ if (m_name.isNull())
+ TTGetNewFontName(&m_fontReference, logFont.lfFaceName, LF_FACESIZE, 0, 0);
+ else {
+ // m_name comes from createUniqueFontName, which, in turn, gets
+ // it from base64-encoded uuid (128-bit). So, m_name
+ // can never be longer than LF_FACESIZE (32).
+ if (m_name.length() + 1 >= LF_FACESIZE) {
+ ASSERT_NOT_REACHED();
+ return FontPlatformData();
+ }
+ memcpy(logFont.lfFaceName, m_name.charactersWithNullTermination(),
+ sizeof(logFont.lfFaceName[0]) * (1 + m_name.length()));
+ }
+
+ // FIXME: almost identical to FillLogFont in FontCacheWin.cpp.
+ // Need to refactor.
+ logFont.lfHeight = -size;
+ logFont.lfWidth = 0;
+ logFont.lfEscapement = 0;
+ logFont.lfOrientation = 0;
+ logFont.lfUnderline = false;
+ logFont.lfStrikeOut = false;
+ logFont.lfCharSet = DEFAULT_CHARSET;
+ logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
+ logFont.lfQuality = ChromiumBridge::layoutTestMode() ?
+ NONANTIALIASED_QUALITY :
+ DEFAULT_QUALITY; // Honor user's desktop settings.
+ logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ logFont.lfItalic = italic;
+ logFont.lfWeight = bold ? 700 : 400;
+
+ HFONT hfont = CreateFontIndirect(&logFont);
+ return FontPlatformData(hfont, size);
+#else
+ notImplemented();
+ return FontPlatformData();
+#endif
+}
+
+#if PLATFORM(WIN_OS)
+// FIXME: EOTStream class and static functions in this #if block are
+// duplicated from platform/graphics/win/FontCustomPlatformData.cpp
+// and need to be shared.
+
+// Streams the concatenation of a header and font data.
+class EOTStream {
+public:
+ EOTStream(const Vector<UInt8, 512>& eotHeader, const SharedBuffer* fontData, size_t overlayDst, size_t overlaySrc, size_t overlayLength)
+ : m_eotHeader(eotHeader)
+ , m_fontData(fontData)
+ , m_overlayDst(overlayDst)
+ , m_overlaySrc(overlaySrc)
+ , m_overlayLength(overlayLength)
+ , m_offset(0)
+ , m_inHeader(true)
+ {
+ }
+
+ size_t read(void* buffer, size_t count);
+
+private:
+ const Vector<UInt8, 512>& m_eotHeader;
+ const SharedBuffer* m_fontData;
+ size_t m_overlayDst;
+ size_t m_overlaySrc;
+ size_t m_overlayLength;
+ size_t m_offset;
+ bool m_inHeader;
+};
+
+size_t EOTStream::read(void* buffer, size_t count)
+{
+ size_t bytesToRead = count;
+ if (m_inHeader) {
+ size_t bytesFromHeader = std::min(m_eotHeader.size() - m_offset, count);
+ memcpy(buffer, m_eotHeader.data() + m_offset, bytesFromHeader);
+ m_offset += bytesFromHeader;
+ bytesToRead -= bytesFromHeader;
+ if (m_offset == m_eotHeader.size()) {
+ m_inHeader = false;
+ m_offset = 0;
+ }
+ }
+ if (bytesToRead && !m_inHeader) {
+ size_t bytesFromData = std::min(m_fontData->size() - m_offset, bytesToRead);
+ memcpy(buffer, m_fontData->data() + m_offset, bytesFromData);
+ if (m_offset < m_overlayDst + m_overlayLength && m_offset + bytesFromData >= m_overlayDst) {
+ size_t dstOffset = std::max<int>(m_overlayDst - m_offset, 0);
+ size_t srcOffset = std::max<int>(0, m_offset - m_overlayDst);
+ size_t bytesToCopy = std::min(bytesFromData - dstOffset, m_overlayLength - srcOffset);
+ memcpy(reinterpret_cast<char*>(buffer) + dstOffset, m_fontData->data() + m_overlaySrc + srcOffset, bytesToCopy);
+ }
+ m_offset += bytesFromData;
+ bytesToRead -= bytesFromData;
+ }
+ return count - bytesToRead;
+}
+
+static unsigned long WINAPIV readEmbedProc(void* stream, void* buffer, unsigned long length)
+{
+ return static_cast<EOTStream*>(stream)->read(buffer, length);
+}
+
+// Creates a unique and unpredictable font name, in order to avoid collisions and to
+// not allow access from CSS.
+static String createUniqueFontName()
+{
+ Vector<char> fontUuid(sizeof(GUID));
+ CoCreateGuid(reinterpret_cast<GUID*>(fontUuid.data()));
+
+ Vector<char> fontNameVector;
+ base64Encode(fontUuid, fontNameVector);
+ ASSERT(fontNameVector.size() < LF_FACESIZE);
+ return String(fontNameVector.data(), fontNameVector.size());
+}
+#endif
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
+{
+ ASSERT_ARG(buffer, buffer);
+
+#if PLATFORM(WIN_OS)
+ // Introduce the font to GDI. AddFontMemResourceEx cannot be used, because it will pollute the process's
+ // font namespace (Windows has no API for creating an HFONT from data without exposing the font to the
+ // entire process first). TTLoadEmbeddedFont lets us override the font family name, so using a unique name
+ // we avoid namespace collisions.
+
+ String fontName = createUniqueFontName();
+
+ // 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, 512> eotHeader;
+ size_t overlayDst;
+ size_t overlaySrc;
+ size_t overlayLength;
+
+ if (!getEOTHeader(buffer, eotHeader, overlayDst, overlaySrc, overlayLength))
+ return 0;
+
+ HANDLE fontReference;
+ ULONG privStatus;
+ ULONG status;
+ EOTStream eotStream(eotHeader, buffer, overlayDst, overlaySrc, overlayLength);
+
+ LONG loadEmbeddedFontResult = TTLoadEmbeddedFont(&fontReference, TTLOAD_PRIVATE, &privStatus, LICENSE_PREVIEWPRINT, &status, readEmbedProc, &eotStream, const_cast<LPWSTR>(fontName.charactersWithNullTermination()), 0, 0);
+ if (loadEmbeddedFontResult == E_NONE)
+ fontName = String();
+ else {
+ fontReference = renameAndActivateFont(buffer, fontName);
+ if (!fontReference)
+ return 0;
+ }
+
+ return new FontCustomPlatformData(fontReference, fontName);
+#else
+ notImplemented();;
+ return 0;
+#endif
+}
+
+}
diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.h b/WebCore/platform/graphics/chromium/FontCustomPlatformData.h
new file mode 100644
index 0000000..2f1a597
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontCustomPlatformData.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 Apple Computer, Inc.
+ * Copyright (c) 2007, 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.
+ */
+
+#ifndef FontCustomPlatformData_h
+#define FontCustomPlatformData_h
+
+#include <wtf/Noncopyable.h>
+
+#if PLATFORM(WIN_OS)
+#include "FontRenderingMode.h"
+#include "PlatformString.h"
+#include <windows.h>
+#endif
+
+namespace WebCore {
+
+class FontPlatformData;
+class SharedBuffer;
+
+struct FontCustomPlatformData : Noncopyable {
+#if PLATFORM(WIN_OS)
+ FontCustomPlatformData(HANDLE fontReference, const String& name)
+ : m_fontReference(fontReference)
+ , m_name(name)
+ {}
+#endif
+
+ ~FontCustomPlatformData();
+
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic,
+ FontRenderingMode = NormalRenderingMode);
+
+#if PLATFORM(WIN_OS)
+ HANDLE m_fontReference;
+ String m_name;
+#endif
+};
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
+}
+
+#endif // FontCustomPlatformData_h
diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp
new file mode 100644
index 0000000..7a3e614
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Font.h"
+
+#include "FloatRect.h"
+#include "GlyphBuffer.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "PlatformContextSkia.h"
+#include "SimpleFontData.h"
+
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkTemplates.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
+
+namespace WebCore {
+
+void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer, int from, int numGlyphs,
+ const FloatPoint& point) const {
+ SkCanvas* canvas = gc->platformContext()->canvas();
+ SkPaint paint;
+
+ gc->platformContext()->setupPaintCommon(&paint);
+ font->platformData().setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setColor(gc->fillColor().rgb());
+
+ SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t)); // compile-time assert
+
+ const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from);
+ SkScalar x = SkFloatToScalar(point.x());
+ SkScalar y = SkFloatToScalar(point.y());
+
+ // FIXME: text rendering speed:
+ // Android has code in their WebCore fork to special case when the
+ // GlyphBuffer has no advances other than the defaults. In that case the
+ // text drawing can proceed faster. However, it's unclear when those
+ // patches may be upstreamed to WebKit so we always use the slower path
+ // here.
+ const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
+ SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
+ SkPoint* pos = storage.get();
+
+ for (int i = 0; i < numGlyphs; i++) {
+ pos[i].set(x, y);
+ x += SkFloatToScalar(adv[i].width());
+ y += SkFloatToScalar(adv[i].height());
+ }
+ canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
+}
+
+void Font::drawComplexText(GraphicsContext* context, const TextRun& run,
+ const FloatPoint& point, int from, int to) const
+{
+ notImplemented();
+}
+
+float Font::floatWidthForComplexText(const TextRun& run) const
+{
+ notImplemented();
+ return 0;
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, int x,
+ bool includePartialGlyphs) const
+{
+ notImplemented();
+ return 0;
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run,
+ const IntPoint& point, int h,
+ int from, int to) const
+{
+ notImplemented();
+ return FloatRect();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/FontPlatformData.h b/WebCore/platform/graphics/chromium/FontPlatformData.h
new file mode 100644
index 0000000..c6f1912
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontPlatformData.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FontPlatformData_h
+#define FontPlatformData_h
+
+#if PLATFORM(WIN_OS)
+#include "FontPlatformDataChromiumWin.h"
+#elif defined(__linux__)
+#include "FontPlatformDataLinux.h"
+#endif
+
+#endif // FontPlatformData_h
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
new file mode 100644
index 0000000..767fe76
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, Inc.
+ * Copyright (c) 2006, 2007, 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 "config.h"
+#include "FontPlatformData.h"
+
+#include <windows.h>
+#include <objidl.h>
+#include <mlang.h>
+
+#include "ChromiumBridge.h"
+#include "SkiaFontWin.h"
+
+namespace WebCore {
+
+FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_font(hashTableDeletedFontValue())
+ , m_size(-1)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+FontPlatformData::FontPlatformData()
+ : m_font(0)
+ , m_size(0)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+FontPlatformData::FontPlatformData(HFONT font, float size)
+ : m_font(RefCountedHFONT::create(font))
+ , m_size(size)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+// FIXME: this constructor is needed for SVG fonts but doesn't seem to do much
+FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
+ : m_font(0)
+ , m_size(size)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+FontPlatformData::FontPlatformData(const FontPlatformData& data)
+ : m_font(data.m_font)
+ , m_size(data.m_size)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+FontPlatformData& FontPlatformData::operator=(const FontPlatformData& data)
+{
+ if (this != &data) {
+ m_font = data.m_font;
+ m_size = data.m_size;
+
+ // The following fields will get re-computed if necessary.
+ ScriptFreeCache(&m_scriptCache);
+ m_scriptCache = 0;
+
+ delete m_scriptFontProperties;
+ m_scriptFontProperties = 0;
+ }
+ return *this;
+}
+
+FontPlatformData::~FontPlatformData()
+{
+ ScriptFreeCache(&m_scriptCache);
+ m_scriptCache = 0;
+
+ delete m_scriptFontProperties;
+ m_scriptFontProperties = 0;
+}
+
+FontPlatformData::RefCountedHFONT::~RefCountedHFONT()
+{
+ if (m_hfont != reinterpret_cast<HFONT>(-1)) {
+ SkiaWinOutlineCache::removePathsForFont(m_hfont);
+ DeleteObject(m_hfont);
+ }
+}
+
+FontPlatformData::RefCountedHFONT* FontPlatformData::hashTableDeletedFontValue()
+{
+ static RefPtr<RefCountedHFONT> deletedValue =
+ RefCountedHFONT::create(reinterpret_cast<HFONT>(-1));
+ return deletedValue.get();
+}
+
+SCRIPT_FONTPROPERTIES* FontPlatformData::scriptFontProperties() const
+{
+ if (!m_scriptFontProperties) {
+ m_scriptFontProperties = new SCRIPT_FONTPROPERTIES;
+ memset(m_scriptFontProperties, 0, sizeof(SCRIPT_FONTPROPERTIES));
+ m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES);
+ HRESULT result = ScriptGetFontProperties(0, scriptCache(),
+ m_scriptFontProperties);
+ if (result == E_PENDING) {
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, hfont());
+ HRESULT hr = ScriptGetFontProperties(dc, scriptCache(),
+ m_scriptFontProperties);
+ if (S_OK != hr) {
+ if (ChromiumBridge::ensureFontLoaded(hfont())) {
+ // FIXME: Handle gracefully the error if this call also fails.
+ hr = ScriptGetFontProperties(dc, scriptCache(),
+ m_scriptFontProperties);
+ if (S_OK != hr) {
+ ASSERT_NOT_REACHED();
+ }
+ }
+ }
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ }
+ }
+ return m_scriptFontProperties;
+}
+
+}
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h
new file mode 100644
index 0000000..ce15a93
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, Inc.
+ * Copyright (c) 2006, 2007, 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.
+ */
+
+#ifndef FontPlatformDataWin_h
+#define FontPlatformDataWin_h
+
+#include "config.h"
+
+#include "StringImpl.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+#include <usp10.h>
+
+typedef struct HFONT__ *HFONT;
+
+namespace WebCore {
+
+class FontDescription;
+
+class FontPlatformData {
+public:
+ // Used for deleted values in the font cache's hash tables. The hash table
+ // will create us with this structure, and it will compare other values
+ // to this "Deleted" one. It expects the Deleted one to be differentiable
+ // from the NULL one (created with the empty constructor), so we can't just
+ // set everything to NULL.
+ FontPlatformData(WTF::HashTableDeletedValueType);
+ FontPlatformData();
+ FontPlatformData(HFONT, float size);
+ FontPlatformData(float size, bool bold, bool oblique);
+ FontPlatformData(const FontPlatformData&);
+
+ FontPlatformData& operator=(const FontPlatformData&);
+
+ bool isHashTableDeletedValue() const { return m_font == hashTableDeletedFontValue(); }
+
+ ~FontPlatformData();
+
+ HFONT hfont() const { return m_font ? m_font->hfont() : 0; }
+ float size() const { return m_size; }
+
+ unsigned hash() const
+ {
+ return m_font ? m_font->hash() : NULL;
+ }
+
+ bool operator==(const FontPlatformData& other) const
+ {
+ return m_font == other.m_font && m_size == other.m_size;
+ }
+
+ SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
+ SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
+
+private:
+ // We refcount the internal HFONT so that FontPlatformData can be
+ // efficiently copied. WebKit depends on being able to copy it, and we
+ // don't really want to re-create the HFONT.
+ class RefCountedHFONT : public RefCounted<RefCountedHFONT> {
+ public:
+ static PassRefPtr<RefCountedHFONT> create(HFONT hfont)
+ {
+ return adoptRef(new RefCountedHFONT(hfont));
+ }
+
+ ~RefCountedHFONT();
+
+ HFONT hfont() const { return m_hfont; }
+ unsigned hash() const
+ {
+ return StringImpl::computeHash(reinterpret_cast<const UChar*>(&m_hfont), sizeof(HFONT) / sizeof(UChar));
+ }
+
+ bool operator==(const RefCountedHFONT& other) const
+ {
+ return m_hfont == other.m_hfont;
+ }
+
+ private:
+ // The create() function assumes there is already a refcount of one
+ // so it can do adoptRef.
+ RefCountedHFONT(HFONT hfont) : m_hfont(hfont)
+ {
+ }
+
+ HFONT m_hfont;
+ };
+
+ static RefCountedHFONT* hashTableDeletedFontValue();
+
+ RefPtr<RefCountedHFONT> m_font;
+ float m_size; // Point size of the font in pixels.
+
+ mutable SCRIPT_CACHE m_scriptCache;
+ mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
+};
+
+} // WebCore
+
+#endif // FontPlatformDataWin_h
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
new file mode 100644
index 0000000..86f96ee
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FontPlatformData.h"
+
+#include "StringImpl.h"
+#include "NotImplemented.h"
+
+#include "SkPaint.h"
+#include "SkTypeface.h"
+
+namespace WebCore {
+
+FontPlatformData::FontPlatformData(const FontPlatformData& src)
+ : m_typeface(src.m_typeface)
+ , m_textSize(src.m_textSize)
+ , m_fakeBold(src.m_fakeBold)
+ , m_fakeItalic(src.m_fakeItalic)
+{
+ m_typeface->safeRef();
+}
+
+FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic)
+ : m_typeface(tf)
+ , m_textSize(textSize)
+ , m_fakeBold(fakeBold)
+ , m_fakeItalic(fakeItalic)
+{
+ m_typeface->safeRef();
+}
+
+FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
+ : m_typeface(src.m_typeface)
+ , m_textSize(textSize)
+ , m_fakeBold(src.m_fakeBold)
+ , m_fakeItalic(src.m_fakeItalic)
+{
+ m_typeface->safeRef();
+}
+
+FontPlatformData::~FontPlatformData()
+{
+ m_typeface->safeUnref();
+}
+
+FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
+{
+ SkRefCnt_SafeAssign(m_typeface, src.m_typeface);
+
+ m_textSize = src.m_textSize;
+ m_fakeBold = src.m_fakeBold;
+ m_fakeItalic = src.m_fakeItalic;
+
+ return *this;
+}
+
+void FontPlatformData::setupPaint(SkPaint* paint) const
+{
+ const float ts = m_textSize > 0 ? m_textSize : 12;
+
+ paint->setAntiAlias(false);
+ paint->setSubpixelText(false);
+ paint->setTextSize(SkFloatToScalar(ts));
+ paint->setTypeface(m_typeface);
+ paint->setFakeBoldText(m_fakeBold);
+ paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0);
+ paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
+}
+
+bool FontPlatformData::operator==(const FontPlatformData& a) const
+{
+ // If either of the typeface pointers are invalid (either NULL or the
+ // special deleted value) then we test for pointer equality. Otherwise, we
+ // call SkTypeface::Equal on the valid pointers.
+ bool typefacesEqual;
+ if (m_typeface == hashTableDeletedFontValue()
+ || a.m_typeface == hashTableDeletedFontValue()
+ || !m_typeface
+ || !a.m_typeface)
+ typefacesEqual = m_typeface == a.m_typeface;
+ else
+ typefacesEqual = SkTypeface::Equal(m_typeface, a.m_typeface);
+
+ return typefacesEqual
+ && m_textSize == a.m_textSize
+ && m_fakeBold == a.m_fakeBold
+ && m_fakeItalic == a.m_fakeItalic;
+}
+
+unsigned FontPlatformData::hash() const
+{
+ unsigned h = SkTypeface::UniqueID(m_typeface);
+ h ^= 0x01010101 * ((static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic));
+
+ // This memcpy is to avoid a reinterpret_cast that breaks strict-aliasing
+ // rules. Memcpy is generally optimized enough so that performance doesn't
+ // matter here.
+ uint32_t textSizeBytes;
+ memcpy(&textSizeBytes, &m_textSize, sizeof(uint32_t));
+ h ^= textSizeBytes;
+
+ return h;
+}
+
+bool FontPlatformData::isFixedPitch() const
+{
+ notImplemented();
+ return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
new file mode 100644
index 0000000..ec7d837
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FontPlatformDataLinux_h
+#define FontPlatformDataLinux_h
+
+#include "StringImpl.h"
+#include <wtf/RefPtr.h>
+
+class SkPaint;
+class SkTypeface;
+
+namespace WebCore {
+
+class FontDescription;
+
+// -----------------------------------------------------------------------------
+// FontPlatformData is the handle which WebKit has on a specific face. A face
+// is the tuple of (font, size, ...etc). Here we are just wrapping a Skia
+// SkTypeface pointer and dealing with the reference counting etc.
+// -----------------------------------------------------------------------------
+class FontPlatformData {
+public:
+ // Used for deleted values in the font cache's hash tables. The hash table
+ // will create us with this structure, and it will compare other values
+ // to this "Deleted" one. It expects the Deleted one to be differentiable
+ // from the NULL one (created with the empty constructor), so we can't just
+ // set everything to NULL.
+ FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_typeface(hashTableDeletedFontValue())
+ , m_textSize(0)
+ , m_fakeBold(false)
+ , m_fakeItalic(false)
+ { }
+
+ FontPlatformData()
+ : m_typeface(0)
+ , m_textSize(0)
+ , m_fakeBold(false)
+ , m_fakeItalic(false)
+ { }
+
+ FontPlatformData(float textSize, bool fakeBold, bool fakeItalic)
+ : m_typeface(0)
+ , m_textSize(textSize)
+ , m_fakeBold(fakeBold)
+ , m_fakeItalic(fakeItalic)
+ { }
+
+ FontPlatformData(const FontPlatformData&);
+ FontPlatformData(SkTypeface*, float textSize, bool fakeBold, bool fakeItalic);
+ FontPlatformData(const FontPlatformData& src, float textSize);
+ ~FontPlatformData();
+
+ // -------------------------------------------------------------------------
+ // Return true iff this font is monospaced (i.e. every glyph has an equal x
+ // advance)
+ // -------------------------------------------------------------------------
+ bool isFixedPitch() const;
+
+ // -------------------------------------------------------------------------
+ // Setup a Skia painting context to use this font.
+ // -------------------------------------------------------------------------
+ void setupPaint(SkPaint*) const;
+
+ unsigned hash() const;
+ float size() const { return m_textSize; }
+
+ bool operator==(const FontPlatformData&) const;
+ FontPlatformData& operator=(const FontPlatformData&);
+ bool isHashTableDeletedValue() const { return m_typeface == hashTableDeletedFontValue(); }
+
+private:
+ // FIXME: Could SkAutoUnref be used here?
+ SkTypeface* m_typeface;
+ float m_textSize;
+ bool m_fakeBold;
+ bool m_fakeItalic;
+
+ SkTypeface* hashTableDeletedFontValue() const { return reinterpret_cast<SkTypeface*>(-1); }
+};
+
+} // namespace WebCore
+
+#endif // ifdef FontPlatformData_h
diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
new file mode 100644
index 0000000..ed326c8
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FontUtilsChromiumWin.h"
+
+#include <limits>
+
+#include "PlatformString.h"
+#include "StringHash.h"
+#include "UniscribeHelper.h"
+#include <unicode/locid.h>
+#include <unicode/uchar.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+namespace {
+
+// A simple mapping from UScriptCode to family name. This is a sparse array,
+// which works well since the range of UScriptCode values is small.
+typedef const UChar* ScriptToFontMap[USCRIPT_CODE_LIMIT];
+
+void initializeScriptFontMap(ScriptToFontMap& scriptFontMap)
+{
+ struct FontMap {
+ UScriptCode script;
+ const UChar* family;
+ };
+
+ const static FontMap fontMap[] = {
+ {USCRIPT_LATIN, L"times new roman"},
+ {USCRIPT_GREEK, L"times new roman"},
+ {USCRIPT_CYRILLIC, L"times new roman"},
+ {USCRIPT_SIMPLIFIED_HAN, L"simsun"},
+ {USCRIPT_HIRAGANA, L"ms pgothic"},
+ {USCRIPT_KATAKANA, L"ms pgothic"},
+ {USCRIPT_KATAKANA_OR_HIRAGANA, L"ms pgothic"},
+ {USCRIPT_HANGUL, L"gulim"},
+ {USCRIPT_THAI, L"tahoma"},
+ {USCRIPT_HEBREW, L"david"},
+ {USCRIPT_ARABIC, L"tahoma"},
+ {USCRIPT_DEVANAGARI, L"mangal"},
+ {USCRIPT_BENGALI, L"vrinda"},
+ {USCRIPT_GURMUKHI, L"raavi"},
+ {USCRIPT_GUJARATI, L"shruti"},
+ {USCRIPT_ORIYA, L"kalinga"},
+ {USCRIPT_TAMIL, L"latha"},
+ {USCRIPT_TELUGU, L"gautami"},
+ {USCRIPT_KANNADA, L"tunga"},
+ {USCRIPT_MALAYALAM, L"kartika"},
+ {USCRIPT_LAO, L"dokchampa"},
+ {USCRIPT_TIBETAN, L"microsoft himalaya"},
+ {USCRIPT_GEORGIAN, L"sylfaen"},
+ {USCRIPT_ARMENIAN, L"sylfaen"},
+ {USCRIPT_ETHIOPIC, L"nyala"},
+ {USCRIPT_CANADIAN_ABORIGINAL, L"euphemia"},
+ {USCRIPT_CHEROKEE, L"plantagenet cherokee"},
+ {USCRIPT_YI, L"microsoft yi balti"},
+ {USCRIPT_SINHALA, L"iskoola pota"},
+ {USCRIPT_SYRIAC, L"estrangelo edessa"},
+ {USCRIPT_KHMER, L"daunpenh"},
+ {USCRIPT_THAANA, L"mv boli"},
+ {USCRIPT_MONGOLIAN, L"mongolian balti"},
+ {USCRIPT_MYANMAR, L"padauk"},
+ // For USCRIPT_COMMON, we map blocks to scripts when
+ // that makes sense.
+ };
+
+ for (int i = 0; i < sizeof(fontMap) / sizeof(fontMap[0]); ++i)
+ scriptFontMap[fontMap[i].script] = fontMap[i].family;
+
+ // Initialize the locale-dependent mapping.
+ // Since Chrome synchronizes the ICU default locale with its UI locale,
+ // this ICU locale tells the current UI locale of Chrome.
+ Locale locale = Locale::getDefault();
+ const UChar* localeFamily = 0;
+ if (locale == Locale::getJapanese())
+ localeFamily = scriptFontMap[USCRIPT_HIRAGANA];
+ else if (locale == Locale::getKorean())
+ localeFamily = scriptFontMap[USCRIPT_HANGUL];
+ else {
+ // Use Simplified Chinese font for all other locales including
+ // Traditional Chinese because Simsun (SC font) has a wider
+ // coverage (covering both SC and TC) than PMingLiu (TC font).
+ // Note that |fontMap| does not have a separate entry for
+ // USCRIPT_TRADITIONAL_HAN for that reason.
+ // This also speeds up the TC version of Chrome when rendering SC
+ // pages.
+ localeFamily = scriptFontMap[USCRIPT_SIMPLIFIED_HAN];
+ }
+ if (localeFamily)
+ scriptFontMap[USCRIPT_HAN] = localeFamily;
+}
+
+const int kUndefinedAscent = std::numeric_limits<int>::min();
+
+// Given an HFONT, return the ascent. If GetTextMetrics fails,
+// kUndefinedAscent is returned, instead.
+int getAscent(HFONT hfont)
+{
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, hfont);
+ TEXTMETRIC tm;
+ BOOL gotMetrics = GetTextMetrics(dc, &tm);
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ return gotMetrics ? tm.tmAscent : kUndefinedAscent;
+}
+
+struct FontData {
+ FontData()
+ : hfont(0)
+ , ascent(kUndefinedAscent)
+ , scriptCache(0)
+ {
+ }
+
+ HFONT hfont;
+ int ascent;
+ mutable SCRIPT_CACHE scriptCache;
+};
+
+// Again, using hash_map does not earn us much here. page_cycler_test intl2
+// gave us a 'better' result with map than with hash_map even though they're
+// well-within 1-sigma of each other so that the difference is not significant.
+// On the other hand, some pages in intl2 seem to take longer to load with map
+// in the 1st pass. Need to experiment further.
+typedef HashMap<String, FontData> FontDataCache;
+
+} // namespace
+
+// FIXME: this is font fallback code version 0.1
+// - Cover all the scripts
+// - Get the default font for each script/generic family from the
+// preference instead of hardcoding in the source.
+// (at least, read values from the registry for IE font settings).
+// - Support generic families (from FontDescription)
+// - If the default font for a script is not available,
+// try some more fonts known to support it. Finally, we can
+// use EnumFontFamilies or similar APIs to come up with a list of
+// fonts supporting the script and cache the result.
+// - Consider using UnicodeSet (or UnicodeMap) converted from
+// GLYPHSET (BMP) or directly read from truetype cmap tables to
+// keep track of which character is supported by which font
+// - Update script_font_cache in response to WM_FONTCHANGE
+
+const UChar* getFontFamilyForScript(UScriptCode script,
+ FontDescription::GenericFamilyType generic)
+{
+ static ScriptToFontMap scriptFontMap;
+ static bool initialized = false;
+ if (!initialized) {
+ initializeScriptFontMap(scriptFontMap);
+ initialized = true;
+ }
+ if (script == USCRIPT_INVALID_CODE)
+ return 0;
+ ASSERT(script < USCRIPT_CODE_LIMIT);
+ return scriptFontMap[script];
+}
+
+// FIXME:
+// - Handle 'Inherited', 'Common' and 'Unknown'
+// (see http://www.unicode.org/reports/tr24/#Usage_Model )
+// For 'Inherited' and 'Common', perhaps we need to
+// accept another parameter indicating the previous family
+// and just return it.
+// - All the characters (or characters up to the point a single
+// font can cover) need to be taken into account
+const UChar* getFallbackFamily(const UChar* characters,
+ int length,
+ FontDescription::GenericFamilyType generic,
+ UChar32* charChecked,
+ UScriptCode* scriptChecked)
+{
+ ASSERT(characters && characters[0] && length > 0);
+ UScriptCode script = USCRIPT_COMMON;
+
+ // Sometimes characters common to script (e.g. space) is at
+ // the beginning of a string so that we need to skip them
+ // 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) {
+ U16_NEXT(characters, i, length, ucs4);
+ UErrorCode err = U_ZERO_ERROR;
+ script = uscript_getScript(ucs4, &err);
+ // silently ignore the error
+ }
+
+ // For the full-width ASCII characters (U+FF00 - U+FF5E), use the font for
+ // Han (determined in a locale-dependent way above). Full-width ASCII
+ // characters are rather widely used in Japanese and Chinese documents and
+ // they're fully covered by Chinese, Japanese and Korean fonts.
+ 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;
+ }
+ }
+
+ // Another lame work-around to cover non-BMP characters.
+ const UChar* family = getFontFamilyForScript(script, generic);
+ if (!family) {
+ int plane = ucs4 >> 16;
+ switch (plane) {
+ case 1:
+ family = L"code2001";
+ break;
+ case 2:
+ family = L"simsun-extb";
+ break;
+ default:
+ family = L"lucida sans unicode";
+ }
+ }
+
+ if (charChecked)
+ *charChecked = ucs4;
+ if (scriptChecked)
+ *scriptChecked = script;
+ return family;
+}
+
+// Be aware that this is not thread-safe.
+bool getDerivedFontData(const UChar* family,
+ int style,
+ LOGFONT* logfont,
+ int* ascent,
+ HFONT* hfont,
+ SCRIPT_CACHE** scriptCache)
+{
+ ASSERT(logfont);
+ ASSERT(family);
+ ASSERT(*family);
+
+ // It does not matter that we leak font data when we exit.
+ static FontDataCache fontDataCache;
+
+ // FIXME: This comes up pretty high in the profile so that
+ // we need to measure whether using SHA256 (after coercing all the
+ // fields to char*) is faster than String::format.
+ String fontKey = String::format("%1d:%d:%ls", style, logfont->lfHeight, family);
+ FontDataCache::iterator iter = fontDataCache.find(fontKey);
+ FontData* derived;
+ if (iter == fontDataCache.end()) {
+ ASSERT(wcslen(family) < LF_FACESIZE);
+ wcscpy_s(logfont->lfFaceName, LF_FACESIZE, family);
+ // FIXME: CreateFontIndirect always comes up with
+ // a font even if there's no font matching the name. Need to
+ // check it against what we actually want (as is done in
+ // FontCacheWin.cpp)
+ pair<FontDataCache::iterator, bool> entry = fontDataCache.add(fontKey, FontData());
+ derived = &entry.first->second;
+ derived->hfont = CreateFontIndirect(logfont);
+ // GetAscent may return kUndefinedAscent, but we still want to
+ // cache it so that we won't have to call CreateFontIndirect once
+ // more for HFONT next time.
+ derived->ascent = getAscent(derived->hfont);
+ } else {
+ derived = &iter->second;
+ // Last time, GetAscent failed so that only HFONT was
+ // cached. Try once more assuming that TryPreloadFont
+ // was called by a caller between calls.
+ if (kUndefinedAscent == derived->ascent)
+ derived->ascent = getAscent(derived->hfont);
+ }
+ *hfont = derived->hfont;
+ *ascent = derived->ascent;
+ *scriptCache = &(derived->scriptCache);
+ return *ascent != kUndefinedAscent;
+}
+
+int getStyleFromLogfont(const LOGFONT* logfont)
+{
+ // FIXME: consider defining UNDEFINED or INVALID for style and
+ // returning it when logfont is 0
+ if (!logfont) {
+ ASSERT_NOT_REACHED();
+ return FontStyleNormal;
+ }
+ return (logfont->lfItalic ? FontStyleItalic : FontStyleNormal) |
+ (logfont->lfUnderline ? FontStyleUnderlined : FontStyleNormal) |
+ (logfont->lfWeight >= 700 ? FontStyleBold : FontStyleNormal);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h
new file mode 100644
index 0000000..6a964c4
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// A collection of utilities for font handling.
+
+// FIXME: Move all methods to the files that have their callsites and remove this file.
+// *Utils files are not very WebKit-ty.
+
+#ifndef FontUtilsWin_h
+#define FontUtilsWin_h
+
+#include <usp10.h>
+#include <wchar.h>
+#include <windows.h>
+
+#include "FontDescription.h"
+#include <unicode/uscript.h>
+
+namespace WebCore {
+
+// Return a font family that supports a script and belongs to |generic| font
+// family. It can return NULL and a caller has to implement its own fallback.
+const UChar* getFontFamilyForScript(UScriptCode, FontDescription::GenericFamilyType);
+
+// Return a font family that can render |characters| based on
+// what script characters belong to. When char_checked is non-NULL,
+// it's filled with the character used to determine the script.
+// When script_checked is non-NULL, the script used to determine
+// the family is returned.
+// FIXME: This function needs a total overhaul.
+const UChar* getFallbackFamily(const UChar* characters, int length,
+ FontDescription::GenericFamilyType,
+ UChar32* charChecked,
+ UScriptCode* scriptChecked);
+
+// Derive a new HFONT by replacing lfFaceName of LOGFONT with |family|,
+// calculate the ascent for the derived HFONT, and initialize SCRIPT_CACHE
+// in FontData.
+// |style| is only used for cache key generation. |style| is
+// bit-wise OR of BOLD(1), UNDERLINED(2) and ITALIC(4) and
+// should match what's contained in LOGFONT. It should be calculated
+// by calling GetStyleFromLogFont.
+// Returns false if the font is not accessible, in which case |ascent| field
+// of |fontdata| is set to kUndefinedAscent.
+// Be aware that this is not thread-safe.
+// FIXME: Instead of having three out params, we'd better have one
+// (|*FontData|), but somehow it mysteriously messes up the layout for
+// certain complex script pages (e.g. hi.wikipedia.org) and also crashes
+// at the start-up if recently visited page list includes pages with complex
+// scripts in their title. Moreover, somehow the very first-pass of
+// intl2 page-cycler test is noticeably slower with one out param than
+// the current version although the subsequent 9 passes take about the
+// same time.
+bool getDerivedFontData(const UChar* family, int style, LOGFONT*, int* ascent, HFONT*, SCRIPT_CACHE**);
+
+enum {
+ FontStyleNormal = 0,
+ FontStyleBold = 1,
+ FontStyleItalic = 2,
+ FontStyleUnderlined = 4
+};
+
+// Derive style (bit-wise OR of FONT_STYLE_BOLD, FONT_STYLE_UNDERLINED, and
+// FONT_STYLE_ITALIC) from LOGFONT. Returns 0 if |*logfont| is NULL.
+int getStyleFromLogfont(const LOGFONT*);
+
+} // namespace WebCore
+
+#endif // FontUtilsWin_h
diff --git a/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp b/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
new file mode 100644
index 0000000..4c5cf7b
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
@@ -0,0 +1,248 @@
+/*
+ * 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 "config.h"
+#include <windows.h>
+#include <vector>
+
+#include "ChromiumBridge.h"
+#include "Font.h"
+#include "GlyphPageTreeNode.h"
+#include "SimpleFontData.h"
+#include "UniscribeHelperTextRun.h"
+#include "WindowsVersion.h"
+
+namespace WebCore {
+
+// Fills one page of font data pointers with 0 to indicate that there
+// are no glyphs for the characters.
+static void fillEmptyGlyphs(GlyphPage* page)
+{
+ for (int i = 0; i < GlyphPage::size; ++i)
+ page->setGlyphDataForIndex(i, 0, 0);
+}
+
+// Lazily initializes space glyph
+static Glyph initSpaceGlyph(HDC dc, Glyph* spaceGlyph)
+{
+ if (*spaceGlyph)
+ return *spaceGlyph;
+
+ static wchar_t space = ' ';
+ GetGlyphIndices(dc, &space, 1, spaceGlyph, 0);
+ return *spaceGlyph;
+}
+
+// Fills |length| glyphs starting at |offset| in a |page| in the Basic
+// Multilingual Plane (<= U+FFFF). The input buffer size should be the
+// same as |length|. We can use the standard Windows GDI functions here.
+// Returns true if any glyphs were found.
+static bool fillBMPGlyphs(unsigned offset,
+ unsigned length,
+ UChar* buffer,
+ GlyphPage* page,
+ const SimpleFontData* fontData,
+ bool recurse)
+{
+ HDC dc = GetDC((HWND)0);
+ HGDIOBJ oldFont = SelectObject(dc, fontData->m_font.hfont());
+
+ TEXTMETRIC tm = {0};
+ if (!GetTextMetrics(dc, &tm)) {
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+
+ if (recurse) {
+ if (ChromiumBridge::ensureFontLoaded(fontData->m_font.hfont()))
+ return fillBMPGlyphs(offset, length, buffer, page, fontData, false);
+ else {
+ fillEmptyGlyphs(page);
+ return false;
+ }
+ } else {
+ // FIXME: This should never happen. We want to crash the
+ // process and receive a crash dump. We should revisit this code later.
+ // See http://crbug.com/6401
+ ASSERT_NOT_REACHED();
+ fillEmptyGlyphs(page);
+ return false;
+ }
+ }
+
+ // FIXME: GetGlyphIndices() sets each item of localGlyphBuffer[]
+ // with the one of the values listed below.
+ // * With the GGI_MARK_NONEXISTING_GLYPHS flag
+ // + If the font has a glyph available for the character,
+ // localGlyphBuffer[i] > 0x0.
+ // + If the font does not have glyphs available for the character,
+ // localGlyphBuffer[i] = 0x1F (TrueType Collection?) or
+ // 0xFFFF (OpenType?).
+ // * Without the GGI_MARK_NONEXISTING_GLYPHS flag
+ // + If the font has a glyph available for the character,
+ // localGlyphBuffer[i] > 0x0.
+ // + If the font does not have glyphs available for the character,
+ // localGlyphBuffer[i] = 0x80.
+ // (Windows automatically assigns the glyph for a box character to
+ // prevent ExtTextOut() from returning errors.)
+ // To avoid from hurting the rendering performance, this code just
+ // tells WebKit whether or not the all glyph indices for the given
+ // characters are 0x80 (i.e. a possibly-invalid glyph) and let it
+ // use alternative fonts for the characters.
+ // Although this may cause a problem, it seems to work fine as far as I
+ // have tested. (Obviously, I need more tests.)
+ WORD localGlyphBuffer[GlyphPage::size];
+
+ // FIXME: I find some Chinese characters can not be correctly displayed
+ // when call GetGlyphIndices without flag GGI_MARK_NONEXISTING_GLYPHS,
+ // because the corresponding glyph index is set as 0x20 when current font
+ // does not have glyphs available for the character. According a blog post
+ // http://blogs.msdn.com/michkap/archive/2006/06/28/649791.aspx
+ // I think we should switch to the way about calling GetGlyphIndices with
+ // flag GGI_MARK_NONEXISTING_GLYPHS, it should be OK according the
+ // description of MSDN.
+ // Also according to Jungshik and Hironori's suggestion and modification
+ // we treat turetype and raster Font as different way when windows version
+ // is less than Vista.
+ GetGlyphIndices(dc, buffer, length, localGlyphBuffer, GGI_MARK_NONEXISTING_GLYPHS);
+
+ // Copy the output to the GlyphPage
+ bool haveGlyphs = false;
+ int invalidGlyph = 0xFFFF;
+ if (!isVistaOrNewer() && !(tm.tmPitchAndFamily & TMPF_TRUETYPE))
+ invalidGlyph = 0x1F;
+
+ Glyph spaceGlyph = 0; // Glyph for a space. Lazily filled.
+
+ for (unsigned i = 0; i < length; i++) {
+ UChar c = buffer[i];
+ Glyph glyph = localGlyphBuffer[i];
+ const SimpleFontData* glyphFontData = fontData;
+ // When this character should be a space, we ignore whatever the font
+ // says and use a space. Otherwise, if fonts don't map one of these
+ // space or zero width glyphs, we will get a box.
+ if (Font::treatAsSpace(c))
+ // Hard code the glyph indices for characters that should be
+ // treated like spaces.
+ glyph = initSpaceGlyph(dc, &spaceGlyph);
+ else if (Font::treatAsZeroWidthSpace(c) || c == 0x200B) {
+ // FIXME: change Font::treatAsZeroWidthSpace to use
+ // u_hasBinaryProperty, per jungshik's comment here:
+ // https://bugs.webkit.org/show_bug.cgi?id=20237#c6.
+ // Then the additional OR above won't be necessary.
+ glyph = initSpaceGlyph(dc, &spaceGlyph);
+ glyphFontData = fontData->zeroWidthFontData();
+ } else if (glyph == invalidGlyph) {
+ // WebKit expects both the glyph index and FontData
+ // pointer to be 0 if the glyph is not present
+ glyph = 0;
+ glyphFontData = 0;
+ } else {
+ if (SimpleFontData::isCJKCodePoint(c))
+ glyphFontData = fontData->cjkWidthFontData();
+ haveGlyphs = true;
+ }
+ page->setGlyphDataForCharacter(offset + i, glyph, glyphFontData);
+ }
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ return haveGlyphs;
+}
+
+// For non-BMP characters, each is two words (UTF-16) and the input buffer
+// size is 2 * |length|. Since GDI doesn't know how to handle non-BMP
+// characters, we must use Uniscribe to tell us the glyph indices.
+//
+// We don't want to call this in the case of "regular" characters since some
+// fonts may not have the correct combining rules for accents. See the notes
+// at the bottom of ScriptGetCMap. We can't use ScriptGetCMap, though, since
+// it doesn't seem to support UTF-16, despite what this blog post says:
+// http://blogs.msdn.com/michkap/archive/2006/06/29/650680.aspx
+//
+// So we fire up the full Uniscribe doohicky, give it our string, and it will
+// correctly handle the UTF-16 for us. The hard part is taking this and getting
+// the glyph indices back out that correspond to the correct input characters,
+// since they may be missing.
+//
+// Returns true if any glyphs were found.
+static bool fillNonBMPGlyphs(unsigned offset,
+ unsigned length,
+ UChar* buffer,
+ GlyphPage* page,
+ const SimpleFontData* fontData)
+{
+ bool haveGlyphs = false;
+
+ UniscribeHelperTextRun state(buffer, length * 2, false,
+ fontData->m_font.hfont(),
+ fontData->m_font.scriptCache(),
+ fontData->m_font.scriptFontProperties());
+ state.setInhibitLigate(true);
+ state.init();
+
+ for (unsigned i = 0; i < length; i++) {
+ // Each character in this input buffer is a surrogate pair, which
+ // consists of two UChars. So, the offset for its i-th character is
+ // (i * 2).
+ WORD glyph = state.firstGlyphForCharacter(i * 2);
+ if (glyph) {
+ haveGlyphs = true;
+ page->setGlyphDataForIndex(offset + i, glyph, fontData);
+ } else
+ // Clear both glyph and fontData fields.
+ page->setGlyphDataForIndex(offset + i, 0, 0);
+ }
+ return haveGlyphs;
+}
+
+// We're supposed to return true if there are any glyphs in the range
+// specified by |offset| and |length| in our font,
+// false if there are none.
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* characterBuffer,
+ unsigned bufferLength, const SimpleFontData* fontData)
+{
+ // We have to handle BMP and non-BMP characters differently.
+ // FIXME: Add assertions to make sure that buffer is entirely in BMP
+ // or entirely in non-BMP.
+ if (bufferLength == length)
+ return fillBMPGlyphs(offset, length, characterBuffer, this, fontData, true);
+
+ if (bufferLength == 2 * length) {
+ // A non-BMP input buffer will be twice as long as output glyph buffer
+ // because each character in the non-BMP input buffer will be
+ // represented by a surrogate pair (two UChar's).
+ return fillNonBMPGlyphs(offset, length, characterBuffer, this, fontData);
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp b/WebCore/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp
new file mode 100644
index 0000000..6024d43
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 "config.h"
+#include "GlyphPageTreeNode.h"
+
+#include "Font.h"
+#include "SimpleFontData.h"
+
+#include "SkTemplates.h"
+#include "SkPaint.h"
+#include "SkUtils.h"
+
+namespace WebCore {
+
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+ if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
+ SkDebugf("%s last char is high-surrogate", __FUNCTION__);
+ return false;
+ }
+
+ SkPaint paint;
+ fontData->platformData().setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+
+ SkAutoSTMalloc <GlyphPage::size, uint16_t> glyphStorage(length);
+ uint16_t* glyphs = glyphStorage.get();
+ // textToGlyphs takes a byte count, not a glyph count so we multiply by two.
+ unsigned count = paint.textToGlyphs(buffer, bufferLength * 2, glyphs);
+ if (count != length) {
+ SkDebugf("%s count != length\n", __FUNCTION__);
+ return false;
+ }
+
+ unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero
+ for (unsigned i = 0; i < length; i++) {
+ setGlyphDataForIndex(offset + i, glyphs[i], glyphs[i] ? fontData : NULL);
+ allGlyphs |= glyphs[i];
+ }
+
+ return allGlyphs != 0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
new file mode 100644
index 0000000..a5a6e1f
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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 "config.h"
+#include "Icon.h"
+
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+Icon::Icon(const PlatformIcon& icon)
+ : m_icon(icon)
+{
+}
+
+Icon::~Icon()
+{
+}
+
+PassRefPtr<Icon> Icon::createIconForFile(const String&)
+{
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
+{
+ notImplemented();
+ return 0;
+}
+
+void Icon::paint(GraphicsContext*, const IntRect&)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/IconChromiumMac.cpp b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
new file mode 100644
index 0000000..93e36ba
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Icon.h"
+
+#include "PassRefPtr.h"
+
+// FIXME: These are temporary stubs, we need real implementations which
+// may come in the form of IconChromium.cpp. The Windows Chromium
+// implementation is currently in IconWin.cpp.
+
+namespace WebCore {
+
+PassRefPtr<Icon> Icon::createIconForFile(const String&)
+{
+ return 0;
+}
+
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
+{
+ return 0;
+}
+
+Icon::~Icon()
+{
+}
+
+void Icon::paint(GraphicsContext*, const IntRect&)
+{
+}
+
+}
diff --git a/WebCore/platform/graphics/chromium/IconChromiumWin.cpp b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
new file mode 100644
index 0000000..b419e6f
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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 "config.h"
+#include "Icon.h"
+
+#include <windows.h>
+#include <shellapi.h>
+
+#include "GraphicsContext.h"
+#include "PlatformContextSkia.h"
+#include "PlatformString.h"
+#include "SkiaUtils.h"
+
+namespace WebCore {
+
+Icon::Icon(const PlatformIcon& icon)
+ : m_icon(icon)
+{
+}
+
+Icon::~Icon()
+{
+ if (m_icon)
+ DestroyIcon(m_icon);
+}
+
+PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+{
+ SHFILEINFO sfi;
+ memset(&sfi, 0, sizeof(sfi));
+
+ String tmpFilename = filename;
+ if (!SHGetFileInfo(tmpFilename.charactersWithNullTermination(), 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SHELLICONSIZE | SHGFI_SMALLICON))
+ return 0;
+
+ return adoptRef(new Icon(sfi.hIcon));
+}
+
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
+{
+ // FIXME: support multiple files.
+ // http://code.google.com/p/chromium/issues/detail?id=4092
+ if (!filenames.size())
+ return 0;
+
+ return createIconForFile(filenames[0]);
+}
+
+void Icon::paint(GraphicsContext* context, const IntRect& rect)
+{
+ if (context->paintingDisabled())
+ return;
+
+ HDC hdc = context->platformContext()->canvas()->beginPlatformPaint();
+ DrawIconEx(hdc, rect.x(), rect.y(), m_icon, rect.width(), rect.height(), 0, 0, DI_NORMAL);
+ context->platformContext()->canvas()->endPlatformPaint();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/ImageBufferData.h b/WebCore/platform/graphics/chromium/ImageBufferData.h
new file mode 100644
index 0000000..504b893
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/ImageBufferData.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#ifndef ImageBufferData_h
+#define ImageBufferData_h
+
+#include "PlatformContextSkia.h"
+
+#include "skia/ext/platform_canvas.h"
+
+namespace WebCore {
+
+class ImageBufferData {
+public:
+ ImageBufferData(const IntSize&);
+
+ skia::PlatformCanvas m_canvas;
+ PlatformContextSkia m_platformContext;
+};
+
+} // namespace WebCore
+
+#endif // ImageBufferData_h
diff --git a/WebCore/platform/graphics/chromium/ImageChromiumMac.mm b/WebCore/platform/graphics/chromium/ImageChromiumMac.mm
new file mode 100644
index 0000000..073a409
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/ImageChromiumMac.mm
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+// A wrapper around Uniscribe that provides a reasonable API.
+
+#include "config.h"
+#include "BitmapImage.h"
+
+#include "ChromiumBridge.h"
+#include "Image.h"
+
+namespace WebCore {
+
+PassRefPtr<Image> Image::loadPlatformResource(const char* name)
+{
+ return ChromiumBridge::loadPlatformImageResource(name);
+}
+
+// FIXME: These are temporary stubs, we need real implementations which
+// may come in the form of ImageChromium.cpp. The Windows Chromium
+// implementation is currently in ImageSkia.cpp.
+
+void BitmapImage::initPlatformData()
+{
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h b/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h
new file mode 100644
index 0000000..959147a
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#ifndef MediaPlayerPrivateChromium_h
+#define MediaPlayerPrivateChromium_h
+
+#if ENABLE(VIDEO)
+
+#include "MediaPlayer.h"
+
+namespace WebCore {
+
+class MediaPlayerPrivate : public Noncopyable {
+public:
+ MediaPlayerPrivate(MediaPlayer*);
+ ~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 setRect(const IntRect&);
+
+ void paint(GraphicsContext*, const IntRect&);
+
+ static void getSupportedTypes(HashSet<String>&);
+ static bool isAvailable();
+
+ // Public methods to be called by WebMediaPlayer
+ FrameView* frameView();
+ void networkStateChanged();
+ void readyStateChanged();
+ void timeChanged();
+ void volumeChanged();
+ void repaint();
+
+private:
+ MediaPlayer* m_player;
+ void* m_data;
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // MediaPlayerPrivateChromium_h
diff --git a/WebCore/platform/graphics/chromium/PlatformIcon.h b/WebCore/platform/graphics/chromium/PlatformIcon.h
new file mode 100644
index 0000000..51613b8
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/PlatformIcon.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#ifndef PlatformIcon_h
+#define PlatformIcon_h
+
+typedef struct HICON__* HICON;
+
+namespace WebCore {
+
+typedef HICON PlatformIcon;
+
+} // namespace WebCore
+
+#endif // PlatformIcon_h
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
new file mode 100644
index 0000000..06e997f
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2006, 2007 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
+ * 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 "SimpleFontData.h"
+
+#include "ChromiumBridge.h"
+#include "Font.h"
+#include "FontCache.h"
+#include "FloatRect.h"
+#include "FontDescription.h"
+#include <wtf/MathExtras.h>
+
+#include <unicode/uchar.h>
+#include <unicode/unorm.h>
+#include <objidl.h>
+#include <mlang.h>
+
+namespace WebCore {
+
+static inline float scaleEmToUnits(float x, int unitsPerEm)
+{
+ return unitsPerEm ? x / static_cast<float>(unitsPerEm) : x;
+}
+
+void SimpleFontData::platformInit()
+{
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, m_font.hfont());
+
+ TEXTMETRIC textMetric = {0};
+ if (!GetTextMetrics(dc, &textMetric)) {
+ if (ChromiumBridge::ensureFontLoaded(m_font.hfont())) {
+ // Retry GetTextMetrics.
+ // FIXME: Handle gracefully the error if this call also fails.
+ // See http://crbug.com/6401.
+ if (!GetTextMetrics(dc, &textMetric))
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ m_avgCharWidth = textMetric.tmAveCharWidth;
+ m_maxCharWidth = textMetric.tmMaxCharWidth;
+
+ m_ascent = textMetric.tmAscent;
+ m_descent = textMetric.tmDescent;
+ m_lineGap = textMetric.tmExternalLeading;
+ m_xHeight = m_ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
+
+ OUTLINETEXTMETRIC outlineTextMetric;
+ if (GetOutlineTextMetrics(dc, sizeof(outlineTextMetric), &outlineTextMetric) > 0) {
+ // This is a TrueType font. We might be able to get an accurate xHeight.
+ GLYPHMETRICS glyphMetrics = {0};
+ MAT2 identityMatrix = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
+ DWORD len = GetGlyphOutlineW(dc, 'x', GGO_METRICS, &glyphMetrics, 0, 0, &identityMatrix);
+ if (len != GDI_ERROR && glyphMetrics.gmBlackBoxY > 0)
+ m_xHeight = static_cast<float>(glyphMetrics.gmBlackBoxY);
+ }
+
+ m_lineSpacing = m_ascent + m_descent + m_lineGap;
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+}
+
+void SimpleFontData::platformDestroy()
+{
+ // We don't hash this on Win32, so it's effectively owned by us.
+ delete m_smallCapsFontData;
+ m_smallCapsFontData = 0;
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_smallCapsFontData) {
+ LOGFONT winFont;
+ GetObject(m_font.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.
+ winFont.lfHeight = -lroundf(smallCapsSize);
+ HFONT hfont = CreateFontIndirect(&winFont);
+ m_smallCapsFontData =
+ new SimpleFontData(FontPlatformData(hfont, smallCapsSize));
+ }
+ return m_smallCapsFontData;
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ // This used to be implemented with IMLangFontLink2, but since that code has
+ // been disabled, this would always return false anyway.
+ return false;
+}
+
+void SimpleFontData::determinePitch()
+{
+ // TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, m_font.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())) {
+ // Retry GetTextMetrics.
+ // FIXME: Handle gracefully the error if this call also fails.
+ // See http://crbug.com/6401.
+ if (!GetTextMetrics(dc, &textMetric))
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ m_treatAsFixedPitch = ((textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, m_font.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())) {
+ // FIXME: Handle gracefully the error if this call also fails.
+ // See http://crbug.com/6401.
+ if (!GetCharWidthI(dc, glyph, 1, 0, &width))
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+
+ return static_cast<float>(width);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
new file mode 100644
index 0000000..8200175
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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 "config.h"
+#include "SimpleFontData.h"
+
+#include "Font.h"
+#include "FontCache.h"
+#include "FloatRect.h"
+#include "FontDescription.h"
+#include "Logging.h"
+#include "NotImplemented.h"
+
+#include "SkPaint.h"
+#include "SkTypeface.h"
+#include "SkTime.h"
+
+namespace WebCore {
+
+// Smallcaps versions of fonts are 70% the size of the normal font.
+static const float smallCapsFraction = 0.7f;
+
+void SimpleFontData::platformInit()
+{
+ SkPaint paint;
+ SkPaint::FontMetrics metrics;
+
+ m_font.setupPaint(&paint);
+ paint.getFontMetrics(&metrics);
+
+ // 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;
+ } else {
+ m_ascent = SkScalarRound(-metrics.fAscent);
+ m_descent = SkScalarRound(metrics.fHeight) - m_ascent;
+ }
+
+ if (metrics.fXHeight)
+ m_xHeight = metrics.fXHeight;
+ else {
+ // hack taken from the Windows port
+ m_xHeight = static_cast<float>(m_ascent) * 0.56;
+ }
+
+ m_lineGap = SkScalarRound(metrics.fLeading);
+ m_lineSpacing = m_ascent + m_descent + m_lineGap;
+
+ // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
+ // 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()));
+
+ if (metrics.fAvgCharWidth)
+ m_avgCharWidth = SkScalarRound(metrics.fAvgCharWidth);
+ else {
+ m_avgCharWidth = m_xHeight;
+
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+
+ if (glyphPageZero) {
+ static const UChar32 x_char = 'x';
+ const Glyph xGlyph = glyphPageZero->glyphDataForCharacter(x_char).glyph;
+
+ if (xGlyph)
+ m_avgCharWidth = widthForGlyph(xGlyph);
+ }
+ }
+}
+
+void SimpleFontData::platformDestroy()
+{
+ delete m_smallCapsFontData;
+ m_smallCapsFontData = 0;
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_smallCapsFontData) {
+ const float smallCapsSize = lroundf(fontDescription.computedSize() * smallCapsFraction);
+ m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_font, smallCapsSize));
+ }
+
+ return m_smallCapsFontData;
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ SkPaint paint;
+ static const unsigned maxBufferCount = 64;
+ uint16_t glyphs[maxBufferCount];
+
+ m_font.setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+
+ while (length > 0) {
+ int n = SkMin32(length, SK_ARRAY_COUNT(glyphs));
+
+ // textToGlyphs takes a byte count so we double the character count.
+ int count = paint.textToGlyphs(characters, n * 2, glyphs);
+ for (int i = 0; i < count; i++) {
+ if (0 == glyphs[i])
+ return false; // missing glyph
+ }
+
+ characters += n;
+ length -= n;
+ }
+
+ return true;
+}
+
+void SimpleFontData::determinePitch()
+{
+ m_treatAsFixedPitch = platformData().isFixedPitch();
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ SkASSERT(sizeof(glyph) == 2); // compile-time assert
+
+ SkPaint paint;
+
+ m_font.setupPaint(&paint);
+
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ SkScalar width = paint.measureText(&glyph, 2);
+
+ return SkScalarToFloat(width);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/ThemeHelperChromiumWin.cpp b/WebCore/platform/graphics/chromium/ThemeHelperChromiumWin.cpp
new file mode 100644
index 0000000..798ee32
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/ThemeHelperChromiumWin.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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 "config.h"
+#include "ThemeHelperChromiumWin.h"
+
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+
+namespace WebCore {
+
+ThemeHelperWin::ThemeHelperWin(GraphicsContext* context, const IntRect& rect)
+ : m_orgContext(context)
+ , m_orgMatrix(context->getCTM())
+ , m_orgRect(rect)
+{
+ if (m_orgMatrix.b() != 0 || m_orgMatrix.c() != 0) { // Check for skew.
+ // Complicated effects, make a copy and draw the bitmap there.
+ m_type = COPY;
+ m_rect.setSize(rect.size());
+
+ m_newBuffer.set(ImageBuffer::create(rect.size(), false).release());
+
+ // Theme drawing messes with the transparency.
+ // FIXME: Ideally, we would leave this transparent, but I was
+ // having problems with button drawing, so we fill with white. Buttons
+ // looked good with transparent here and no fixing up of the alpha
+ // later, but text areas didn't. This makes text areas look good but
+ // gives buttons a white halo. Is there a way to fix this? I think
+ // buttons actually have antialised edges which is just not possible
+ // to handle on a transparent background given that it messes with the
+ // alpha channel.
+ FloatRect newContextRect(0, 0, rect.width(), rect.height());
+ GraphicsContext* newContext = m_newBuffer->context();
+ newContext->setFillColor(Color::white);
+ newContext->fillRect(newContextRect);
+
+ return;
+ }
+
+ if (m_orgMatrix.a() != 1.0 || m_orgMatrix.d() != 1.0) { // Check for scale.
+ // Only a scaling is applied.
+ m_type = SCALE;
+
+ // Save the transformed coordinates to draw.
+ m_rect = m_orgMatrix.mapRect(rect);
+
+ m_orgContext->save();
+ m_orgContext->concatCTM(m_orgContext->getCTM().inverse());
+ return;
+ }
+
+ // Nothing interesting.
+ m_rect = rect;
+ m_type = ORIGINAL;
+}
+
+ThemeHelperWin::~ThemeHelperWin()
+{
+ switch (m_type) {
+ case SCALE:
+ m_orgContext->restore();
+ break;
+ case COPY: {
+ // Copy the duplicate bitmap with our control to the original canvas.
+ FloatRect destRect(m_orgRect);
+ m_newBuffer->context()->platformContext()->canvas()->
+ getTopPlatformDevice().fixupAlphaBeforeCompositing();
+ m_orgContext->drawImage(m_newBuffer->image(), destRect);
+ break;
+ }
+ case ORIGINAL:
+ break;
+ }
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/ThemeHelperChromiumWin.h b/WebCore/platform/graphics/chromium/ThemeHelperChromiumWin.h
new file mode 100644
index 0000000..1771fb4
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/ThemeHelperChromiumWin.h
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#ifndef ThemeHelperWin_h
+#define ThemeHelperWin_h
+
+#include "TransformationMatrix.h"
+#include "ImageBuffer.h"
+#include "IntRect.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class GraphicsContext;
+class IntRect;
+
+// Helps drawing theme elements like buttons and scroll bars. This will handle
+// translations and scalings that Windows might not, by either making Windows
+// draw the appropriate sized control, or by rendering it into an off-screen
+// context and transforming it ourselves.
+class ThemeHelperWin {
+ enum Type {
+ // Use the original canvas with no changes. This is the normal mode.
+ ORIGINAL,
+
+ // Use the original canvas but scale the rectangle of the control so
+ // that it will be the correct size, undoing any scale already on the
+ // canvas. This will have the effect of just drawing the control bigger
+ // or smaller and not actually expanding or contracting the pixels in
+ // it. This usually looks better.
+ SCALE,
+
+ // Make a copy of the control and then transform it ourselves after
+ // Windows draws it. This allows us to get complex effects.
+ COPY,
+ };
+
+public:
+ // Prepares drawing a control with the given rect to the given context.
+ ThemeHelperWin(GraphicsContext* context, const IntRect& rect);
+ ~ThemeHelperWin();
+
+ // Returns the context to draw the control into, which may be the original
+ // or the copy, depending on the mode.
+ GraphicsContext* context()
+ {
+ return m_newBuffer.get() ? m_newBuffer->context() : m_orgContext;
+ }
+
+ // Returns the rectangle in which to draw into the canvas() by Windows.
+ const IntRect& rect() { return m_rect; }
+
+private:
+ Type m_type;
+
+ // The original canvas to wrote to. Not owned by this class.
+ GraphicsContext* m_orgContext;
+ TransformationMatrix m_orgMatrix;
+ IntRect m_orgRect;
+
+ // When m_type == COPY, this will be a new surface owned by this class that
+ // represents the copy.
+ OwnPtr<ImageBuffer> m_newBuffer;
+
+ // The control rectangle in the coordinate space of canvas().
+ IntRect m_rect;
+};
+
+} // namespace WebCore
+
+#endif // ThemeHelperWin_h
diff --git a/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
new file mode 100644
index 0000000..caeb959
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
@@ -0,0 +1,902 @@
+/*
+ * Copyright (c) 2006, 2007, 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 "config.h"
+#include "UniscribeHelper.h"
+
+#include <windows.h>
+
+#include "FontUtilsChromiumWin.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+// This function is used to see where word spacing should be applied inside
+// runs. Note that this must match Font::treatAsSpace so we all agree where
+// and how much space this is, so we don't want to do more general Unicode
+// "is this a word break" thing.
+static bool treatAsSpace(UChar c)
+{
+ return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0;
+}
+
+// SCRIPT_FONTPROPERTIES contains glyph indices for default, invalid
+// and blank glyphs. Just because ScriptShape succeeds does not mean
+// that a text run is rendered correctly. Some characters may be rendered
+// with default/invalid/blank glyphs. Therefore, we need to check if the glyph
+// array returned by ScriptShape contains any of those glyphs to make
+// sure that the text run is rendered successfully.
+static bool containsMissingGlyphs(WORD *glyphs,
+ int length,
+ SCRIPT_FONTPROPERTIES* properties)
+{
+ for (int i = 0; i < length; ++i) {
+ if (glyphs[i] == properties->wgDefault
+ || (glyphs[i] == properties->wgInvalid
+ && glyphs[i] != properties->wgBlank))
+ return true;
+ }
+
+ return false;
+}
+
+// HFONT is the 'incarnation' of 'everything' about font, but it's an opaque
+// handle and we can't directly query it to make a new HFONT sharing
+// its characteristics (height, style, etc) except for family name.
+// This function uses GetObject to convert HFONT back to LOGFONT,
+// resets the fields of LOGFONT and calculates style to use later
+// for the creation of a font identical to HFONT other than family name.
+static void setLogFontAndStyle(HFONT hfont, LOGFONT *logfont, int *style)
+{
+ ASSERT(hfont && logfont);
+ if (!hfont || !logfont)
+ return;
+
+ GetObject(hfont, sizeof(LOGFONT), logfont);
+ // We reset these fields to values appropriate for CreateFontIndirect.
+ // while keeping lfHeight, which is the most important value in creating
+ // a new font similar to hfont.
+ logfont->lfWidth = 0;
+ logfont->lfEscapement = 0;
+ logfont->lfOrientation = 0;
+ logfont->lfCharSet = DEFAULT_CHARSET;
+ logfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
+ logfont->lfQuality = DEFAULT_QUALITY; // Honor user's desktop settings.
+ logfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ if (style)
+ *style = getStyleFromLogfont(logfont);
+}
+
+UniscribeHelper::UniscribeHelper(const UChar* input,
+ int inputLength,
+ bool isRtl,
+ HFONT hfont,
+ SCRIPT_CACHE* scriptCache,
+ SCRIPT_FONTPROPERTIES* fontProperties)
+ : m_input(input)
+ , m_inputLength(inputLength)
+ , m_isRtl(isRtl)
+ , m_hfont(hfont)
+ , m_scriptCache(scriptCache)
+ , m_fontProperties(fontProperties)
+ , m_directionalOverride(false)
+ , m_inhibitLigate(false)
+ , m_letterSpacing(0)
+ , m_spaceWidth(0)
+ , m_wordSpacing(0)
+ , m_ascent(0)
+{
+ m_logfont.lfFaceName[0] = 0;
+}
+
+UniscribeHelper::~UniscribeHelper()
+{
+}
+
+void UniscribeHelper::initWithOptionalLengthProtection(bool lengthProtection)
+{
+ // We cap the input length and just don't do anything. We'll allocate a lot
+ // of things of the size of the number of characters, so the allocated
+ // memory will be several times the input length. Plus shaping such a large
+ // buffer may be a form of denial of service. No legitimate text should be
+ // this long. It also appears that Uniscribe flatly rejects very long
+ // strings, so we don't lose anything by doing this.
+ //
+ // The input length protection may be disabled by the unit tests to cause
+ // an error condition.
+ static const int kMaxInputLength = 65535;
+ if (m_inputLength == 0 || (lengthProtection && m_inputLength > kMaxInputLength))
+ return;
+
+ fillRuns();
+ fillShapes();
+ fillScreenOrder();
+}
+
+int UniscribeHelper::width() const
+{
+ int width = 0;
+ for (int itemIndex = 0; itemIndex < static_cast<int>(m_runs.size()); itemIndex++)
+ width += advanceForItem(itemIndex);
+ return width;
+}
+
+void UniscribeHelper::justify(int additionalSpace)
+{
+ // Count the total number of glyphs we have so we know how big to make the
+ // buffers below.
+ int totalGlyphs = 0;
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ int runIndex = m_screenOrder[run];
+ totalGlyphs += static_cast<int>(m_shapes[runIndex].glyphLength());
+ }
+ if (totalGlyphs == 0)
+ return; // Nothing to do.
+
+ // We make one big buffer in screen order of all the glyphs we are drawing
+ // across runs so that the justification function will adjust evenly across
+ // all glyphs.
+ Vector<SCRIPT_VISATTR, 64> visualAttributes;
+ visualAttributes.resize(totalGlyphs);
+ Vector<int, 64> advances;
+ advances.resize(totalGlyphs);
+ Vector<int, 64> justify;
+ justify.resize(totalGlyphs);
+
+ // Build the packed input.
+ int destIndex = 0;
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ int runIndex = m_screenOrder[run];
+ const Shaping& shaping = m_shapes[runIndex];
+
+ for (int i = 0; i < shaping.glyphLength(); i++, destIndex++) {
+ memcpy(&visualAttributes[destIndex], &shaping.m_visualAttributes[i],
+ sizeof(SCRIPT_VISATTR));
+ advances[destIndex] = shaping.m_advance[i];
+ }
+ }
+
+ // The documentation for Scriptjustify is wrong, the parameter is the space
+ // to add and not the width of the column you want.
+ const int minKashida = 1; // How do we decide what this should be?
+ ScriptJustify(&visualAttributes[0], &advances[0], totalGlyphs,
+ additionalSpace, minKashida, &justify[0]);
+
+ // Now we have to unpack the justification amounts back into the runs so
+ // the glyph indices match.
+ int globalGlyphIndex = 0;
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ int runIndex = m_screenOrder[run];
+ Shaping& shaping = m_shapes[runIndex];
+
+ shaping.m_justify.resize(shaping.glyphLength());
+ for (int i = 0; i < shaping.glyphLength(); i++, globalGlyphIndex++)
+ shaping.m_justify[i] = justify[globalGlyphIndex];
+ }
+}
+
+int UniscribeHelper::characterToX(int offset) const
+{
+ HRESULT hr;
+ ASSERT(offset <= m_inputLength);
+
+ // Our algorithm is to traverse the items in screen order from left to
+ // right, adding in each item's screen width until we find the item with
+ // the requested character in it.
+ int width = 0;
+ for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
+ // Compute the length of this run.
+ int itemIndex = m_screenOrder[screenIndex];
+ const SCRIPT_ITEM& item = m_runs[itemIndex];
+ const Shaping& shaping = m_shapes[itemIndex];
+ int itemLength = shaping.charLength();
+
+ if (offset >= item.iCharPos && offset <= item.iCharPos + itemLength) {
+ // Character offset is in this run.
+ int charLength = offset - item.iCharPos;
+
+ int curX = 0;
+ hr = ScriptCPtoX(charLength, FALSE, itemLength,
+ shaping.glyphLength(),
+ &shaping.m_logs[0], &shaping.m_visualAttributes[0],
+ shaping.effectiveAdvances(), &item.a, &curX);
+ if (FAILED(hr))
+ return 0;
+
+ width += curX + shaping.m_prePadding;
+ ASSERT(width >= 0);
+ return width;
+ }
+
+ // Move to the next item.
+ width += advanceForItem(itemIndex);
+ }
+ ASSERT(width >= 0);
+ return width;
+}
+
+int UniscribeHelper::xToCharacter(int x) const
+{
+ // We iterate in screen order until we find the item with the given pixel
+ // position in it. When we find that guy, we ask Uniscribe for the
+ // character index.
+ HRESULT hr;
+ for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
+ int itemIndex = m_screenOrder[screenIndex];
+ int itemAdvance = advanceForItem(itemIndex);
+
+ // Note that the run may be empty if shaping failed, so we want to skip
+ // over it.
+ const Shaping& shaping = m_shapes[itemIndex];
+ int itemLength = shaping.charLength();
+ if (x <= itemAdvance && itemLength > 0) {
+ // The requested offset is within this item.
+ const SCRIPT_ITEM& item = m_runs[itemIndex];
+
+ // Account for the leading space we've added to this run that
+ // Uniscribe doesn't know about.
+ x -= shaping.m_prePadding;
+
+ int charX = 0;
+ int trailing;
+ hr = ScriptXtoCP(x, itemLength, shaping.glyphLength(),
+ &shaping.m_logs[0], &shaping.m_visualAttributes[0],
+ shaping.effectiveAdvances(), &item.a, &charX,
+ &trailing);
+
+ // The character offset is within the item. We need to add the
+ // item's offset to transform it into the space of the TextRun
+ return charX + item.iCharPos;
+ }
+
+ // The offset is beyond this item, account for its length and move on.
+ x -= itemAdvance;
+ }
+
+ // Error condition, we don't know what to do if we don't have that X
+ // position in any of our items.
+ return 0;
+}
+
+void UniscribeHelper::draw(HDC dc, int x, int y, int from, int to)
+{
+ HGDIOBJ oldFont = 0;
+ int curX = x;
+ bool firstRun = true;
+
+ for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
+ int itemIndex = m_screenOrder[screenIndex];
+ const SCRIPT_ITEM& item = m_runs[itemIndex];
+ const Shaping& shaping = m_shapes[itemIndex];
+
+ // Character offsets within this run. THESE MAY NOT BE IN RANGE and may
+ // be negative, etc. The code below handles this.
+ int fromChar = from - item.iCharPos;
+ int toChar = to - item.iCharPos;
+
+ // See if we need to draw any characters in this item.
+ if (shaping.charLength() == 0 ||
+ fromChar >= shaping.charLength() || toChar <= 0) {
+ // No chars in this item to display.
+ curX += advanceForItem(itemIndex);
+ continue;
+ }
+
+ // Compute the starting glyph within this span. |from| and |to| are
+ // global offsets that may intersect arbitrarily with our local run.
+ int fromGlyph, afterGlyph;
+ if (item.a.fRTL) {
+ // To compute the first glyph when going RTL, we use |to|.
+ if (toChar >= shaping.charLength())
+ // The end of the text is after (to the left) of us.
+ fromGlyph = 0;
+ else {
+ // Since |to| is exclusive, the first character we draw on the
+ // left is actually the one right before (to the right) of
+ // |to|.
+ fromGlyph = shaping.m_logs[toChar - 1];
+ }
+
+ // The last glyph is actually the first character in the range.
+ if (fromChar <= 0) {
+ // The first character to draw is before (to the right) of this
+ // span, so draw all the way to the end.
+ afterGlyph = shaping.glyphLength();
+ } else {
+ // We want to draw everything up until the character to the
+ // right of |from|. To the right is - 1, so we look that up
+ // (remember our character could be more than one glyph, so we
+ // can't look up our glyph and add one).
+ afterGlyph = shaping.m_logs[fromChar - 1];
+ }
+ } else {
+ // Easy case, everybody agrees about directions. We only need to
+ // handle boundary conditions to get a range inclusive at the
+ // beginning, and exclusive at the ending. We have to do some
+ // computation to see the glyph one past the end.
+ fromGlyph = shaping.m_logs[fromChar < 0 ? 0 : fromChar];
+ if (toChar >= shaping.charLength())
+ afterGlyph = shaping.glyphLength();
+ else
+ afterGlyph = shaping.m_logs[toChar];
+ }
+
+ // Account for the characters that were skipped in this run. When
+ // WebKit asks us to draw a subset of the run, it actually tells us
+ // to draw at the X offset of the beginning of the run, since it
+ // doesn't know the internal position of any of our characters.
+ const int* effectiveAdvances = shaping.effectiveAdvances();
+ int innerOffset = 0;
+ for (int i = 0; i < fromGlyph; i++)
+ innerOffset += effectiveAdvances[i];
+
+ // Actually draw the glyphs we found.
+ int glyphCount = afterGlyph - fromGlyph;
+ if (fromGlyph >= 0 && glyphCount > 0) {
+ // Account for the preceeding space we need to add to this run. We
+ // don't need to count for the following space because that will be
+ // counted in advanceForItem below when we move to the next run.
+ innerOffset += shaping.m_prePadding;
+
+ // Pass 0 in when there is no justification.
+ const int* justify = shaping.m_justify.size() == 0 ? 0 : &shaping.m_justify[fromGlyph];
+
+ if (firstRun) {
+ oldFont = SelectObject(dc, shaping.m_hfont);
+ firstRun = false;
+ } else
+ SelectObject(dc, shaping.m_hfont);
+
+ // Fonts with different ascents can be used to render different
+ // runs. 'Across-runs' y-coordinate correction needs to be
+ // adjusted for each font.
+ HRESULT hr = S_FALSE;
+ for (int executions = 0; executions < 2; ++executions) {
+ hr = ScriptTextOut(dc, shaping.m_scriptCache,
+ curX + innerOffset,
+ y - shaping.m_ascentOffset,
+ 0, 0, &item.a, 0, 0,
+ &shaping.m_glyphs[fromGlyph],
+ glyphCount,
+ &shaping.m_advance[fromGlyph],
+ justify,
+ &shaping.m_offsets[fromGlyph]);
+ if (S_OK != hr && 0 == executions) {
+ // If this ScriptTextOut is called from the renderer it
+ // might fail because the sandbox is preventing it from
+ // opening the font files. If we are running in the
+ // renderer, TryToPreloadFont is overridden to ask the
+ // browser to preload the font for us so we can access it.
+ tryToPreloadFont(shaping.m_hfont);
+ continue;
+ }
+ break;
+ }
+
+ ASSERT(S_OK == hr);
+ }
+
+ curX += advanceForItem(itemIndex);
+ }
+
+ if (oldFont)
+ SelectObject(dc, oldFont);
+}
+
+WORD UniscribeHelper::firstGlyphForCharacter(int charOffset) const
+{
+ // Find the run for the given character.
+ for (int i = 0; i < static_cast<int>(m_runs.size()); i++) {
+ int firstChar = m_runs[i].iCharPos;
+ const Shaping& shaping = m_shapes[i];
+ int localOffset = charOffset - firstChar;
+ if (localOffset >= 0 && localOffset < shaping.charLength()) {
+ // The character is in this run, return the first glyph for it
+ // (should generally be the only glyph). It seems Uniscribe gives
+ // glyph 0 for empty, which is what we want to return in the
+ // "missing" case.
+ size_t glyphIndex = shaping.m_logs[localOffset];
+ if (glyphIndex >= shaping.m_glyphs.size()) {
+ // The glyph should be in this run, but the run has too few
+ // actual characters. This can happen when shaping the run
+ // fails, in which case, we should have no data in the logs at
+ // all.
+ ASSERT(shaping.m_glyphs.size() == 0);
+ return 0;
+ }
+ return shaping.m_glyphs[glyphIndex];
+ }
+ }
+
+ return 0;
+}
+
+void UniscribeHelper::fillRuns()
+{
+ HRESULT hr;
+ m_runs.resize(UNISCRIBE_HELPER_STACK_RUNS);
+
+ SCRIPT_STATE inputState;
+ inputState.uBidiLevel = m_isRtl;
+ inputState.fOverrideDirection = m_directionalOverride;
+ inputState.fInhibitSymSwap = false;
+ inputState.fCharShape = false; // Not implemented in Uniscribe
+ inputState.fDigitSubstitute = false; // Do we want this for Arabic?
+ inputState.fInhibitLigate = m_inhibitLigate;
+ inputState.fDisplayZWG = false; // Don't draw control characters.
+ inputState.fArabicNumContext = m_isRtl; // Do we want this for Arabic?
+ inputState.fGcpClusters = false;
+ inputState.fReserved = 0;
+ inputState.fEngineReserved = 0;
+ // The psControl argument to ScriptItemize should be non-0 for RTL text,
+ // per http://msdn.microsoft.com/en-us/library/ms776532.aspx . So use a
+ // SCRIPT_CONTROL that is set to all zeros. Zero as a locale ID means the
+ // neutral locale per http://msdn.microsoft.com/en-us/library/ms776294.aspx
+ static SCRIPT_CONTROL inputControl = {0, // uDefaultLanguage :16;
+ 0, // fContextDigits :1;
+ 0, // fInvertPreBoundDir :1;
+ 0, // fInvertPostBoundDir :1;
+ 0, // fLinkStringBefore :1;
+ 0, // fLinkStringAfter :1;
+ 0, // fNeutralOverride :1;
+ 0, // fNumericOverride :1;
+ 0, // fLegacyBidiClass :1;
+ 0, // fMergeNeutralItems :1;
+ 0};// fReserved :7;
+ // Calling ScriptApplyDigitSubstitution( 0, &inputControl, &inputState)
+ // here would be appropriate if we wanted to set the language ID, and get
+ // local digit substitution behavior. For now, don't do it.
+
+ while (true) {
+ int numberOfItems = 0;
+
+ // Ideally, we would have a way to know the runs before and after this
+ // one, and put them into the control parameter of ScriptItemize. This
+ // would allow us to shape characters properly that cross style
+ // boundaries (WebKit bug 6148).
+ //
+ // We tell ScriptItemize that the output list of items is one smaller
+ // than it actually is. According to Mozilla bug 366643, if there is
+ // not enough room in the array on pre-SP2 systems, ScriptItemize will
+ // write one past the end of the buffer.
+ //
+ // ScriptItemize is very strange. It will often require a much larger
+ // ITEM buffer internally than it will give us as output. For example,
+ // it will say a 16-item buffer is not big enough, and will write
+ // interesting numbers into all those items. But when we give it a 32
+ // item buffer and it succeeds, it only has one item output.
+ //
+ // It seems to be doing at least two passes, the first where it puts a
+ // lot of intermediate data into our items, and the second where it
+ // collates them.
+ hr = ScriptItemize(m_input, m_inputLength,
+ static_cast<int>(m_runs.size()) - 1, &inputControl,
+ &inputState,
+ &m_runs[0], &numberOfItems);
+ if (SUCCEEDED(hr)) {
+ m_runs.resize(numberOfItems);
+ break;
+ }
+ if (hr != E_OUTOFMEMORY) {
+ // Some kind of unexpected error.
+ m_runs.resize(0);
+ break;
+ }
+ // There was not enough items for it to write into, expand.
+ m_runs.resize(m_runs.size() * 2);
+ }
+}
+
+bool UniscribeHelper::shape(const UChar* input,
+ int itemLength,
+ int numGlyphs,
+ SCRIPT_ITEM& run,
+ Shaping& shaping)
+{
+ HFONT hfont = m_hfont;
+ SCRIPT_CACHE* scriptCache = m_scriptCache;
+ SCRIPT_FONTPROPERTIES* fontProperties = m_fontProperties;
+ int ascent = m_ascent;
+ HDC tempDC = 0;
+ HGDIOBJ oldFont = 0;
+ HRESULT hr;
+ bool lastFallbackTried = false;
+ bool result;
+
+ int generatedGlyphs = 0;
+
+ // In case HFONT passed in ctor cannot render this run, we have to scan
+ // other fonts from the beginning of the font list.
+ resetFontIndex();
+
+ // Compute shapes.
+ while (true) {
+ shaping.m_logs.resize(itemLength);
+ shaping.m_glyphs.resize(numGlyphs);
+ shaping.m_visualAttributes.resize(numGlyphs);
+
+#ifdef PURIFY
+ // http://code.google.com/p/chromium/issues/detail?id=5309
+ // Purify isn't able to track the assignments that ScriptShape makes to
+ // shaping.m_glyphs. Consequently, any bytes with value 0xCD that it
+ // writes, will be considered un-initialized data.
+ //
+ // This hack avoid the false-positive UMRs by marking the buffer as
+ // initialized.
+ //
+ // FIXME: A better solution would be to use Purify's API and mark only
+ // the populated range as initialized:
+ //
+ // PurifyMarkAsInitialized(
+ // &shaping.m_glyphs[0],
+ // sizeof(shaping.m_glyphs[0] * generatedGlyphs);
+
+ ZeroMemory(&shaping.m_glyphs[0],
+ sizeof(shaping.m_glyphs[0]) * shaping.m_glyphs.size());
+#endif
+
+ // Firefox sets SCRIPT_ANALYSIS.SCRIPT_STATE.fDisplayZWG to true
+ // here. Is that what we want? It will display control characters.
+ hr = ScriptShape(tempDC, scriptCache, input, itemLength,
+ numGlyphs, &run.a,
+ &shaping.m_glyphs[0], &shaping.m_logs[0],
+ &shaping.m_visualAttributes[0], &generatedGlyphs);
+ if (hr == E_PENDING) {
+ // Allocate the DC.
+ tempDC = GetDC(0);
+ oldFont = SelectObject(tempDC, hfont);
+ continue;
+ } else if (hr == E_OUTOFMEMORY) {
+ numGlyphs *= 2;
+ continue;
+ } else if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(&shaping.m_glyphs[0], generatedGlyphs, fontProperties)))
+ break;
+
+ // The current font can't render this run. clear DC and try
+ // next font.
+ if (tempDC) {
+ SelectObject(tempDC, oldFont);
+ ReleaseDC(0, tempDC);
+ tempDC = 0;
+ }
+
+ if (nextWinFontData(&hfont, &scriptCache, &fontProperties, &ascent)) {
+ // The primary font does not support this run. Try next font.
+ // In case of web page rendering, they come from fonts specified in
+ // CSS stylesheets.
+ continue;
+ } else if (!lastFallbackTried) {
+ lastFallbackTried = true;
+
+ // Generate a last fallback font based on the script of
+ // a character to draw while inheriting size and styles
+ // from the primary font
+ if (!m_logfont.lfFaceName[0])
+ setLogFontAndStyle(m_hfont, &m_logfont, &m_style);
+
+ // TODO(jungshik): generic type should come from webkit for
+ // UniscribeHelperTextRun (a derived class used in webkit).
+ const UChar *family = getFallbackFamily(input, itemLength,
+ FontDescription::StandardFamily, 0, 0);
+ bool fontOk = getDerivedFontData(family, m_style, &m_logfont,
+ &ascent, &hfont, &scriptCache);
+
+ if (!fontOk) {
+ // If this GetDerivedFontData is called from the renderer it
+ // might fail because the sandbox is preventing it from opening
+ // the font files. If we are running in the renderer,
+ // TryToPreloadFont is overridden to ask the browser to preload
+ // the font for us so we can access it.
+ tryToPreloadFont(hfont);
+
+ // Try again.
+ fontOk = getDerivedFontData(family, m_style, &m_logfont,
+ &ascent, &hfont, &scriptCache);
+ ASSERT(fontOk);
+ }
+
+ // TODO(jungshik) : Currently GetDerivedHFont always returns a
+ // a valid HFONT, but in the future, I may change it to return 0.
+ ASSERT(hfont);
+
+ // We don't need a font_properties for the last resort fallback font
+ // because we don't have anything more to try and are forced to
+ // accept empty glyph boxes. If we tried a series of fonts as
+ // 'last-resort fallback', we'd need it, but currently, we don't.
+ continue;
+ } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
+ run.a.eScript = SCRIPT_UNDEFINED;
+ continue;
+ } else if (FAILED(hr)) {
+ // Error shaping.
+ generatedGlyphs = 0;
+ result = false;
+ goto cleanup;
+ }
+ }
+
+ // Sets Windows font data for this run to those corresponding to
+ // a font supporting this run. we don't need to store font_properties
+ // because it's not used elsewhere.
+ shaping.m_hfont = hfont;
+ shaping.m_scriptCache = scriptCache;
+
+ // The ascent of a font for this run can be different from
+ // that of the primary font so that we need to keep track of
+ // the difference per run and take that into account when calling
+ // ScriptTextOut in |draw|. Otherwise, different runs rendered by
+ // different fonts would not be aligned vertically.
+ shaping.m_ascentOffset = m_ascent ? ascent - m_ascent : 0;
+ result = true;
+
+ cleanup:
+ shaping.m_glyphs.resize(generatedGlyphs);
+ shaping.m_visualAttributes.resize(generatedGlyphs);
+ shaping.m_advance.resize(generatedGlyphs);
+ shaping.m_offsets.resize(generatedGlyphs);
+ if (tempDC) {
+ SelectObject(tempDC, oldFont);
+ ReleaseDC(0, tempDC);
+ }
+ // On failure, our logs don't mean anything, so zero those out.
+ if (!result)
+ shaping.m_logs.clear();
+
+ return result;
+}
+
+void UniscribeHelper::fillShapes()
+{
+ m_shapes.resize(m_runs.size());
+ for (size_t i = 0; i < m_runs.size(); i++) {
+ int startItem = m_runs[i].iCharPos;
+ int itemLength = m_inputLength - startItem;
+ if (i < m_runs.size() - 1)
+ itemLength = m_runs[i + 1].iCharPos - startItem;
+
+ int numGlyphs;
+ if (itemLength < UNISCRIBE_HELPER_STACK_CHARS) {
+ // We'll start our buffer sizes with the current stack space
+ // available in our buffers if the current input fits. As long as
+ // it doesn't expand past that we'll save a lot of time mallocing.
+ numGlyphs = UNISCRIBE_HELPER_STACK_CHARS;
+ } else {
+ // When the input doesn't fit, give up with the stack since it will
+ // almost surely not be enough room (unless the input actually
+ // shrinks, which is unlikely) and just start with the length
+ // recommended by the Uniscribe documentation as a "usually fits"
+ // size.
+ numGlyphs = itemLength * 3 / 2 + 16;
+ }
+
+ // Convert a string to a glyph string trying the primary font, fonts in
+ // the fallback list and then script-specific last resort font.
+ Shaping& shaping = m_shapes[i];
+ if (!shape(&m_input[startItem], itemLength, numGlyphs, m_runs[i], shaping))
+ continue;
+
+ // Compute placements. Note that offsets is documented incorrectly
+ // and is actually an array.
+
+ // DC that we lazily create if Uniscribe commands us to.
+ // (this does not happen often because scriptCache is already
+ // updated when calling ScriptShape).
+ HDC tempDC = 0;
+ HGDIOBJ oldFont = 0;
+ HRESULT hr;
+ while (true) {
+ shaping.m_prePadding = 0;
+ hr = ScriptPlace(tempDC, shaping.m_scriptCache,
+ &shaping.m_glyphs[0],
+ static_cast<int>(shaping.m_glyphs.size()),
+ &shaping.m_visualAttributes[0], &m_runs[i].a,
+ &shaping.m_advance[0], &shaping.m_offsets[0],
+ &shaping.m_abc);
+ if (hr != E_PENDING)
+ break;
+
+ // Allocate the DC and run the loop again.
+ tempDC = GetDC(0);
+ oldFont = SelectObject(tempDC, shaping.m_hfont);
+ }
+
+ if (FAILED(hr)) {
+ // Some error we don't know how to handle. Nuke all of our data
+ // since we can't deal with partially valid data later.
+ m_runs.clear();
+ m_shapes.clear();
+ m_screenOrder.clear();
+ }
+
+ if (tempDC) {
+ SelectObject(tempDC, oldFont);
+ ReleaseDC(0, tempDC);
+ }
+ }
+
+ adjustSpaceAdvances();
+
+ if (m_letterSpacing != 0 || m_wordSpacing != 0)
+ applySpacing();
+}
+
+void UniscribeHelper::fillScreenOrder()
+{
+ m_screenOrder.resize(m_runs.size());
+
+ // We assume that the input has only one text direction in it.
+ // TODO(brettw) are we sure we want to keep this restriction?
+ if (m_isRtl) {
+ for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++)
+ m_screenOrder[static_cast<int>(m_screenOrder.size()) - i - 1] = i;
+ } else {
+ for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++)
+ m_screenOrder[i] = i;
+ }
+}
+
+void UniscribeHelper::adjustSpaceAdvances()
+{
+ if (m_spaceWidth == 0)
+ return;
+
+ int spaceWidthWithoutLetterSpacing = m_spaceWidth - m_letterSpacing;
+
+ // This mostly matches what WebKit's UniscribeController::shapeAndPlaceItem.
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ Shaping& shaping = m_shapes[run];
+
+ for (int i = 0; i < shaping.charLength(); i++) {
+ if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
+ continue;
+
+ int glyphIndex = shaping.m_logs[i];
+ int currentAdvance = shaping.m_advance[glyphIndex];
+ // Don't give zero-width spaces a width.
+ if (!currentAdvance)
+ continue;
+
+ // currentAdvance does not include additional letter-spacing, but
+ // space_width does. Here we find out how off we are from the
+ // correct width for the space not including letter-spacing, then
+ // just subtract that diff.
+ int diff = currentAdvance - spaceWidthWithoutLetterSpacing;
+ // The shaping can consist of a run of text, so only subtract the
+ // difference in the width of the glyph.
+ shaping.m_advance[glyphIndex] -= diff;
+ shaping.m_abc.abcB -= diff;
+ }
+ }
+}
+
+void UniscribeHelper::applySpacing()
+{
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ Shaping& shaping = m_shapes[run];
+ bool isRtl = m_runs[run].a.fRTL;
+
+ if (m_letterSpacing != 0) {
+ // RTL text gets padded to the left of each character. We increment
+ // the run's advance to make this happen. This will be balanced out
+ // by NOT adding additional advance to the last glyph in the run.
+ if (isRtl)
+ shaping.m_prePadding += m_letterSpacing;
+
+ // Go through all the glyphs in this run and increase the "advance"
+ // to account for letter spacing. We adjust letter spacing only on
+ // cluster boundaries.
+ //
+ // This works for most scripts, but may have problems with some
+ // indic scripts. This behavior is better than Firefox or IE for
+ // Hebrew.
+ for (int i = 0; i < shaping.glyphLength(); i++) {
+ if (shaping.m_visualAttributes[i].fClusterStart) {
+ // Ick, we need to assign the extra space so that the glyph
+ // comes first, then is followed by the space. This is
+ // opposite for RTL.
+ if (isRtl) {
+ if (i != shaping.glyphLength() - 1) {
+ // All but the last character just get the spacing
+ // applied to their advance. The last character
+ // doesn't get anything,
+ shaping.m_advance[i] += m_letterSpacing;
+ shaping.m_abc.abcB += m_letterSpacing;
+ }
+ } else {
+ // LTR case is easier, we just add to the advance.
+ shaping.m_advance[i] += m_letterSpacing;
+ shaping.m_abc.abcB += m_letterSpacing;
+ }
+ }
+ }
+ }
+
+ // Go through all the characters to find whitespace and insert the
+ // extra wordspacing amount for the glyphs they correspond to.
+ if (m_wordSpacing != 0) {
+ for (int i = 0; i < shaping.charLength(); i++) {
+ if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
+ continue;
+
+ // The char in question is a word separator...
+ int glyphIndex = shaping.m_logs[i];
+
+ // Spaces will not have a glyph in Uniscribe, it will just add
+ // additional advance to the character to the left of the
+ // space. The space's corresponding glyph will be the character
+ // following it in reading order.
+ if (isRtl) {
+ // In RTL, the glyph to the left of the space is the same
+ // as the first glyph of the following character, so we can
+ // just increment it.
+ shaping.m_advance[glyphIndex] += m_wordSpacing;
+ shaping.m_abc.abcB += m_wordSpacing;
+ } else {
+ // LTR is actually more complex here, we apply it to the
+ // previous character if there is one, otherwise we have to
+ // apply it to the leading space of the run.
+ if (glyphIndex == 0)
+ shaping.m_prePadding += m_wordSpacing;
+ else {
+ shaping.m_advance[glyphIndex - 1] += m_wordSpacing;
+ shaping.m_abc.abcB += m_wordSpacing;
+ }
+ }
+ }
+ } // m_wordSpacing != 0
+
+ // Loop for next run...
+ }
+}
+
+// The advance is the ABC width of the run
+int UniscribeHelper::advanceForItem(int itemIndex) const
+{
+ int accum = 0;
+ const Shaping& shaping = m_shapes[itemIndex];
+
+ if (shaping.m_justify.size() == 0) {
+ // Easy case with no justification, the width is just the ABC width of
+ // the run. (The ABC width is the sum of the advances).
+ return shaping.m_abc.abcA + shaping.m_abc.abcB +
+ shaping.m_abc.abcC + shaping.m_prePadding;
+ }
+
+ // With justification, we use the justified amounts instead. The
+ // justification array contains both the advance and the extra space
+ // added for justification, so is the width we want.
+ int justification = 0;
+ for (size_t i = 0; i < shaping.m_justify.size(); i++)
+ justification += shaping.m_justify[i];
+
+ return shaping.m_prePadding + justification;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/UniscribeHelper.h b/WebCore/platform/graphics/chromium/UniscribeHelper.h
new file mode 100644
index 0000000..d291105
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/UniscribeHelper.h
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2006, 2007, 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.
+ */
+
+// A wrapper around Uniscribe that provides a reasonable API.
+
+#ifndef UniscribeHelper_h
+#define UniscribeHelper_h
+
+#include <windows.h>
+#include <usp10.h>
+#include <map>
+
+#include <unicode/uchar.h>
+#include <wtf/Vector.h>
+
+class UniscribeTest_TooBig_Test; // A gunit test for UniscribeHelper.
+
+namespace WebCore {
+
+#define UNISCRIBE_HELPER_STACK_RUNS 8
+#define UNISCRIBE_HELPER_STACK_CHARS 32
+
+// This object should be safe to create & destroy frequently, as long as the
+// caller preserves the script_cache when possible (this data may be slow to
+// compute).
+//
+// This object is "kind of large" (~1K) because it reserves a lot of space for
+// working with to avoid expensive heap operations. Therefore, not only should
+// you not worry about creating and destroying it, you should try to not keep
+// them around.
+class UniscribeHelper {
+public:
+ // Initializes this Uniscribe run with the text pointed to by |run| with
+ // |length|. The input is NOT null terminated.
+ //
+ // The is_rtl flag should be set if the input script is RTL. It is assumed
+ // that the caller has already divided up the input text (using ICU, for
+ // example) into runs of the same direction of script. This avoids
+ // disagreements between the caller and Uniscribe later (see FillItems).
+ //
+ // A script cache should be provided by the caller that is initialized to
+ // NULL. When the caller is done with the cache (it may be stored between
+ // runs as long as it is used consistently with the same HFONT), it should
+ // call ScriptFreeCache().
+ UniscribeHelper(const UChar* input,
+ int inputLength,
+ bool isRtl,
+ HFONT,
+ SCRIPT_CACHE*,
+ SCRIPT_FONTPROPERTIES*);
+
+ virtual ~UniscribeHelper();
+
+ // Sets Uniscribe's directional override flag. False by default.
+ bool directionalOverride() const
+ {
+ return m_directionalOverride;
+ }
+ void setDirectionalOverride(bool override)
+ {
+ m_directionalOverride = override;
+ }
+
+ // Set's Uniscribe's no-ligate override flag. False by default.
+ bool inhibitLigate() const
+ {
+ return m_inhibitLigate;
+ }
+ void setInhibitLigate(bool inhibit)
+ {
+ m_inhibitLigate = inhibit;
+ }
+
+ // Set letter spacing. We will try to insert this much space between
+ // graphemes (one or more glyphs perceived as a single unit by ordinary
+ // users of a script). Positive values increase letter spacing, negative
+ // values decrease it. 0 by default.
+ int letterSpacing() const
+ {
+ return m_letterSpacing;
+ }
+ void setLetterSpacing(int letterSpacing)
+ {
+ m_letterSpacing = letterSpacing;
+ }
+
+ // Set the width of a standard space character. We use this to normalize
+ // space widths. Windows will make spaces after Hindi characters larger than
+ // other spaces. A space_width of 0 means to use the default space width.
+ //
+ // Must be set before Init() is called.
+ int spaceWidth() const
+ {
+ return m_spaceWidth;
+ }
+ void setSpaceWidth(int spaceWidth)
+ {
+ m_spaceWidth = spaceWidth;
+ }
+
+ // Set word spacing. We will try to insert this much extra space between
+ // each word in the input (beyond whatever whitespace character separates
+ // words). Positive values lead to increased letter spacing, negative values
+ // decrease it. 0 by default.
+ //
+ // Must be set before Init() is called.
+ int wordSpacing() const
+ {
+ return m_wordSpacing;
+ }
+ void setWordSpacing(int wordSpacing)
+ {
+ m_wordSpacing = wordSpacing;
+ }
+
+ void setAscent(int ascent)
+ {
+ m_ascent = ascent;
+ }
+
+ // You must call this after setting any options but before doing any
+ // other calls like asking for widths or drawing.
+ void init()
+ {
+ initWithOptionalLengthProtection(true);
+ }
+
+ // Returns the total width in pixels of the text run.
+ int width() const;
+
+ // Call to justify the text, with the amount of space that should be ADDED
+ // to get the desired width that the column should be justified to.
+ // Normally, spaces are inserted, but for Arabic there will be kashidas
+ // (extra strokes) inserted instead.
+ //
+ // This function MUST be called AFTER Init().
+ void justify(int additionalSpace);
+
+ // Computes the given character offset into a pixel offset of the beginning
+ // of that character.
+ int characterToX(int offset) const;
+
+ // Converts the given pixel X position into a logical character offset into
+ // the run. For positions appearing before the first character, this will
+ // return -1.
+ int xToCharacter(int x) const;
+
+ // Draws the given characters to (x, y) in the given DC. The font will be
+ // handled by this function, but the font color and other attributes should
+ // be pre-set.
+ //
+ // The y position is the upper left corner, NOT the baseline.
+ void draw(HDC, int x, int y, int from, int to);
+
+ // Returns the first glyph assigned to the character at the given offset.
+ // This function is used to retrieve glyph information when Uniscribe is
+ // being used to generate glyphs for non-complex, non-BMP (above U+FFFF)
+ // characters. These characters are not otherwise special and have no
+ // complex shaping rules, so we don't otherwise need Uniscribe, except
+ // Uniscribe is the only way to get glyphs for non-BMP characters.
+ //
+ // Returns 0 if there is no glyph for the given character.
+ WORD firstGlyphForCharacter(int charOffset) const;
+
+protected:
+ // Backend for init. The flag allows the unit test to specify whether we
+ // should fail early for very long strings like normal, or try to pass the
+ // long string to Uniscribe. The latter provides a way to force failure of
+ // shaping.
+ void initWithOptionalLengthProtection(bool lengthProtection);
+
+ // Tries to preload the font when the it is not accessible.
+ // This is the default implementation and it does not do anything.
+ virtual void tryToPreloadFont(HFONT) {}
+
+private:
+ friend class UniscribeTest_TooBig_Test;
+
+ // An array corresponding to each item in runs_ containing information
+ // on each of the glyphs that were generated. Like runs_, this is in
+ // reading order. However, for rtl text, the characters within each
+ // item will be reversed.
+ struct Shaping {
+ Shaping()
+ : m_prePadding(0)
+ , m_hfont(NULL)
+ , m_scriptCache(NULL)
+ , m_ascentOffset(0) {
+ m_abc.abcA = 0;
+ m_abc.abcB = 0;
+ m_abc.abcC = 0;
+ }
+
+ // Returns the number of glyphs (which will be drawn to the screen)
+ // in this run.
+ int glyphLength() const
+ {
+ return static_cast<int>(m_glyphs.size());
+ }
+
+ // Returns the number of characters (that we started with) in this run.
+ int charLength() const
+ {
+ return static_cast<int>(m_logs.size());
+ }
+
+ // Returns the advance array that should be used when measuring glyphs.
+ // The returned pointer will indicate an array with glyph_length()
+ // elements and the advance that should be used for each one. This is
+ // either the real advance, or the justified advances if there is one,
+ // and is the array we want to use for measurement.
+ const int* effectiveAdvances() const
+ {
+ if (m_advance.size() == 0)
+ return 0;
+ if (m_justify.size() == 0)
+ return &m_advance[0];
+ return &m_justify[0];
+ }
+
+ // This is the advance amount of space that we have added to the
+ // beginning of the run. It is like the ABC's |A| advance but one that
+ // we create and must handle internally whenever computing with pixel
+ // offsets.
+ int m_prePadding;
+
+ // Glyph indices in the font used to display this item. These indices
+ // are in screen order.
+ Vector<WORD, UNISCRIBE_HELPER_STACK_CHARS> m_glyphs;
+
+ // For each input character, this tells us the first glyph index it
+ // generated. This is the only array with size of the input chars.
+ //
+ // All offsets are from the beginning of this run. Multiple characters
+ // can generate one glyph, in which case there will be adjacent
+ // duplicates in this list. One character can also generate multiple
+ // glyphs, in which case there will be skipped indices in this list.
+ Vector<WORD, UNISCRIBE_HELPER_STACK_CHARS> m_logs;
+
+ // Flags and such for each glyph.
+ Vector<SCRIPT_VISATTR, UNISCRIBE_HELPER_STACK_CHARS> m_visualAttributes;
+
+ // Horizontal advances for each glyph listed above, this is basically
+ // how wide each glyph is.
+ Vector<int, UNISCRIBE_HELPER_STACK_CHARS> m_advance;
+
+ // This contains glyph offsets, from the nominal position of a glyph.
+ // It is used to adjust the positions of multiple combining characters
+ // around/above/below base characters in a context-sensitive manner so
+ // that they don't bump against each other and the base character.
+ Vector<GOFFSET, UNISCRIBE_HELPER_STACK_CHARS> m_offsets;
+
+ // Filled by a call to Justify, this is empty for nonjustified text.
+ // If nonempty, this contains the array of justify characters for each
+ // character as returned by ScriptJustify.
+ //
+ // This is the same as the advance array, but with extra space added
+ // for some characters. The difference between a glyph's |justify|
+ // width and it's |advance| width is the extra space added.
+ Vector<int, UNISCRIBE_HELPER_STACK_CHARS> m_justify;
+
+ // Sizing information for this run. This treats the entire run as a
+ // character with a preceeding advance, width, and ending advance. The
+ // B width is the sum of the |advance| array, and the A and C widths
+ // are any extra spacing applied to each end.
+ //
+ // It is unclear from the documentation what this actually means. From
+ // experimentation, it seems that the sum of the character advances is
+ // always the sum of the ABC values, and I'm not sure what you're
+ // supposed to do with the ABC values.
+ ABC m_abc;
+
+ // Pointers to windows font data used to render this run.
+ HFONT m_hfont;
+ SCRIPT_CACHE* m_scriptCache;
+
+ // Ascent offset between the ascent of the primary font
+ // and that of the fallback font. The offset needs to be applied,
+ // when drawing a string, to align multiple runs rendered with
+ // different fonts.
+ int m_ascentOffset;
+ };
+
+ // Computes the runs_ array from the text run.
+ void fillRuns();
+
+ // Computes the shapes_ array given an runs_ array already filled in.
+ void fillShapes();
+
+ // Fills in the screen_order_ array (see below).
+ void fillScreenOrder();
+
+ // Called to update the glyph positions based on the current spacing
+ // options that are set.
+ void applySpacing();
+
+ // Normalizes all advances for spaces to the same width. This keeps windows
+ // from making spaces after Hindi characters larger, which is then
+ // inconsistent with our meaure of the width since WebKit doesn't include
+ // spaces in text-runs sent to uniscribe unless white-space:pre.
+ void adjustSpaceAdvances();
+
+ // Returns the total width of a single item.
+ int advanceForItem(int) const;
+
+ // Shapes a run (pointed to by |input|) using |hfont| first.
+ // Tries a series of fonts specified retrieved with NextWinFontData
+ // and finally a font covering characters in |*input|. A string pointed
+ // by |input| comes from ScriptItemize and is supposed to contain
+ // characters belonging to a single script aside from characters common to
+ // all scripts (e.g. space).
+ bool shape(const UChar* input, int itemLength, int numGlyphs, SCRIPT_ITEM& run, Shaping&);
+
+ // Gets Windows font data for the next best font to try in the list
+ // of fonts. When there's no more font available, returns false
+ // without touching any of out params. Need to call ResetFontIndex
+ // to start scanning of the font list from the beginning.
+ virtual bool nextWinFontData(HFONT*, SCRIPT_CACHE**, SCRIPT_FONTPROPERTIES**, int* ascent)
+ {
+ return false;
+ }
+
+ // Resets the font index to the first in the list of fonts to try after the
+ // primaryFont turns out not to work. With fontIndex reset,
+ // NextWinFontData scans fallback fonts from the beginning.
+ virtual void resetFontIndex() {}
+
+ // The input data for this run of Uniscribe. See the constructor.
+ const UChar* m_input;
+ const int m_inputLength;
+ const bool m_isRtl;
+
+ // Windows font data for the primary font. In a sense, m_logfont and m_style
+ // are redundant because m_hfont contains all the information. However,
+ // invoking GetObject, everytime we need the height and the style, is rather
+ // expensive so that we cache them. Would it be better to add getter and
+ // (virtual) setter for the height and the style of the primary font,
+ // instead of m_logfont? Then, a derived class ctor can set m_ascent,
+ // m_height and m_style if they're known. Getters for them would have to
+ // 'infer' their values from m_hfont ONLY when they're not set.
+ HFONT m_hfont;
+ SCRIPT_CACHE* m_scriptCache;
+ SCRIPT_FONTPROPERTIES* m_fontProperties;
+ int m_ascent;
+ LOGFONT m_logfont;
+ int m_style;
+
+ // Options, see the getters/setters above.
+ bool m_directionalOverride;
+ bool m_inhibitLigate;
+ int m_letterSpacing;
+ int m_spaceWidth;
+ int m_wordSpacing;
+
+ // Uniscribe breaks the text into Runs. These are one length of text that is
+ // in one script and one direction. This array is in reading order.
+ Vector<SCRIPT_ITEM, UNISCRIBE_HELPER_STACK_RUNS> m_runs;
+
+ Vector<Shaping, UNISCRIBE_HELPER_STACK_RUNS> m_shapes;
+
+ // This is a mapping between reading order and screen order for the items.
+ // Uniscribe's items array are in reading order. For right-to-left text,
+ // or mixed (although WebKit's |TextRun| should really be only one
+ // direction), this makes it very difficult to compute character offsets
+ // and positions. This list is in screen order from left to right, and
+ // gives the index into the |m_runs| and |m_shapes| arrays of each
+ // subsequent item.
+ Vector<int, UNISCRIBE_HELPER_STACK_RUNS> m_screenOrder;
+};
+
+} // namespace WebCore
+
+#endif // UniscribeHelper_h
diff --git a/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp b/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
new file mode 100644
index 0000000..f801c13
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2006, 2007, 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 "config.h"
+#include "UniscribeHelperTextRun.h"
+
+#include "ChromiumBridge.h"
+#include "Font.h"
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+UniscribeHelperTextRun::UniscribeHelperTextRun(const TextRun& run,
+ const Font& font)
+ : UniscribeHelper(run.characters(), run.length(), run.rtl(),
+ font.primaryFont()->platformData().hfont(),
+ font.primaryFont()->platformData().scriptCache(),
+ font.primaryFont()->platformData().scriptFontProperties())
+ , m_font(&font)
+ , m_fontIndex(0)
+{
+ setDirectionalOverride(run.directionalOverride());
+ setLetterSpacing(font.letterSpacing());
+ setSpaceWidth(font.spaceWidth());
+ setWordSpacing(font.wordSpacing());
+ setAscent(font.primaryFont()->ascent());
+
+ init();
+
+ // Padding is the amount to add to make justification happen. This
+ // should be done after Init() so all the runs are already measured.
+ if (run.padding() > 0)
+ justify(run.padding());
+}
+
+UniscribeHelperTextRun::UniscribeHelperTextRun(
+ const wchar_t* input,
+ int inputLength,
+ bool isRtl,
+ HFONT hfont,
+ SCRIPT_CACHE* scriptCache,
+ SCRIPT_FONTPROPERTIES* fontProperties)
+ : UniscribeHelper(input, inputLength, isRtl, hfont,
+ scriptCache, fontProperties)
+ , m_font(0)
+ , m_fontIndex(-1)
+{
+}
+
+void UniscribeHelperTextRun::tryToPreloadFont(HFONT font)
+{
+ // Ask the browser to get the font metrics for this font.
+ // That will preload the font and it should now be accessible
+ // from the renderer.
+ ChromiumBridge::ensureFontLoaded(font);
+}
+
+bool UniscribeHelperTextRun::nextWinFontData(
+ HFONT* hfont,
+ SCRIPT_CACHE** scriptCache,
+ SCRIPT_FONTPROPERTIES** fontProperties,
+ int* ascent)
+{
+ // This check is necessary because NextWinFontData can be called again
+ // after we already ran out of fonts. fontDataAt behaves in a strange
+ // manner when the difference between param passed and # of fonts stored in
+ // WebKit::Font is larger than one. We can avoid this check by setting
+ // font_index_ to # of elements in hfonts_ when we run out of font. In that
+ // case, we'd have to go through a couple of more checks before returning
+ // false.
+ if (m_fontIndex == -1 || !m_font)
+ return false;
+
+ // If the font data for a fallback font requested is not yet retrieved, add
+ // them to our vectors. Note that '>' rather than '>=' is used to test that
+ // condition. primaryFont is not stored in hfonts_, and friends so that
+ // indices for fontDataAt and our vectors for font data are 1 off from each
+ // other. That is, when fully populated, hfonts_ and friends have one font
+ // fewer than what's contained in font_.
+ if (static_cast<size_t>(++m_fontIndex) > m_hfonts.size()) {
+ const FontData *fontData = m_font->fontDataAt(m_fontIndex);
+ if (!fontData) {
+ // Ran out of fonts.
+ m_fontIndex = -1;
+ return false;
+ }
+
+ // FIXME: this won't work for SegmentedFontData
+ // http://crbug.com/6425
+ const SimpleFontData* simpleFontData =
+ fontData->fontDataForCharacter(' ');
+
+ m_hfonts.append(simpleFontData->platformData().hfont());
+ m_scriptCaches.append(simpleFontData->platformData().scriptCache());
+ m_fontProperties.append(simpleFontData->platformData().scriptFontProperties());
+ m_ascents.append(simpleFontData->ascent());
+ }
+
+ *hfont = m_hfonts[m_fontIndex - 1];
+ *scriptCache = m_scriptCaches[m_fontIndex - 1];
+ *fontProperties = m_fontProperties[m_fontIndex - 1];
+ *ascent = m_ascents[m_fontIndex - 1];
+ return true;
+}
+
+void UniscribeHelperTextRun::resetFontIndex()
+{
+ m_fontIndex = 0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.h b/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.h
new file mode 100644
index 0000000..b5c54a0
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006, 2007, 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.
+ */
+
+#ifndef UniscribeHelperTextRun_h
+#define UniscribeHelperTextRun_h
+
+#include "UniscribeHelper.h"
+
+namespace WebCore {
+
+class Font;
+class TextRun;
+
+// Wrapper around the Uniscribe helper that automatically sets it up with the
+// WebKit types we supply.
+class UniscribeHelperTextRun : public UniscribeHelper {
+public:
+ // Regular constructor used for WebCore text run processing.
+ UniscribeHelperTextRun(const TextRun&, const Font&);
+
+ // Constructor with the same interface as the gfx::UniscribeState. Using
+ // this constructor will not give you font fallback, but it will provide
+ // the ability to load fonts that may not be in the OS cache
+ // ("TryToPreloadFont") if the caller does not have a TextRun/Font.
+ UniscribeHelperTextRun(const wchar_t* input,
+ int inputLength,
+ bool isRtl,
+ HFONT hfont,
+ SCRIPT_CACHE*,
+ SCRIPT_FONTPROPERTIES*);
+
+protected:
+ virtual void tryToPreloadFont(HFONT);
+
+private:
+ // This function retrieves the Windows font data (HFONT, etc) for the next
+ // WebKit font in the list. If the font data corresponding to font_index_
+ // has been obtained before, returns the values stored in our internal
+ // vectors (hfonts_, etc). Otherwise, it gets next SimpleFontData from
+ // WebKit and adds them to in hfonts_ and friends so that font data can be
+ // returned quickly next time they're requested.
+ virtual bool nextWinFontData(HFONT*, SCRIPT_CACHE**, SCRIPT_FONTPROPERTIES**, int* ascent);
+ virtual void resetFontIndex();
+
+ // Reference to WebKit::Font that contains all the information about fonts
+ // we can use to render this input run of text. It is used in
+ // NextWinFontData to retrieve Windows font data for a series of
+ // non-primary fonts.
+ //
+ // This pointer can be NULL for no font fallback handling.
+ const Font* m_font;
+
+ // It's rare that many fonts are listed in stylesheets.
+ // Four would be large enough in most cases.
+ const static size_t kNumberOfFonts = 4;
+
+ // These vectors are used to store Windows font data for non-primary fonts.
+ Vector<HFONT, kNumberOfFonts> m_hfonts;
+ Vector<SCRIPT_CACHE*, kNumberOfFonts> m_scriptCaches;
+ Vector<SCRIPT_FONTPROPERTIES*, kNumberOfFonts> m_fontProperties;
+ Vector<int, kNumberOfFonts> m_ascents;
+
+ // Index of the fallback font we're currently using for NextWinFontData.
+ int m_fontIndex;
+};
+
+} // namespace WebCore
+
+#endif // UniscribeHelperTextRun_h
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
index 1ca3e95..d076cb6 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
@@ -63,6 +63,7 @@ void SimpleFontData::platformInit()
void SimpleFontData::platformDestroy()
{
delete m_smallCapsFontData;
+ m_smallCapsFontData = 0;
if (isCustomFont())
return;
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
index 8621865..db8dd3b 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
@@ -80,6 +80,7 @@ void SimpleFontData::platformDestroy()
}
delete m_smallCapsFontData;
+ m_smallCapsFontData = 0;
}
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
@@ -97,25 +98,27 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
{
bool result = true;
- PangoCoverage* requested = pango_coverage_from_bytes((guchar*)characters, length);
- PangoCoverage* available = pango_font_get_coverage(m_font.m_font, pango_language_get_default());
- pango_coverage_max(requested, available);
+ PangoCoverage* coverage = pango_font_get_coverage(m_font.m_font, pango_language_get_default());
for (int i = 0; i < length; i++) {
- if (PANGO_COVERAGE_NONE == pango_coverage_get(requested, i)) {
+ if (PANGO_COVERAGE_NONE == pango_coverage_get(coverage, characters[i])) {
result = false;
break;
}
}
- pango_coverage_unref(requested);
- pango_coverage_unref(available);
+ pango_coverage_unref(coverage);
return result;
}
void SimpleFontData::determinePitch()
{
+ if (isCustomFont()) {
+ m_treatAsFixedPitch = false;
+ return;
+ }
+
m_treatAsFixedPitch = m_font.isFixedPitch();
}
diff --git a/WebCore/platform/graphics/mac/ColorMac.h b/WebCore/platform/graphics/mac/ColorMac.h
index 3be9094..830e9d9 100644
--- a/WebCore/platform/graphics/mac/ColorMac.h
+++ b/WebCore/platform/graphics/mac/ColorMac.h
@@ -39,6 +39,7 @@ class NSColor;
namespace WebCore {
+ // These functions assume NSColors are in DeviceRGB colorspace
Color colorFromNSColor(NSColor *);
NSColor* nsColor(const Color&);
diff --git a/WebCore/platform/graphics/mac/ColorMac.mm b/WebCore/platform/graphics/mac/ColorMac.mm
index 96fdc39..9b0f770 100644
--- a/WebCore/platform/graphics/mac/ColorMac.mm
+++ b/WebCore/platform/graphics/mac/ColorMac.mm
@@ -28,6 +28,7 @@
#import "ColorMac.h"
#import <wtf/Assertions.h>
+#import <wtf/StdLibExtras.h>
#import <wtf/RetainPtr.h>
@interface WebCoreControlTintObserver : NSObject
@@ -59,37 +60,30 @@ NSColor* nsColor(const Color& color)
switch (c) {
case 0: {
// Need this to avoid returning nil because cachedRGBAValues will default to 0.
- static RetainPtr<NSColor> clearColor = [NSColor clearColor];
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, clearColor, ([NSColor colorWithDeviceRed:0.0f green:0.0f blue:0.0f alpha:0.0f]));
return clearColor.get();
}
case Color::black: {
- static RetainPtr<NSColor> blackColor = [NSColor blackColor];
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, blackColor, ([NSColor colorWithDeviceRed:0.0f green:0.0f blue:0.0f alpha:1.0f]));
return blackColor.get();
}
case Color::white: {
- static RetainPtr<NSColor> whiteColor = [NSColor whiteColor];
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, whiteColor, ([NSColor colorWithDeviceRed:1.0f green:1.0f blue:1.0f alpha:1.0f]));
return whiteColor.get();
}
default: {
const int cacheSize = 32;
static unsigned cachedRGBAValues[cacheSize];
- static RetainPtr<NSColor> cachedColors[cacheSize];
+ static RetainPtr<NSColor>* cachedColors = new RetainPtr<NSColor>[cacheSize];
for (int i = 0; i != cacheSize; ++i)
if (cachedRGBAValues[i] == c)
return cachedColors[i].get();
-#ifdef COLORMATCH_EVERYTHING
- NSColor* result = [NSColor colorWithCalibratedRed:color.red() / 255.0f
- green:color.green() / 255.0f
- blue:color.blue() / 255.0f
- alpha:color.alpha() /255.0f];
-#else
NSColor* result = [NSColor colorWithDeviceRed:color.red() / 255.0f
green:color.green() / 255.0f
blue:color.blue() / 255.0f
alpha:color.alpha() /255.0f];
-#endif
static int cursor;
cachedRGBAValues[cursor] = c;
@@ -158,12 +152,8 @@ void setUsesTestModeFocusRingColor(bool newValue)
+ (void)controlTintDidChange
{
-#ifdef COLORMATCH_EVERYTHING
-#error Not yet implemented.
-#else
NSColor* color = [[NSColor keyboardFocusIndicatorColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
WebCore::systemFocusRingColor = WebCore::makeRGBAFromNSColor(color);
-#endif
}
@end
diff --git a/WebCore/platform/graphics/mac/CoreTextController.cpp b/WebCore/platform/graphics/mac/CoreTextController.cpp
index 171a7ec..49e83c4 100644
--- a/WebCore/platform/graphics/mac/CoreTextController.cpp
+++ b/WebCore/platform/graphics/mac/CoreTextController.cpp
@@ -369,9 +369,9 @@ void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsig
static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
static const void* ltrOptionValues[] = { kCFBooleanFalse };
static const void* rtlOptionValues[] = { kCFBooleanTrue };
- static RetainPtr<CFDictionaryRef> ltrTypesetterOptions(AdoptCF, CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
- static RetainPtr<CFDictionaryRef> rtlTypesetterOptions(AdoptCF, CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
- typesetter.adoptCF(CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions.get() : rtlTypesetterOptions.get()));
+ static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ typesetter.adoptCF(CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));
} else
typesetter.adoptCF(CTTypesetterCreateWithAttributedString(attributedString.get()));
diff --git a/WebCore/platform/graphics/mac/FontCacheMac.mm b/WebCore/platform/graphics/mac/FontCacheMac.mm
index e7cda66..26d84cc 100644
--- a/WebCore/platform/graphics/mac/FontCacheMac.mm
+++ b/WebCore/platform/graphics/mac/FontCacheMac.mm
@@ -35,6 +35,7 @@
#import "FontPlatformData.h"
#import "WebCoreSystemInterface.h"
#import "WebFontCache.h"
+#include <wtf/StdLibExtras.h>
#ifdef BUILDING_ON_TIGER
typedef int NSInteger;
@@ -44,7 +45,7 @@ namespace WebCore {
static void fontCacheATSNotificationCallback(ATSFontNotificationInfoRef, void*)
{
- FontCache::invalidate();
+ fontCache()->invalidate();
}
void FontCache::platformInit()
@@ -139,10 +140,10 @@ FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
const FontFamily* currFamily = &font.fontDescription().family();
while (currFamily && !platformData) {
if (currFamily->family().length()) {
- static String matchWords[3] = { String("Arabic"), String("Pashto"), String("Urdu") };
- static AtomicString geezaStr("Geeza Pro");
+ static String* matchWords[3] = { new String("Arabic"), new String("Pashto"), new String("Urdu") };
+ DEFINE_STATIC_LOCAL(AtomicString, geezaStr, ("Geeza Pro"));
for (int j = 0; j < 3 && !platformData; ++j)
- if (currFamily->family().contains(matchWords[j], false))
+ if (currFamily->family().contains(*matchWords[j], false))
platformData = getCachedFontPlatformData(font.fontDescription(), geezaStr);
}
currFamily = currFamily->next();
@@ -153,8 +154,8 @@ FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
{
- static AtomicString timesStr("Times");
- static AtomicString lucidaGrandeStr("Lucida Grande");
+ DEFINE_STATIC_LOCAL(AtomicString, timesStr, ("Times"));
+ DEFINE_STATIC_LOCAL(AtomicString, lucidaGrandeStr, ("Lucida Grande"));
// 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 any prefs.
diff --git a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
index 1fb144c..9aa4997 100644
--- a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
@@ -68,7 +68,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
CGFontRef cgFontRef = CGFontCreateWithPlatformFont(&fontRef);
#ifndef BUILDING_ON_TIGER
// Workaround for <rdar://problem/5675504>.
- if (!CGFontGetNumberOfGlyphs(cgFontRef)) {
+ if (cgFontRef && !CGFontGetNumberOfGlyphs(cgFontRef)) {
CFRelease(cgFontRef);
cgFontRef = 0;
}
diff --git a/WebCore/platform/graphics/mac/FontMacATSUI.mm b/WebCore/platform/graphics/mac/FontMacATSUI.mm
index 9a45c5a..52493e7 100644
--- a/WebCore/platform/graphics/mac/FontMacATSUI.mm
+++ b/WebCore/platform/graphics/mac/FontMacATSUI.mm
@@ -154,8 +154,7 @@ static void initializeATSUStyle(const SimpleFontData* fontData)
fontData->m_ATSUStyleInitialized = true;
}
-static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector iCurrentOperation, ATSULineRef iLineRef, URefCon iRefCon,
- void *iOperationCallbackParameterPtr, ATSULayoutOperationCallbackStatus *oCallbackStatus)
+static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef iLineRef, URefCon iRefCon, void*, ATSULayoutOperationCallbackStatus* oCallbackStatus)
{
ATSULayoutParameters* params = reinterpret_cast<ATSULayoutParameters*>(iRefCon);
OSStatus status;
@@ -592,7 +591,7 @@ float Font::floatWidthForComplexText(const TextRun& run) const
MIN(FixedToFloat(firstGlyphBounds.upperLeft.x), FixedToFloat(firstGlyphBounds.lowerLeft.x));
}
-int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const
+int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool /*includePartialGlyphs*/) const
{
OwnArrayPtr<UChar> charactersWithOverride;
TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
diff --git a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
index 15e573d..7cd9ab6 100644
--- a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
+++ b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
@@ -34,7 +34,7 @@ FontPlatformData::FontPlatformData(NSFont *f, bool b , bool o)
CFRetain(f);
m_size = f ? [f pointSize] : 0.0f;
#ifndef BUILDING_ON_TIGER
- m_cgFont = CTFontCopyGraphicsFont(toCTFontRef(f), 0);
+ m_cgFont.adoptCF(CTFontCopyGraphicsFont(toCTFontRef(f), 0));
m_atsuFontID = CTFontGetPlatformFont(toCTFontRef(f), 0);
#else
m_cgFont = wkGetCGFontFromNSFont(f);
@@ -86,7 +86,7 @@ void FontPlatformData::setFont(NSFont *font)
m_font = font;
m_size = font ? [font pointSize] : 0.0f;
#ifndef BUILDING_ON_TIGER
- m_cgFont = CTFontCopyGraphicsFont(toCTFontRef(font), 0);
+ m_cgFont.adoptCF(CTFontCopyGraphicsFont(toCTFontRef(font), 0));
m_atsuFontID = CTFontGetPlatformFont(toCTFontRef(font), 0);
#else
m_cgFont = wkGetCGFontFromNSFont(font);
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index 3f9176c..ae829e2 100644
--- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -27,6 +27,7 @@
#import "GraphicsContext.h"
#import "../cg/GraphicsContextPlatformPrivateCG.h"
+#import <wtf/StdLibExtras.h>
#import "WebCoreSystemInterface.h"
@@ -80,53 +81,42 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op)
[pool drain];
}
#endif
-
+
+static NSColor* createPatternColor(NSString* name, NSColor* defaultColor, bool& usingDot)
+{
+ NSImage *image = [NSImage imageNamed:name];
+ ASSERT(image); // if image is not available, we want to know
+ NSColor *color = (image ? [NSColor colorWithPatternImage:image] : nil);
+ if (color)
+ usingDot = true;
+ else
+ color = defaultColor;
+ return color;
+}
+
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar)
{
if (paintingDisabled())
return;
- // Constants for spelling pattern color
- static RetainPtr<NSColor> spellingPatternColor = nil;
- static bool usingDotForSpelling = false;
-
- // Constants for grammar pattern color
- static RetainPtr<NSColor> grammarPatternColor = nil;
- static bool usingDotForGrammar = false;
-
// These are the same for misspelling or bad grammar
int patternHeight = cMisspellingLineThickness;
int patternWidth = cMisspellingLinePatternWidth;
- // Initialize pattern color if needed
- if (!grammar && !spellingPatternColor) {
- NSImage *image = [NSImage imageNamed:@"SpellingDot"];
- ASSERT(image); // if image is not available, we want to know
- NSColor *color = (image ? [NSColor colorWithPatternImage:image] : nil);
- if (color)
- usingDotForSpelling = true;
- else
- color = [NSColor redColor];
- spellingPatternColor = color;
- }
-
- if (grammar && !grammarPatternColor) {
- NSImage *image = [NSImage imageNamed:@"GrammarDot"];
- ASSERT(image); // if image is not available, we want to know
- NSColor *color = (image ? [NSColor colorWithPatternImage:image] : nil);
- if (color)
- usingDotForGrammar = true;
- else
- color = [NSColor greenColor];
- grammarPatternColor = color;
- }
-
bool usingDot;
NSColor *patternColor;
if (grammar) {
+ // 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
+ static bool usingDotForSpelling = false;
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"SpellingDot", [NSColor redColor], usingDotForSpelling)));
+
usingDot = usingDotForSpelling;
patternColor = spellingPatternColor.get();
}
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 0ec56d6..a33c8d2 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -29,14 +29,19 @@
#import "MediaPlayerPrivateQTKit.h"
+#ifdef BUILDING_ON_TIGER
+#import "AutodrainedPool.h"
+#endif
+
#import "BlockExceptions.h"
+#import "FrameView.h"
#import "GraphicsContext.h"
#import "KURL.h"
-#import "FrameView.h"
#import "SoftLinking.h"
#import "WebCoreSystemInterface.h"
#import <QTKit/QTKit.h>
#import <objc/objc-runtime.h>
+#import <wtf/UnusedParam.h>
#if DRAW_FRAME_RATE
#import "Font.h"
@@ -239,7 +244,7 @@ void MediaPlayerPrivate::createQTMovie(const String& url)
object:m_qtMovie.get()];
}
-static void mainThreadSetNeedsDisplay(id self, SEL _cmd)
+static void mainThreadSetNeedsDisplay(id self, SEL)
{
id movieView = [self superview];
ASSERT(!movieView || [movieView isKindOfClass:[QTMovieView class]]);
@@ -772,6 +777,10 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
context->scale(FloatSize(1.0f, -1.0f));
context->setImageInterpolationQuality(InterpolationLow);
IntRect paintRect(IntPoint(0, 0), IntSize(r.width(), r.height()));
+
+#ifdef BUILDING_ON_TIGER
+ AutodrainedPool pool;
+#endif
NSGraphicsContext* newContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context->platformContext() flipped:NO];
// draw the current video frame
@@ -969,48 +978,54 @@ void MediaPlayerPrivate::disableUnsupportedTracks(unsigned& enabledTrackCount)
m_callback->repaint();
}
-- (void)loadStateChanged:(NSNotification *)notification
+- (void)loadStateChanged:(NSNotification *)unusedNotification
{
+ UNUSED_PARAM(unusedNotification);
if (m_delayCallbacks)
[self performSelector:_cmd withObject:nil afterDelay:0];
else
m_callback->loadStateChanged();
}
-- (void)rateChanged:(NSNotification *)notification
+- (void)rateChanged:(NSNotification *)unusedNotification
{
+ UNUSED_PARAM(unusedNotification);
if (m_delayCallbacks)
[self performSelector:_cmd withObject:nil afterDelay:0];
else
m_callback->rateChanged();
}
-- (void)sizeChanged:(NSNotification *)notification
+- (void)sizeChanged:(NSNotification *)unusedNotification
{
+ UNUSED_PARAM(unusedNotification);
if (m_delayCallbacks)
[self performSelector:_cmd withObject:nil afterDelay:0];
else
m_callback->sizeChanged();
}
-- (void)timeChanged:(NSNotification *)notification
+- (void)timeChanged:(NSNotification *)unusedNotification
{
+ UNUSED_PARAM(unusedNotification);
if (m_delayCallbacks)
[self performSelector:_cmd withObject:nil afterDelay:0];
else
m_callback->timeChanged();
}
-- (void)didEnd:(NSNotification *)notification
+- (void)didEnd:(NSNotification *)unusedNotification
{
+ UNUSED_PARAM(unusedNotification);
if (m_delayCallbacks)
[self performSelector:_cmd withObject:nil afterDelay:0];
else
m_callback->didEnd();
}
-- (void)newImageAvailable:(NSNotification *)notification
+- (void)newImageAvailable:(NSNotification *)unusedNotification
{
+ UNUSED_PARAM(unusedNotification);
[self repaint];
}
diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index 4ee5933..30dbf97 100644
--- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -42,6 +42,7 @@
#import <float.h>
#import <unicode/uchar.h>
#import <wtf/Assertions.h>
+#import <wtf/StdLibExtras.h>
#import <wtf/RetainPtr.h>
@interface NSFont (WebAppKitSecretAPI)
@@ -54,7 +55,7 @@ const float smallCapsFontSizeMultiplier = 0.7f;
const float contextDPI = 72.0f;
static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return x * (contextDPI / (contextDPI * unitsPerEm)); }
-bool initFontData(SimpleFontData* fontData)
+static bool initFontData(SimpleFontData* fontData)
{
if (!fontData->m_font.cgFont())
return false;
@@ -92,9 +93,7 @@ bool initFontData(SimpleFontData* fontData)
static NSString *webFallbackFontFamily(void)
{
- static RetainPtr<NSString> webFallbackFontFamily = nil;
- if (!webFallbackFontFamily)
- webFallbackFontFamily = [[NSFont systemFontOfSize:16.0f] familyName];
+ DEFINE_STATIC_LOCAL(RetainPtr<NSString>, webFallbackFontFamily, ([[NSFont systemFontOfSize:16.0f] familyName]));
return webFallbackFontFamily.get();
}
@@ -315,7 +314,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
smallCapsFont.m_syntheticBold = (fontTraits & NSBoldFontMask) && !(smallCapsFontTraits & NSBoldFontMask);
smallCapsFont.m_syntheticOblique = (fontTraits & NSItalicFontMask) && !(smallCapsFontTraits & NSItalicFontMask);
- m_smallCapsFontData = FontCache::getCachedFontData(&smallCapsFont);
+ m_smallCapsFontData = fontCache()->getCachedFontData(&smallCapsFont);
}
END_BLOCK_OBJC_EXCEPTIONS;
}
@@ -325,7 +324,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
{
- NSString *string = [[NSString alloc] initWithCharactersNoCopy:(UniChar*)characters length:length freeWhenDone:NO];
+ NSString *string = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(characters) length:length freeWhenDone:NO];
NSCharacterSet *set = [[m_font.font() coveredCharacterSet] invertedSet];
bool result = set && [string rangeOfCharacterFromSet:set].location == NSNotFound;
[string release];
diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp
index be31d96..114f073 100644
--- a/WebCore/platform/graphics/qt/FontCacheQt.cpp
+++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp
@@ -1,5 +1,6 @@
/*
Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2008 Holger Hans Peter Freyther
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -21,18 +22,31 @@
*/
#include "config.h"
#include "FontCache.h"
+
#include "FontDescription.h"
+#include "FontPlatformData.h"
#include "Font.h"
+#include <wtf/StdLibExtras.h>
namespace WebCore {
+FontCache* fontCache()
+{
+ DEFINE_STATIC_LOCAL(FontCache, globalFontCache, ());
+ return &globalFontCache;
+}
+
+FontCache::FontCache()
+{
+}
+
void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
{
}
-FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName)
+FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& description, const AtomicString& family, bool checkingAlternateName)
{
- return 0;
+ return new FontPlatformData(description);
}
SimpleFontData* FontCache::getCachedFontData(const FontPlatformData*)
@@ -45,6 +59,10 @@ FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription&)
return 0;
}
+void FontCache::releaseFontData(const WebCore::SimpleFontData*)
+{
+}
+
void FontCache::addClient(FontSelector*)
{
}
diff --git a/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp b/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
index 8fc3ea0..a19464e 100644
--- a/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
@@ -25,19 +25,25 @@
#include "FontPlatformData.h"
#include "SharedBuffer.h"
#include <QFontDatabase>
+#include <QStringList>
namespace WebCore {
FontCustomPlatformData::~FontCustomPlatformData()
{
- QFontDatabase::removeApplicationFont(handle);
+ QFontDatabase::removeApplicationFont(m_handle);
}
FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontRenderingMode)
{
- FontPlatformData result;
- result.handle = handle;
- return result;
+ QFont font;
+ font.setFamily(QFontDatabase::applicationFontFamilies(m_handle)[0]);
+ font.setPixelSize(size);
+ if (bold)
+ font.setWeight(QFont::Bold);
+ font.setItalic(italic);
+
+ return FontPlatformData(font, bold);
}
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
@@ -47,8 +53,11 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
int id = QFontDatabase::addApplicationFontFromData(QByteArray(buffer->data(), buffer->size()));
if (id == -1)
return 0;
+
+ Q_ASSERT(QFontDatabase::applicationFontFamilies(id).size() > 0);
+
FontCustomPlatformData *data = new FontCustomPlatformData;
- data->handle = id;
+ data->m_handle = id;
return data;
}
diff --git a/WebCore/platform/graphics/qt/FontCustomPlatformData.h b/WebCore/platform/graphics/qt/FontCustomPlatformData.h
index da5159d..4305b87 100644
--- a/WebCore/platform/graphics/qt/FontCustomPlatformData.h
+++ b/WebCore/platform/graphics/qt/FontCustomPlatformData.h
@@ -33,7 +33,8 @@ class FontPlatformData;
struct FontCustomPlatformData : Noncopyable {
~FontCustomPlatformData();
- int handle; // for use with QFontDatabase::addApplicationFont/removeApplicationFont
+ // for use with QFontDatabase::addApplicationFont/removeApplicationFont
+ int m_handle;
FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode);
};
diff --git a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
new file mode 100644
index 0000000..22ae205
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
@@ -0,0 +1,106 @@
+/*
+ Copyright (C) 2008 Holger Hans Peter Freyther
+
+ 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.
+
+ Replacement of the stock FontFallbackList as Qt is going to find us a
+ replacement font, will do caching and the other stuff we implement in
+ WebKit.
+*/
+
+#include "config.h"
+#include "FontFallbackList.h"
+
+#include "Font.h"
+#include "SegmentedFontData.h"
+
+#include <QDebug>
+
+namespace WebCore {
+
+FontFallbackList::FontFallbackList()
+ : m_familyIndex(0)
+ , m_pitch(UnknownPitch)
+ , m_loadingCustomFonts(false)
+ , m_fontSelector(0)
+ , m_generation(0)
+{
+}
+
+void FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector> fontSelector)
+{
+ releaseFontData();
+ m_fontList.clear();
+ m_familyIndex = 0;
+ m_pitch = UnknownPitch;
+ m_loadingCustomFonts = false;
+ m_fontSelector = fontSelector;
+ m_generation = 0;
+}
+
+void FontFallbackList::releaseFontData()
+{
+}
+
+void FontFallbackList::determinePitch(const WebCore::Font* font) const
+{
+ const FontData* fontData = primaryFont(font);
+ if (!fontData->isSegmented())
+ m_pitch = static_cast<const SimpleFontData*>(fontData)->pitch();
+ else {
+ const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
+ unsigned numRanges = segmentedFontData->numRanges();
+ if (numRanges == 1)
+ m_pitch = segmentedFontData->rangeAt(0).fontData()->pitch();
+ else
+ m_pitch = VariablePitch;
+ }
+}
+
+const FontData* FontFallbackList::fontDataAt(const WebCore::Font* _font, unsigned index) const
+{
+ if (index != 0)
+ return 0;
+
+ // Use the FontSelector to get a WebCore font and then fallback to Qt
+ const FontDescription& description = _font->fontDescription();
+ const FontFamily* family = &description.family();
+ while (family) {
+ if (m_fontSelector) {
+ FontData* data = m_fontSelector->getFontData(description, family->family());
+ if (data) {
+ if (data->isLoading())
+ m_loadingCustomFonts = true;
+ return data;
+ }
+ }
+ family = family->next();
+ }
+
+ return new SimpleFontData(FontPlatformData(description), _font->wordSpacing(), _font->letterSpacing());
+}
+
+const FontData* FontFallbackList::fontDataForCharacters(const WebCore::Font* font, const UChar*, int) const
+{
+ return primaryFont(font);
+}
+
+void FontFallbackList::setPlatformFont(const WebCore::FontPlatformData& platformData)
+{
+ m_familyIndex = cAllFamiliesScanned;
+}
+
+}
diff --git a/WebCore/platform/graphics/qt/FontPlatformData.h b/WebCore/platform/graphics/qt/FontPlatformData.h
index e4363be..5e97678 100644
--- a/WebCore/platform/graphics/qt/FontPlatformData.h
+++ b/WebCore/platform/graphics/qt/FontPlatformData.h
@@ -1,5 +1,6 @@
/*
Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2008 Holger Hans Peter Freyther
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -22,14 +23,29 @@
#ifndef FontPlatformData_h
#define FontPlatformData_h
+#include "FontDescription.h"
+
+#include <QFont>
+
namespace WebCore {
class FontPlatformData
{
public:
- // this is only used for custom loaded fonts and represents the id handle passed to
- // QFontDatabase::addApplicationFont/removeApplicationFont
- int handle;
+#if ENABLE(SVG_FONTS)
+ FontPlatformData(float size, bool bold, bool oblique);
+#endif
+ FontPlatformData();
+ FontPlatformData(const FontDescription&, int wordSpacing = 0, int letterSpacing = 0);
+ FontPlatformData(const QFont&, bool bold);
+
+ QFont font() const { return m_font; }
+ float size() const { return m_size; }
+
+ float m_size;
+ bool m_bold;
+ bool m_oblique;
+ QFont m_font;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
new file mode 100644
index 0000000..ea51fe8
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2008 Holger Hans Peter Freyther
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "config.h"
+#include "FontPlatformData.h"
+
+namespace WebCore {
+
+FontPlatformData::FontPlatformData(const FontDescription& description, int wordSpacing, int letterSpacing)
+ : m_size(0.0f)
+ , m_bold(false)
+ , m_oblique(false)
+{
+ QString familyName;
+ const FontFamily* family = &description.family();
+ while (family) {
+ familyName += family->family();
+ family = family->next();
+ if (family)
+ familyName += QLatin1Char(',');
+ }
+
+ m_font.setFamily(familyName);
+ m_font.setPixelSize(qRound(description.computedSize()));
+ m_font.setItalic(description.italic());
+ // FIXME: Map all FontWeight values to QFont weights.
+ if (description.weight() >= FontWeight600)
+ m_font.setWeight(QFont::Bold);
+ else
+ m_font.setWeight(QFont::Normal);
+
+ bool smallCaps = description.smallCaps();
+ m_font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
+ m_font.setWordSpacing(wordSpacing);
+ m_font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
+ m_size = m_font.pointSize();
+}
+
+FontPlatformData::FontPlatformData(const QFont& font, bool bold)
+ : m_size(font.pointSize())
+ , m_bold(bold)
+ , m_oblique(false)
+ , m_font(font)
+{
+}
+
+FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
+ : m_size(size)
+ , m_bold(bold)
+ , m_oblique(oblique)
+{
+}
+
+FontPlatformData::FontPlatformData()
+ : m_size(0.0f)
+ , m_bold(false)
+ , m_oblique(false)
+{
+}
+
+}
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index e2ef605..deeea99 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -1,5 +1,6 @@
/*
Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2008 Holger Hans Peter Freyther
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -20,6 +21,7 @@
#include "config.h"
#include "Font.h"
#include "FontDescription.h"
+#include "FontFallbackList.h"
#include "FontSelector.h"
#include "GraphicsContext.h"
@@ -31,66 +33,9 @@
#include <qdebug.h>
#include <limits.h>
-namespace WebCore {
#if QT_VERSION >= 0x040400
-
-Font::Font()
- : m_letterSpacing(0)
- , m_wordSpacing(0)
- , m_font()
- , m_scFont()
-{
- QFontMetrics metrics(m_font);
- m_spaceWidth = metrics.width(QLatin1Char(' '));
-}
-
-Font::Font(const FontDescription& description, short letterSpacing, short wordSpacing)
- : m_fontDescription(description)
- , m_letterSpacing(letterSpacing)
- , m_wordSpacing(wordSpacing)
-{
- const FontFamily* family = &description.family();
- QString familyName;
- while (family) {
- familyName += family->family();
- family = family->next();
- if (family)
- familyName += QLatin1Char(',');
- }
-
- m_font.setFamily(familyName);
- m_font.setPixelSize(qRound(description.computedSize()));
- m_font.setItalic(description.italic());
- // FIXME: Map all FontWeight values to QFont weights.
- if (description.weight() >= FontWeight600)
- m_font.setWeight(QFont::Bold);
- else
- m_font.setWeight(QFont::Normal);
-
- bool smallCaps = description.smallCaps();
- m_font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
-
- QFontMetrics metrics = QFontMetrics(m_font);
- m_spaceWidth = metrics.width(QLatin1Char(' '));
-
- if (wordSpacing)
- m_font.setWordSpacing(wordSpacing);
- if (letterSpacing)
- m_font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
-}
-
-void Font::setWordSpacing(short s)
-{
- m_font.setWordSpacing(s);
- m_wordSpacing = s;
-}
-void Font::setLetterSpacing(short s)
-{
- m_font.setLetterSpacing(QFont::AbsoluteSpacing, s);
- m_letterSpacing = s;
-}
-
+namespace WebCore {
static QString qstring(const TextRun& run)
{
@@ -121,10 +66,11 @@ static QTextLine setupLayout(QTextLayout* layout, const TextRun& style)
return line;
}
-void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
+void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
{
if (to < 0)
to = run.length();
+
QPainter *p = ctx->platformContext();
Color color = ctx->fillColor();
p->setPen(QColor(color));
@@ -138,14 +84,14 @@ void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint&
bool hasShadow = ctx->textDrawingMode() == cTextFill && ctx->getShadow(shadowSize, shadowBlur, shadowColor);
if (from > 0 || to < run.length()) {
- QTextLayout layout(string, m_font);
+ QTextLayout layout(string, font());
QTextLine line = setupLayout(&layout, run);
float x1 = line.cursorToX(from);
float x2 = line.cursorToX(to);
if (x2 < x1)
qSwap(x1, x2);
- QFontMetrics fm(m_font);
+ QFontMetrics fm(font());
int ascent = fm.ascent();
QRectF clip(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
@@ -179,7 +125,7 @@ void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint&
return;
}
- p->setFont(m_font);
+ p->setFont(font());
QPointF pt(point.x(), point.y());
int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
@@ -194,12 +140,12 @@ void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint&
p->drawText(pt, string, flags, run.padding());
}
-int Font::width(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run) const
{
if (!run.length())
return 0;
QString string = qstring(run);
- QTextLayout layout(string, m_font);
+ QTextLayout layout(string, font());
QTextLine line = setupLayout(&layout, run);
int w = int(line.naturalTextWidth());
// WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
@@ -209,30 +155,18 @@ int Font::width(const TextRun& run) const
return w + run.padding();
}
-float Font::floatWidth(const TextRun& run) const
-{
- return width(run);
-}
-
-float Font::floatWidth(const TextRun& run, int /*extraCharsAvailable*/, int& charsConsumed, String& glyphName) const
-{
- charsConsumed = run.length();
- glyphName = "";
- return width(run);
-}
-
-int Font::offsetForPosition(const TextRun& run, int position, bool /*includePartialGlyphs*/) const
+int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const
{
QString string = qstring(run);
- QTextLayout layout(string, m_font);
+ QTextLayout layout(string, font());
QTextLine line = setupLayout(&layout, run);
return line.xToCursor(position);
}
-FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const
{
QString string = qstring(run);
- QTextLayout layout(string, m_font);
+ QTextLayout layout(string, font());
QTextLine line = setupLayout(&layout, run);
float x1 = line.cursorToX(from);
@@ -243,464 +177,12 @@ FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& pt, int
return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
}
-#else
-
-
-struct TextRunComponent {
- TextRunComponent() : font(0) {}
- TextRunComponent(const UChar *start, int length, bool rtl, const QFont *font, int offset, bool sc = false);
- TextRunComponent(int spaces, bool rtl, const QFont *font, int offset);
-
- inline bool isSpace() const { return spaces != 0; }
-
- QString string;
- const QFont *font;
- int width;
- int offset;
- int spaces;
-};
-
-TextRunComponent::TextRunComponent(const UChar *start, int length, bool rtl, const QFont *f, int o, bool sc)
- : string(reinterpret_cast<const QChar*>(start), length)
- , font(f)
- , offset(o)
- , spaces(0)
-{
- if (sc)
- string = string.toUpper();
- string.prepend(rtl ? QChar(0x202e) : QChar(0x202d));
- width = QFontMetrics(*font).width(string);
-}
-
-TextRunComponent::TextRunComponent(int s, bool rtl, const QFont *f, int o)
- : string(s, QLatin1Char(' '))
- , font(f)
- , offset(o)
- , spaces(s)
-{
- string.prepend(rtl ? QChar(0x202e) : QChar(0x202d));
- width = spaces * QFontMetrics(*font).width(QLatin1Char(' '));
-}
-
-
-Font::Font()
- : m_letterSpacing(0)
- , m_wordSpacing(0)
- , m_font()
- , m_scFont()
-{
- QFontMetrics metrics(m_font);
- m_spaceWidth = metrics.width(QLatin1Char(' '));
- qreal pointsize = m_font.pointSizeF();
- if (pointsize > 0)
- m_scFont.setPointSizeF(pointsize*0.7);
- else
- m_scFont.setPixelSize(qRound(m_font.pixelSize()*.7));
-}
-
-Font::Font(const FontDescription& description, short letterSpacing, short wordSpacing)
- : m_fontDescription(description)
- , m_letterSpacing(letterSpacing)
- , m_wordSpacing(wordSpacing)
-{
- const FontFamily* family = &description.family();
- QString familyName;
- while (family) {
- familyName += family->family();
- family = family->next();
- if (family)
- familyName += QLatin1Char(',');
- }
-
- m_font.setFamily(familyName);
- m_font.setPixelSize(qRound(description.computedSize()));
- m_font.setItalic(description.italic());
- // FIXME: Map all FontWeight values to QFont weights.
- if (description.weight() >= FontWeight600)
- m_font.setWeight(QFont::Bold);
- else
- m_font.setWeight(QFont::Normal);
-
- QFontMetrics metrics = QFontMetrics(m_font);
- m_spaceWidth = metrics.width(QLatin1Char(' '));
- m_scFont = m_font;
- m_scFont.setPixelSize(qRound(description.computedSize()*.7));
-}
-
-void Font::setWordSpacing(short s)
-{
- m_wordSpacing = s;
-}
-void Font::setLetterSpacing(short s)
-{
- m_letterSpacing = s;
-}
-
-static int generateComponents(Vector<TextRunComponent, 1024>* components, const Font &font, const TextRun &run)
-{
-// qDebug() << "generateComponents" << QString((const QChar *)run.characters(), run.length());
- int letterSpacing = font.letterSpacing();
- int wordSpacing = font.wordSpacing();
- bool smallCaps = font.fontDescription().smallCaps();
- int padding = run.padding();
- int numSpaces = 0;
- if (padding) {
- for (int i = 0; i < run.length(); i++)
- if (Font::treatAsSpace(run[i]))
- ++numSpaces;
- }
-
- int offset = 0;
- const QFont *f = &font.font();
- if (letterSpacing || smallCaps) {
- // need to draw every letter on it's own
- int start = 0;
- if (Font::treatAsSpace(run[0])) {
- int add = 0;
- if (numSpaces) {
- add = padding/numSpaces;
- padding -= add;
- --numSpaces;
- }
- components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
- offset += add + letterSpacing + components->last().width;
- start = 1;
-// qDebug() << "space at 0" << offset;
- } else if (smallCaps) {
- f = (QChar::category(run[0]) == QChar::Letter_Lowercase ? &font.scFont() : &font.font());
- }
- for (int i = 1; i < run.length(); ++i) {
- uint ch = run[i];
- if (QChar(ch).isHighSurrogate() && QChar(run[i-1]).isLowSurrogate())
- ch = QChar::surrogateToUcs4(ch, run[i-1]);
- if (QChar(ch).isLowSurrogate() || QChar::category(ch) == QChar::Mark_NonSpacing)
- continue;
- if (Font::treatAsSpace(run[i])) {
- int add = 0;
-// qDebug() << " treatAsSpace:" << i << start;
- if (i - start > 0) {
- components->append(TextRunComponent(run.characters() + start, i - start,
- run.rtl(),
- f, offset, f == &font.scFont()));
- offset += components->last().width + letterSpacing;
-// qDebug() << " appending(1) " << components->last().string << components->last().width;
- }
- if (numSpaces) {
- add = padding/numSpaces;
- padding -= add;
- --numSpaces;
- }
- components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
- offset += wordSpacing + add + components->last().width + letterSpacing;
- start = i + 1;
- continue;
- } else if (!letterSpacing) {
-// qDebug() << i << char(run[i]) << (QChar::category(ch) == QChar::Letter_Lowercase) <<
-// QFontInfo(*f).pointSizeF();
- if (QChar::category(ch) == QChar::Letter_Lowercase) {
- if (f == &font.scFont())
- continue;
- } else {
- if (f == &font.font())
- continue;
- }
- }
- if (i - start > 0) {
- components->append(TextRunComponent(run.characters() + start, i - start,
- run.rtl(),
- f, offset, f == &font.scFont()));
- offset += components->last().width + letterSpacing;
-// qDebug() << " appending(2) " << components->last().string << components->last().width;
- }
- if (smallCaps)
- f = (QChar::category(ch) == QChar::Letter_Lowercase ? &font.scFont() : &font.font());
- start = i;
- }
- if (run.length() - start > 0) {
- components->append(TextRunComponent(run.characters() + start, run.length() - start,
- run.rtl(),
- f, offset, f == &font.scFont()));
- offset += components->last().width;
-// qDebug() << " appending(3) " << components->last().string << components->last().width;
- }
- offset += letterSpacing;
- } else {
- int start = 0;
- for (int i = 0; i < run.length(); ++i) {
- if (Font::treatAsSpace(run[i])) {
- if (i - start > 0) {
- components->append(TextRunComponent(run.characters() + start, i - start,
- run.rtl(),
- f, offset));
- offset += components->last().width;
- }
- int add = 0;
- if (numSpaces) {
- add = padding/numSpaces;
- padding -= add;
- --numSpaces;
- }
- components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
- offset += add + components->last().width;
- if (i)
- offset += wordSpacing;
- start = i + 1;
- }
- }
- if (run.length() - start > 0) {
- components->append(TextRunComponent(run.characters() + start, run.length() - start,
- run.rtl(),
- f, offset));
- offset += components->last().width;
- }
- }
- return offset;
-}
-
-void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- if (to < 0)
- to = run.length();
- QPainter *p = ctx->platformContext();
- Color color = ctx->fillColor();
- p->setPen(QColor(color));
-
- Vector<TextRunComponent, 1024> components;
- int w = generateComponents(&components, *this, run);
-
- if (from > 0 || to < run.length()) {
- FloatRect clip = selectionRectForText(run,
- IntPoint(qRound(point.x()), qRound(point.y())),
- QFontMetrics(m_font).height(), from, to);
- QRectF rect(clip.x(), clip.y() - ascent(), clip.width(), clip.height());
- p->save();
- p->setClipRect(rect.toRect());
- }
-
- if (run.rtl()) {
- for (int i = 0; i < components.size(); ++i) {
- if (!components.at(i).isSpace()) {
- p->setFont(*components.at(i).font);
- QPointF pt(point.x() + w - components.at(i).offset - components.at(i).width, point.y());
- p->drawText(pt, components.at(i).string);
- }
- }
- } else {
- for (int i = 0; i < components.size(); ++i) {
- if (!components.at(i).isSpace()) {
- p->setFont(*components.at(i).font);
- QPointF pt(point.x() + components.at(i).offset, point.y());
- p->drawText(pt, components.at(i).string);
- }
- }
- }
- if (from > 0 || to < run.length())
- p->restore();
-}
-
-int Font::width(const TextRun& run) const
-{
- Vector<TextRunComponent, 1024> components;
- int w = generateComponents(&components, *this, run);
-
-// qDebug() << " width=" << w;
- return w;
-}
-
-float Font::floatWidth(const TextRun& run) const
-{
- return width(run);
-}
-
-float Font::floatWidth(const TextRun& run, int /*extraCharsAvailable*/, int& charsConsumed, String& glyphName) const
+QFont Font::font() const
{
- charsConsumed = run.length();
- glyphName = "";
- return width(run);
+ return primaryFont()->getQtFont();
}
-int Font::offsetForPosition(const TextRun& run, int position, bool includePartialGlyphs) const
-{
- Vector<TextRunComponent, 1024> components;
- int w = generateComponents(&components, *this, run);
-
- int offset = 0;
- if (run.rtl()) {
- for (int i = 0; i < components.size(); ++i) {
- int xe = w - components.at(i).offset;
- int xs = xe - components.at(i).width;
- if (position >= xs) {
- QTextLayout layout(components.at(i).string, *components.at(i).font);
- layout.beginLayout();
- QTextLine l = layout.createLine();
- if (!l.isValid())
- return offset;
-
- l.setLineWidth(INT_MAX/256);
- layout.endLayout();
-
- if (position - xs >= l.width())
- return offset;
- int cursor = l.xToCursor(position - xs);
- if (cursor > 1)
- --cursor;
- return offset + cursor;
- } else {
- offset += components.at(i).string.length() - 1;
- }
- }
- } else {
- for (int i = 0; i < components.size(); ++i) {
- int xs = components.at(i).offset;
- int xe = xs + components.at(i).width;
- if (position <= xe) {
- QTextLayout layout(components.at(i).string, *components.at(i).font);
- layout.beginLayout();
- QTextLine l = layout.createLine();
- if (!l.isValid())
- return offset;
-
- l.setLineWidth(INT_MAX/256);
- layout.endLayout();
-
- if (position - xs >= l.width())
- return offset + components.at(i).string.length() - 1;
- int cursor = l.xToCursor(position - xs);
- if (cursor > 1)
- --cursor;
- return offset + cursor;
- } else {
- offset += components.at(i).string.length() - 1;
- }
- }
- }
- return run.length();
}
-static float cursorToX(const Vector<TextRunComponent, 1024>& components, int width, bool rtl, int cursor)
-{
- int start = 0;
- for (int i = 0; i < components.size(); ++i) {
- if (start + components.at(i).string.length() - 1 < cursor) {
- start += components.at(i).string.length() - 1;
- continue;
- }
- int xs = components.at(i).offset;
- if (rtl)
- xs = width - xs - components.at(i).width;
- QTextLayout layout(components.at(i).string, *components.at(i).font);
- layout.beginLayout();
- QTextLine l = layout.createLine();
- if (!l.isValid())
- return 0;
-
- l.setLineWidth(INT_MAX/256);
- layout.endLayout();
-
- return xs + l.cursorToX(cursor - start + 1);
- }
- return width;
-}
-
-FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& pt,
- int h, int from, int to) const
-{
- Vector<TextRunComponent, 1024> components;
- int w = generateComponents(&components, *this, run);
-
- if (from == 0 && to == run.length())
- return FloatRect(pt.x(), pt.y(), w, h);
-
- float x1 = cursorToX(components, w, run.rtl(), from);
- float x2 = cursorToX(components, w, run.rtl(), to);
- if (x2 < x1)
- qSwap(x1, x2);
-
- return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
-}
#endif
-
-Font::~Font()
-{
-}
-
-Font::Font(const Font& other)
- : m_fontDescription(other.m_fontDescription)
- , m_letterSpacing(other.m_letterSpacing)
- , m_wordSpacing(other.m_wordSpacing)
- , m_font(other.m_font)
- , m_scFont(other.m_scFont)
- , m_spaceWidth(other.m_spaceWidth)
-{
-}
-
-Font& Font::operator=(const Font& other)
-{
- m_fontDescription = other.m_fontDescription;
- m_letterSpacing = other.m_letterSpacing;
- m_wordSpacing = other.m_wordSpacing;
- m_font = other.m_font;
- m_scFont = other.m_scFont;
- m_spaceWidth = other.m_spaceWidth;
- return *this;
-}
-
-bool Font::operator==(const Font& other) const
-{
- return m_fontDescription == other.m_fontDescription
- && m_letterSpacing == other.m_letterSpacing
- && m_wordSpacing == other.m_wordSpacing
- && m_font == other.m_font
- && m_scFont == other.m_scFont
- && m_spaceWidth == other.m_spaceWidth;
-}
-
-void Font::update(PassRefPtr<FontSelector>) const
-{
- // don't think we need this
-}
-
-
-bool Font::isFixedPitch() const
-{
- return QFontInfo(m_font).fixedPitch();
-}
-
-// Metrics that we query the FontFallbackList for.
-int Font::ascent() const
-{
- return QFontMetrics(m_font).ascent();
-}
-
-int Font::descent() const
-{
- return QFontMetrics(m_font).descent();
-}
-
-int Font::lineSpacing() const
-{
- return QFontMetrics(m_font).lineSpacing();
-}
-
-int Font::lineGap() const
-{
- return QFontMetrics(m_font).leading();
-}
-
-float Font::xHeight() const
-{
- return QFontMetrics(m_font).xHeight();
-}
-
-unsigned Font::unitsPerEm() const
-{
- return 1; // FIXME!
-}
-
-int Font::spaceWidth() const
-{
- return m_spaceWidth;
-}
-
-}
diff --git a/WebCore/platform/graphics/qt/FontQt43.cpp b/WebCore/platform/graphics/qt/FontQt43.cpp
new file mode 100644
index 0000000..137b7c9
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FontQt43.cpp
@@ -0,0 +1,356 @@
+/*
+ Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2008 Holger Hans Peter Freyther
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "Font.h"
+#include "FontDescription.h"
+#include "FontFallbackList.h"
+#include "FontSelector.h"
+
+#include "GraphicsContext.h"
+#include <QTextLayout>
+#include <QPainter>
+#include <QFontMetrics>
+#include <QFontInfo>
+#include <qalgorithms.h>
+#include <qdebug.h>
+
+#include <limits.h>
+
+#if QT_VERSION < 0x040400
+
+namespace WebCore {
+
+struct TextRunComponent {
+ TextRunComponent() : font(0) {}
+ TextRunComponent(const UChar *start, int length, bool rtl, const QFont *font, int offset, bool sc = false);
+ TextRunComponent(int spaces, bool rtl, const QFont *font, int offset);
+
+ inline bool isSpace() const { return spaces != 0; }
+
+ QString string;
+ const QFont *font;
+ int width;
+ int offset;
+ int spaces;
+};
+
+TextRunComponent::TextRunComponent(const UChar *start, int length, bool rtl, const QFont *f, int o, bool sc)
+ : string(reinterpret_cast<const QChar*>(start), length)
+ , font(f)
+ , offset(o)
+ , spaces(0)
+{
+ if (sc)
+ string = string.toUpper();
+ string.prepend(rtl ? QChar(0x202e) : QChar(0x202d));
+ width = QFontMetrics(*font).width(string);
+}
+
+TextRunComponent::TextRunComponent(int s, bool rtl, const QFont *f, int o)
+ : string(s, QLatin1Char(' '))
+ , font(f)
+ , offset(o)
+ , spaces(s)
+{
+ string.prepend(rtl ? QChar(0x202e) : QChar(0x202d));
+ width = spaces * QFontMetrics(*font).width(QLatin1Char(' '));
+}
+
+
+static int generateComponents(Vector<TextRunComponent, 1024>* components, const Font &font, const TextRun &run)
+{
+// qDebug() << "generateComponents" << QString((const QChar *)run.characters(), run.length());
+ int letterSpacing = font.letterSpacing();
+ int wordSpacing = font.wordSpacing();
+ bool smallCaps = font.fontDescription().smallCaps();
+ int padding = run.padding();
+ int numSpaces = 0;
+ if (padding) {
+ for (int i = 0; i < run.length(); i++)
+ if (Font::treatAsSpace(run[i]))
+ ++numSpaces;
+ }
+
+ int offset = 0;
+ const QFont *f = &font.font();
+ if (letterSpacing || smallCaps) {
+ // need to draw every letter on it's own
+ int start = 0;
+ if (Font::treatAsSpace(run[0])) {
+ int add = 0;
+ if (numSpaces) {
+ add = padding/numSpaces;
+ padding -= add;
+ --numSpaces;
+ }
+ components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
+ offset += add + letterSpacing + components->last().width;
+ start = 1;
+// qDebug() << "space at 0" << offset;
+ } else if (smallCaps) {
+ f = (QChar::category(run[0]) == QChar::Letter_Lowercase ? &font.scFont() : &font.font());
+ }
+ for (int i = 1; i < run.length(); ++i) {
+ uint ch = run[i];
+ if (QChar(ch).isHighSurrogate() && QChar(run[i-1]).isLowSurrogate())
+ ch = QChar::surrogateToUcs4(ch, run[i-1]);
+ if (QChar(ch).isLowSurrogate() || QChar::category(ch) == QChar::Mark_NonSpacing)
+ continue;
+ if (Font::treatAsSpace(run[i])) {
+ int add = 0;
+// qDebug() << " treatAsSpace:" << i << start;
+ if (i - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, i - start,
+ run.rtl(),
+ f, offset, f == &font.scFont()));
+ offset += components->last().width + letterSpacing;
+// qDebug() << " appending(1) " << components->last().string << components->last().width;
+ }
+ if (numSpaces) {
+ add = padding/numSpaces;
+ padding -= add;
+ --numSpaces;
+ }
+ components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
+ offset += wordSpacing + add + components->last().width + letterSpacing;
+ start = i + 1;
+ continue;
+ } else if (!letterSpacing) {
+// qDebug() << i << char(run[i]) << (QChar::category(ch) == QChar::Letter_Lowercase) <<
+// QFontInfo(*f).pointSizeF();
+ if (QChar::category(ch) == QChar::Letter_Lowercase) {
+ if (f == &font.scFont())
+ continue;
+ } else {
+ if (f == &font.font())
+ continue;
+ }
+ }
+ if (i - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, i - start,
+ run.rtl(),
+ f, offset, f == &font.scFont()));
+ offset += components->last().width + letterSpacing;
+// qDebug() << " appending(2) " << components->last().string << components->last().width;
+ }
+ if (smallCaps)
+ f = (QChar::category(ch) == QChar::Letter_Lowercase ? &font.scFont() : &font.font());
+ start = i;
+ }
+ if (run.length() - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, run.length() - start,
+ run.rtl(),
+ f, offset, f == &font.scFont()));
+ offset += components->last().width;
+// qDebug() << " appending(3) " << components->last().string << components->last().width;
+ }
+ offset += letterSpacing;
+ } else {
+ int start = 0;
+ for (int i = 0; i < run.length(); ++i) {
+ if (Font::treatAsSpace(run[i])) {
+ if (i - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, i - start,
+ run.rtl(),
+ f, offset));
+ offset += components->last().width;
+ }
+ int add = 0;
+ if (numSpaces) {
+ add = padding/numSpaces;
+ padding -= add;
+ --numSpaces;
+ }
+ components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
+ offset += add + components->last().width;
+ if (i)
+ offset += wordSpacing;
+ start = i + 1;
+ }
+ }
+ if (run.length() - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, run.length() - start,
+ run.rtl(),
+ f, offset));
+ offset += components->last().width;
+ }
+ }
+ return offset;
+}
+
+void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ if (to < 0)
+ to = run.length();
+
+ QPainter *p = ctx->platformContext();
+ Color color = ctx->fillColor();
+ p->setPen(QColor(color));
+
+ Vector<TextRunComponent, 1024> components;
+ int w = generateComponents(&components, *this, run);
+
+ if (from > 0 || to < run.length()) {
+ FloatRect clip = selectionRectForComplexText(run,
+ IntPoint(qRound(point.x()), qRound(point.y())),
+ QFontMetrics(font()).height(), from, to);
+ QRectF rect(clip.x(), clip.y() - ascent(), clip.width(), clip.height());
+ p->save();
+ p->setClipRect(rect.toRect());
+ }
+
+ if (run.rtl()) {
+ for (int i = 0; i < components.size(); ++i) {
+ if (!components.at(i).isSpace()) {
+ p->setFont(*components.at(i).font);
+ QPointF pt(point.x() + w - components.at(i).offset - components.at(i).width, point.y());
+ p->drawText(pt, components.at(i).string);
+ }
+ }
+ } else {
+ for (int i = 0; i < components.size(); ++i) {
+ if (!components.at(i).isSpace()) {
+ p->setFont(*components.at(i).font);
+ QPointF pt(point.x() + components.at(i).offset, point.y());
+ p->drawText(pt, components.at(i).string);
+ }
+ }
+ }
+ if (from > 0 || to < run.length())
+ p->restore();
+}
+
+float Font::floatWidthForComplexText(const TextRun& run) const
+{
+ Vector<TextRunComponent, 1024> components;
+ int w = generateComponents(&components, *this, run);
+
+ return w;
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const
+{
+ Vector<TextRunComponent, 1024> components;
+ int w = generateComponents(&components, *this, run);
+
+ int offset = 0;
+ if (run.rtl()) {
+ for (int i = 0; i < components.size(); ++i) {
+ int xe = w - components.at(i).offset;
+ int xs = xe - components.at(i).width;
+ if (position >= xs) {
+ QTextLayout layout(components.at(i).string, *components.at(i).font);
+ layout.beginLayout();
+ QTextLine l = layout.createLine();
+ if (!l.isValid())
+ return offset;
+
+ l.setLineWidth(INT_MAX/256);
+ layout.endLayout();
+
+ if (position - xs >= l.width())
+ return offset;
+ int cursor = l.xToCursor(position - xs);
+ if (cursor > 1)
+ --cursor;
+ return offset + cursor;
+ } else {
+ offset += components.at(i).string.length() - 1;
+ }
+ }
+ } else {
+ for (int i = 0; i < components.size(); ++i) {
+ int xs = components.at(i).offset;
+ int xe = xs + components.at(i).width;
+ if (position <= xe) {
+ QTextLayout layout(components.at(i).string, *components.at(i).font);
+ layout.beginLayout();
+ QTextLine l = layout.createLine();
+ if (!l.isValid())
+ return offset;
+
+ l.setLineWidth(INT_MAX/256);
+ layout.endLayout();
+
+ if (position - xs >= l.width())
+ return offset + components.at(i).string.length() - 1;
+ int cursor = l.xToCursor(position - xs);
+ if (cursor > 1)
+ --cursor;
+ return offset + cursor;
+ } else {
+ offset += components.at(i).string.length() - 1;
+ }
+ }
+ }
+ return run.length();
+}
+
+static float cursorToX(const Vector<TextRunComponent, 1024>& components, int width, bool rtl, int cursor)
+{
+ int start = 0;
+ for (int i = 0; i < components.size(); ++i) {
+ if (start + components.at(i).string.length() - 1 < cursor) {
+ start += components.at(i).string.length() - 1;
+ continue;
+ }
+ int xs = components.at(i).offset;
+ if (rtl)
+ xs = width - xs - components.at(i).width;
+ QTextLayout layout(components.at(i).string, *components.at(i).font);
+ layout.beginLayout();
+ QTextLine l = layout.createLine();
+ if (!l.isValid())
+ return 0;
+
+ l.setLineWidth(INT_MAX/256);
+ layout.endLayout();
+
+ return xs + l.cursorToX(cursor - start + 1);
+ }
+ return width;
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt,
+ int h, int from, int to) const
+{
+ Vector<TextRunComponent, 1024> components;
+ int w = generateComponents(&components, *this, run);
+
+ if (from == 0 && to == run.length())
+ return FloatRect(pt.x(), pt.y(), w, h);
+
+ float x1 = cursorToX(components, w, run.rtl(), from);
+ float x2 = cursorToX(components, w, run.rtl(), to);
+ if (x2 < x1)
+ qSwap(x1, x2);
+
+ return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
+}
+
+int Font::lineGap() const
+{
+ return QFontMetrics(m_font).leading();
+}
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/qt/GlyphPageTreeNodeQt.cpp b/WebCore/platform/graphics/qt/GlyphPageTreeNodeQt.cpp
index d32cc63..2121206 100644
--- a/WebCore/platform/graphics/qt/GlyphPageTreeNodeQt.cpp
+++ b/WebCore/platform/graphics/qt/GlyphPageTreeNodeQt.cpp
@@ -1,5 +1,6 @@
/*
Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2008 Holger Hans Peter Freyther
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -24,7 +25,11 @@
namespace WebCore {
-void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData* fontData)
+void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData*)
+{
+}
+
+void GlyphPageTreeNode::pruneTreeFontData(const WebCore::SimpleFontData*)
{
}
diff --git a/WebCore/platform/graphics/qt/GradientQt.cpp b/WebCore/platform/graphics/qt/GradientQt.cpp
index f414efa..a0edf8d 100644
--- a/WebCore/platform/graphics/qt/GradientQt.cpp
+++ b/WebCore/platform/graphics/qt/GradientQt.cpp
@@ -52,7 +52,7 @@ QGradient* Gradient::platformGradient()
QColor stopColor;
Vector<ColorStop>::iterator stopIterator = m_stops.begin();
- qreal lastStop;
+ qreal lastStop(0.0);
const qreal lastStopDiff = 0.0000001;
while (stopIterator != m_stops.end()) {
stopColor.setRgbF(stopIterator->red, stopIterator->green, stopIterator->blue, stopIterator->alpha);
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index 600d77c..2e7cdcb 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -39,7 +39,7 @@
#include <windows.h>
#endif
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "Color.h"
#include "FloatConversion.h"
#include "Font.h"
@@ -280,7 +280,7 @@ PlatformGraphicsContext* GraphicsContext::platformContext() const
return m_data->p();
}
-AffineTransform GraphicsContext::getCTM() const
+TransformationMatrix GraphicsContext::getCTM() const
{
return platformContext()->combinedMatrix();
}
@@ -293,6 +293,11 @@ void GraphicsContext::savePlatformState()
void GraphicsContext::restorePlatformState()
{
m_data->p()->restore();
+
+ if (!m_data->currentPath.isEmpty() && m_common->state.pathTransform.isInvertible()) {
+ QMatrix matrix = m_common->state.pathTransform;
+ m_data->currentPath = m_data->currentPath * matrix;
+ }
}
/* FIXME: DISABLED WHILE MERGING BACK FROM UNITY
@@ -520,6 +525,15 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
p->restore();
}
+QPen GraphicsContext::pen()
+{
+ if (paintingDisabled())
+ return QPen();
+
+ QPainter *p = m_data->p();
+ return p->pen();
+}
+
void GraphicsContext::fillPath()
{
if (paintingDisabled())
@@ -533,15 +547,18 @@ void GraphicsContext::fillPath()
if (fillColor().alpha())
p->fillPath(path, p->brush());
break;
- case PatternColorSpace:
- p->fillPath(path, QBrush(m_common->state.fillPattern.get()->createPlatformPattern(getCTM())));
+ case PatternColorSpace: {
+ TransformationMatrix affine;
+ p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
break;
+ }
case GradientColorSpace:
- QGradient* gradient = m_common->state.fillGradient.get()->platformGradient();
+ QGradient* gradient = m_common->state.fillGradient->platformGradient();
*gradient = applySpreadMethod(*gradient, spreadMethod());
p->fillPath(path, QBrush(*gradient));
break;
}
+ m_data->currentPath = QPainterPath();
}
void GraphicsContext::strokePath()
@@ -559,13 +576,14 @@ void GraphicsContext::strokePath()
p->strokePath(path, pen);
break;
case PatternColorSpace: {
- pen.setBrush(QBrush(m_common->state.strokePattern.get()->createPlatformPattern(getCTM())));
+ TransformationMatrix affine;
+ pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine)));
p->setPen(pen);
p->strokePath(path, pen);
break;
}
case GradientColorSpace: {
- QGradient* gradient = m_common->state.strokeGradient.get()->platformGradient();
+ QGradient* gradient = m_common->state.strokeGradient->platformGradient();
*gradient = applySpreadMethod(*gradient, spreadMethod());
pen.setBrush(QBrush(*gradient));
p->setPen(pen);
@@ -573,6 +591,7 @@ void GraphicsContext::strokePath()
break;
}
}
+ m_data->currentPath = QPainterPath();
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -587,13 +606,16 @@ void GraphicsContext::fillRect(const FloatRect& rect)
if (fillColor().alpha())
p->fillRect(rect, p->brush());
break;
- case PatternColorSpace:
- p->fillRect(rect, QBrush(m_common->state.fillPattern.get()->createPlatformPattern(getCTM())));
+ case PatternColorSpace: {
+ TransformationMatrix affine;
+ p->fillRect(rect, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
break;
+ }
case GradientColorSpace:
p->fillRect(rect, QBrush(*(m_common->state.fillGradient.get()->platformGradient())));
break;
}
+ m_data->currentPath = QPainterPath();
}
void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
@@ -621,7 +643,9 @@ void GraphicsContext::beginPath()
void GraphicsContext::addPath(const Path& path)
{
- m_data->currentPath = *(path.platformPath());
+ QPainterPath newPath = m_data->currentPath;
+ newPath.addPath(*(path.platformPath()));
+ m_data->currentPath = newPath;
}
bool GraphicsContext::inTransparencyLayer() const
@@ -645,6 +669,17 @@ void GraphicsContext::clip(const FloatRect& rect)
else p->setClipRect(rect, Qt::IntersectClip);
}
+void GraphicsContext::clipPath(WindRule clipRule)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QPainterPath newPath = m_data->currentPath;
+ newPath.setFillRule(clipRule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
+ p->setClipPath(newPath);
+}
+
/**
* Focus ring handling is not handled here. Qt style in
* RenderTheme handles drawing focus on widgets which
@@ -823,8 +858,9 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
if (dashLength % 2)
count *= 2;
+ float penWidth = narrowPrecisionToFloat(double(pen.widthF()));
for (unsigned i = 0; i < count; i++)
- pattern.append(dashes[i % dashLength] / narrowPrecisionToFloat(pen.widthF()));
+ pattern.append(dashes[i % dashLength] / penWidth);
pen.setDashPattern(pattern);
pen.setDashOffset(dashOffset);
@@ -901,6 +937,12 @@ void GraphicsContext::translate(float x, float y)
return;
m_data->p()->translate(x, y);
+
+ if (!m_data->currentPath.isEmpty()) {
+ QMatrix matrix;
+ m_data->currentPath = m_data->currentPath * matrix.translate(-x, -y);
+ m_common->state.pathTransform.translate(x, y);
+ }
}
IntPoint GraphicsContext::origin()
@@ -917,6 +959,12 @@ void GraphicsContext::rotate(float radians)
return;
m_data->p()->rotate(180/M_PI*radians);
+
+ if (!m_data->currentPath.isEmpty()) {
+ QMatrix matrix;
+ m_data->currentPath = m_data->currentPath * matrix.rotate(-180/M_PI*radians);
+ m_common->state.pathTransform.rotate(radians);
+ }
}
void GraphicsContext::scale(const FloatSize& s)
@@ -925,6 +973,12 @@ void GraphicsContext::scale(const FloatSize& s)
return;
m_data->p()->scale(s.width(), s.height());
+
+ if (!m_data->currentPath.isEmpty()) {
+ QMatrix matrix;
+ m_data->currentPath = m_data->currentPath * matrix.scale(1 / s.width(), 1 / s.height());
+ m_common->state.pathTransform.scale(s.width(), s.height());
+ }
}
void GraphicsContext::clipOut(const IntRect& rect)
@@ -982,12 +1036,20 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
m_data->p()->setClipPath(path, Qt::IntersectClip);
}
-void GraphicsContext::concatCTM(const AffineTransform& transform)
+void GraphicsContext::concatCTM(const TransformationMatrix& transform)
{
if (paintingDisabled())
return;
m_data->p()->setMatrix(transform, true);
+
+ // Transformations to the context shouldn't transform the currentPath.
+ // We have to undo every change made to the context from the currentPath to avoid wrong drawings.
+ if (!m_data->currentPath.isEmpty() && transform.isInvertible()) {
+ QMatrix matrix = transform.inverse();
+ m_data->currentPath = m_data->currentPath * matrix;
+ m_common->state.pathTransform.multiply(transform);
+ }
}
void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
@@ -995,13 +1057,6 @@ void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
notImplemented();
}
-void GraphicsContext::setPlatformFont(const Font& aFont)
-{
- if (paintingDisabled())
- return;
- m_data->p()->setFont(aFont.font());
-}
-
void GraphicsContext::setPlatformStrokeColor(const Color& color)
{
if (paintingDisabled())
@@ -1039,7 +1094,7 @@ void GraphicsContext::setPlatformFillColor(const Color& color)
m_data->p()->setBrush(QBrush(color));
}
-void GraphicsContext::setUseAntialiasing(bool enable)
+void GraphicsContext::setPlatformShouldAntialias(bool enable)
{
if (paintingDisabled())
return;
@@ -1051,8 +1106,8 @@ void GraphicsContext::setUseAntialiasing(bool enable)
HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
- // painting through native HDC is only supported for plugin, where mayCreateBitmap is always TRUE
- Q_ASSERT(mayCreateBitmap == TRUE);
+ // painting through native HDC is only supported for plugin, where mayCreateBitmap is always true
+ Q_ASSERT(mayCreateBitmap);
if (dstRect.isEmpty())
return 0;
@@ -1090,6 +1145,7 @@ HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlpha
memset(bmpInfo.bmBits, 0, bufferSize);
}
+#if !PLATFORM(WIN_CE)
// Make sure we can do world transforms.
SetGraphicsMode(bitmapDC, GM_ADVANCED);
@@ -1102,15 +1158,15 @@ HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlpha
xform.eDx = -dstRect.x();
xform.eDy = -dstRect.y();
::SetWorldTransform(bitmapDC, &xform);
-
+#endif
return bitmapDC;
}
void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
- // painting through native HDC is only supported for plugin, where mayCreateBitmap is always TRUE
- Q_ASSERT(mayCreateBitmap == TRUE);
+ // painting through native HDC is only supported for plugin, where mayCreateBitmap is always true
+ Q_ASSERT(mayCreateBitmap);
if (hdc) {
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index e3b00a1..394c7a7 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -178,9 +178,26 @@ ImageDecoderQt::ReadContext::IncrementalReadResult
return IncrementalReadComplete;
}
+ImageDecoderQt* ImageDecoderQt::create(const SharedBuffer& data)
+{
+ // We need at least 4 bytes to figure out what kind of image we're dealing with.
+ if (data.size() < 4)
+ return 0;
+
+ QByteArray bytes = QByteArray::fromRawData(data.data(), data.size());
+ QBuffer buffer(&bytes);
+ if (!buffer.open(QBuffer::ReadOnly))
+ return 0;
+
+ QString imageFormat = QString::fromLatin1(QImageReader::imageFormat(&buffer).toLower());
+ if (imageFormat.isEmpty())
+ return 0; // Image format not supported
+
+ return new ImageDecoderQt(imageFormat);
+}
-// ImageDecoderQt
-ImageDecoderQt::ImageDecoderQt( )
+ImageDecoderQt::ImageDecoderQt(const QString &imageFormat)
+ : m_imageFormat(imageFormat)
{
}
@@ -254,7 +271,6 @@ int ImageDecoderQt::frameCount() const
return m_imageList.size();
}
-
int ImageDecoderQt::repetitionCount() const
{
if (debugImageDecoderQt)
@@ -262,7 +278,6 @@ int ImageDecoderQt::repetitionCount() const
return m_loopCount;
}
-
bool ImageDecoderQt::supportsAlpha() const
{
return hasFirstImageHeader() && m_imageList[0].m_image.hasAlphaChannel();
@@ -275,6 +290,13 @@ int ImageDecoderQt::duration(size_t index) const
return m_imageList[index].m_duration;
}
+String ImageDecoderQt::filenameExtension() const
+{
+ if (debugImageDecoderQt)
+ qDebug() << " ImageDecoderQt::filenameExtension() returns" << m_imageFormat;
+ return m_imageFormat;
+};
+
RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
{
Q_ASSERT("use imageAtIndex instead");
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
index 3573dd0..a2eb6aa 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.h
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -38,34 +38,30 @@ namespace WebCore {
class ImageDecoderQt : public ImageDecoder
{
- ImageDecoderQt(const ImageDecoderQt&);
- ImageDecoderQt &operator=(const ImageDecoderQt&);
public:
- ImageDecoderQt();
+ static ImageDecoderQt* create(const SharedBuffer& data);
~ImageDecoderQt();
typedef Vector<char> IncomingData;
virtual void setData(const IncomingData& data, bool allDataReceived);
-
virtual bool isSizeAvailable() const;
-
virtual int frameCount() const;
-
-
virtual int repetitionCount() const;
-
-
virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
QPixmap* imageAtIndex(size_t index) const;
-
virtual bool supportsAlpha() const;
-
int duration(size_t index) const;
+ virtual String filenameExtension() const;
void clearFrame(size_t index);
+
private:
+ ImageDecoderQt(const QString &imageFormat);
+ ImageDecoderQt(const ImageDecoderQt&);
+ ImageDecoderQt &operator=(const ImageDecoderQt&);
+
class ReadContext;
void reset();
bool hasFirstImageHeader() const;
@@ -89,6 +85,7 @@ private:
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 9234c69..99062f9 100644
--- a/WebCore/platform/graphics/qt/ImageQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageQt.cpp
@@ -34,7 +34,7 @@
#include "FloatRect.h"
#include "PlatformString.h"
#include "GraphicsContext.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "NotImplemented.h"
#include "StillImageQt.h"
#include "qwebsettings.h"
@@ -69,14 +69,16 @@ static QPixmap loadResourcePixmap(const char *name)
namespace WebCore {
-void FrameData::clear()
+bool FrameData::clear(bool clearMetadata)
{
+ if (clearMetadata)
+ m_haveMetadata = false;
+
if (m_frame) {
m_frame = 0;
- // NOTE: We purposefully don't reset metadata here, so that even if we
- // throw away previously-decoded data, animation loops can still access
- // properties like frame durations without re-decoding.
+ return true;
}
+ return false;
}
@@ -91,7 +93,7 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name)
}
-void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
+void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
{
notImplemented();
@@ -136,7 +138,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
ctxt->restore();
}
-void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
+void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
{
QPixmap* framePixmap = nativeImageForCurrentFrame();
diff --git a/WebCore/platform/graphics/qt/ImageSourceQt.cpp b/WebCore/platform/graphics/qt/ImageSourceQt.cpp
index 1d14f9d..d62acc3 100644
--- a/WebCore/platform/graphics/qt/ImageSourceQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageSourceQt.cpp
@@ -29,6 +29,7 @@
#include "config.h"
#include "ImageSource.h"
#include "ImageDecoderQt.h"
+#include "NotImplemented.h"
#include "SharedBuffer.h"
#include <QBuffer>
@@ -36,25 +37,6 @@
#include <QImageReader>
namespace WebCore {
-static bool canHandleImage(const SharedBuffer& _data)
-{
- // We need at least 4 bytes to figure out what kind of image we're dealing with.
- if (_data.size() < 4)
- return false;
-
- QByteArray data = QByteArray::fromRawData(_data.data(), _data.size());
- QBuffer buffer(&data);
- if (!buffer.open(QBuffer::ReadOnly))
- return false;
-
- return !QImageReader::imageFormat(&buffer).isEmpty();
-}
-
-ImageDecoderQt* createDecoder(const SharedBuffer& data) {
- if (!canHandleImage(data))
- return 0;
- return new ImageDecoderQt();
-}
ImageSource::ImageSource()
: m_decoder(0)
@@ -63,7 +45,7 @@ ImageSource::ImageSource()
ImageSource::~ImageSource()
{
- delete m_decoder;
+ clear(true);
}
bool ImageSource::initialized() const
@@ -78,7 +60,7 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
// If insufficient bytes are available to determine the image type, no decoder plugin will be
// made.
if (!m_decoder)
- m_decoder = createDecoder(*data);
+ m_decoder = ImageDecoderQt::create(*data);
if (!m_decoder)
return;
@@ -86,6 +68,14 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
m_decoder->setData(data->buffer(), allDataReceived);
}
+String ImageSource::filenameExtension() const
+{
+ if (!m_decoder)
+ return String();
+
+ return m_decoder->filenameExtension();
+}
+
bool ImageSource::isSizeAvailable()
{
if (!m_decoder)
@@ -162,13 +152,20 @@ bool ImageSource::frameIsCompleteAtIndex(size_t index)
return (m_decoder && m_decoder->imageAtIndex(index) != 0);
}
-void ImageSource::clear()
+void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
{
- delete m_decoder;
+ if (!destroyAll) {
+ if (m_decoder)
+ m_decoder->clearFrameBufferCache(clearBeforeFrame);
+ return;
+ }
+
+ delete m_decoder;
m_decoder = 0;
+ if (data)
+ setData(data, allDataReceived);
}
-
}
// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
index 431e68e..b1a48fb 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
@@ -84,6 +84,9 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
{
// Hint to Phonon to disable overlay painting
m_videoWidget->setAttribute(Qt::WA_DontShowOnScreen);
+#if QT_VERSION < 0x040500
+ m_videoWidget->setAttribute(Qt::WA_QuitOnClose, false);
+#endif
createPath(m_mediaObject, m_videoWidget);
createPath(m_mediaObject, m_audioOutput);
@@ -96,7 +99,6 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
this, SLOT(stateChanged(Phonon::State, Phonon::State)));
- connect(m_mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
connect(m_mediaObject, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged()));
connect(m_mediaObject, SIGNAL(seekableChanged(bool)), this, SLOT(seekableChanged(bool)));
connect(m_mediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(hasVideoChanged(bool)));
@@ -105,7 +107,6 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
connect(m_mediaObject, SIGNAL(currentSourceChanged(const Phonon::MediaSource&)),
this, SLOT(currentSourceChanged(const Phonon::MediaSource&)));
connect(m_mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
- connect(m_mediaObject, SIGNAL(prefinishMarkReached(qint32)), this, SLOT(prefinishMarkReached(qint32)));
connect(m_mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64)));
}
@@ -314,7 +315,7 @@ void MediaPlayerPrivate::updateStates()
m_mediaObject->pause();
}
} else if (phononState == Phonon::PausedState) {
- m_networkState = MediaPlayer::LoadedFirstFrame;
+ m_networkState = MediaPlayer::Loaded;
m_readyState = MediaPlayer::CanPlayThrough;
} else if (phononState == Phonon::ErrorState) {
if (!m_mediaObject || m_mediaObject->errorType() == Phonon::FatalError) {
@@ -371,42 +372,6 @@ void MediaPlayerPrivate::setRect(const IntRect& newRect)
m_videoWidget->resize(newRect.width(), newRect.height());
}
-
-void MediaPlayerPrivate::loadStateChanged()
-{
- notImplemented();
-}
-
-void MediaPlayerPrivate::rateChanged()
-{
- notImplemented();
-}
-
-void MediaPlayerPrivate::sizeChanged()
-{
- notImplemented();
-}
-
-void MediaPlayerPrivate::timeChanged()
-{
- notImplemented();
-}
-
-void MediaPlayerPrivate::volumeChanged()
-{
- notImplemented();
-}
-
-void MediaPlayerPrivate::didEnd()
-{
- notImplemented();
-}
-
-void MediaPlayerPrivate::loadingFailed()
-{
- notImplemented();
-}
-
IntSize MediaPlayerPrivate::naturalSize() const
{
if (!hasVideo()) {
@@ -430,17 +395,12 @@ IntSize MediaPlayerPrivate::naturalSize() const
bool MediaPlayerPrivate::eventFilter(QObject* obj, QEvent* event)
{
- if (event->type() == QEvent::Paint)
+ if (event->type() == QEvent::UpdateRequest)
m_player->repaint();
return QObject::eventFilter(obj, event);
}
-void MediaPlayerPrivate::repaint()
-{
- m_player->repaint();
-}
-
void MediaPlayerPrivate::paint(GraphicsContext* graphicsContect, const IntRect& rect)
{
if (graphicsContect->paintingDisabled())
@@ -469,12 +429,6 @@ void MediaPlayerPrivate::stateChanged(Phonon::State newState, Phonon::State oldS
updateStates();
}
-void MediaPlayerPrivate::tick(qint64)
-{
- updateStates();
- m_player->timeChanged();
-}
-
void MediaPlayerPrivate::metaDataChanged()
{
LOG(Media, "MediaPlayerPrivatePhonon::metaDataChanged()");
@@ -516,12 +470,6 @@ void MediaPlayerPrivate::aboutToFinish()
LOG_MEDIAOBJECT();
}
-void MediaPlayerPrivate::prefinishMarkReached(qint32)
-{
- notImplemented();
- LOG_MEDIAOBJECT();
-}
-
void MediaPlayerPrivate::totalTimeChanged(qint64 totalTime)
{
LOG(Media, "MediaPlayerPrivatePhonon::totalTimeChanged(%d)", totalTime);
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
index 5eb2a09..1b20a84 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
@@ -111,15 +111,6 @@ namespace WebCore {
void setVisible(bool);
void setRect(const IntRect&);
- void loadStateChanged();
- void rateChanged();
- void sizeChanged();
- void timeChanged();
- void volumeChanged();
- void didEnd();
- void loadingFailed();
-
- void repaint();
void paint(GraphicsContext*, const IntRect&);
static void getSupportedTypes(HashSet<String>&);
static bool isAvailable() { return true; }
@@ -129,7 +120,6 @@ namespace WebCore {
private slots:
void stateChanged(Phonon::State, Phonon::State);
- void tick(qint64);
void metaDataChanged();
void seekableChanged(bool);
void hasVideoChanged(bool);
@@ -137,7 +127,6 @@ namespace WebCore {
void finished();
void currentSourceChanged(const Phonon::MediaSource&);
void aboutToFinish();
- void prefinishMarkReached(qint32);
void totalTimeChanged(qint64);
private:
diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp
index 76f375c..bd0192c 100644
--- a/WebCore/platform/graphics/qt/PathQt.cpp
+++ b/WebCore/platform/graphics/qt/PathQt.cpp
@@ -29,9 +29,12 @@
#include "config.h"
#include "Path.h"
+#include "TransformationMatrix.h"
#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
#include "PlatformString.h"
-#include "AffineTransform.h"
+#include "StrokeStyleApplier.h"
#include <QPainterPath>
#include <QMatrix>
#include <QString>
@@ -39,6 +42,10 @@
#define _USE_MATH_DEFINES
#include <math.h>
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
namespace WebCore {
Path::Path()
@@ -77,6 +84,28 @@ bool Path::contains(const FloatPoint& point, WindRule rule) const
return contains;
}
+bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
+{
+ ASSERT(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);
+ GraphicsContext* gc = scratchImage->context();
+ QPainterPathStroker stroke;
+ applier->strokeStyle(gc);
+
+ QPen pen = gc->pen();
+ stroke.setWidth(pen.widthF());
+ stroke.setCapStyle(pen.capStyle());
+ stroke.setJoinStyle(pen.joinStyle());
+ stroke.setMiterLimit(pen.miterLimit());
+ stroke.setDashPattern(pen.dashPattern());
+ stroke.setDashOffset(pen.dashOffset());
+
+ return (stroke.createStroke(*platformPath())).contains(point);
+}
+
void Path::translate(const FloatSize& size)
{
QMatrix matrix;
@@ -89,6 +118,27 @@ FloatRect Path::boundingRect() const
return m_path->boundingRect();
}
+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);
+ GraphicsContext* gc = scratchImage->context();
+ QPainterPathStroker stroke;
+ if (applier) {
+ applier->strokeStyle(gc);
+
+ QPen pen = gc->pen();
+ stroke.setWidth(pen.widthF());
+ stroke.setCapStyle(pen.capStyle());
+ stroke.setJoinStyle(pen.joinStyle());
+ stroke.setMiterLimit(pen.miterLimit());
+ stroke.setDashPattern(pen.dashPattern());
+ stroke.setDashOffset(pen.dashOffset());
+ }
+ return (stroke.createStroke(*platformPath())).boundingRect();
+}
+
void Path::moveTo(const FloatPoint& point)
{
m_path->moveTo(point);
@@ -263,7 +313,7 @@ void Path::apply(void* info, PathApplierFunction function) const
}
}
-void Path::transform(const AffineTransform& transform)
+void Path::transform(const TransformationMatrix& transform)
{
if (m_path) {
QMatrix mat = transform;
diff --git a/WebCore/platform/graphics/qt/PatternQt.cpp b/WebCore/platform/graphics/qt/PatternQt.cpp
index 883a258..5b76841 100644
--- a/WebCore/platform/graphics/qt/PatternQt.cpp
+++ b/WebCore/platform/graphics/qt/PatternQt.cpp
@@ -26,12 +26,12 @@
#include "config.h"
#include "Pattern.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "GraphicsContext.h"
namespace WebCore {
-QBrush Pattern::createPlatformPattern(const AffineTransform& transform) const
+QBrush Pattern::createPlatformPattern(const TransformationMatrix& transform) const
{
QPixmap* pixmap = tileImage()->nativeImageForCurrentFrame();
if (!pixmap)
diff --git a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
index 1ffce33..6cf4e55 100644
--- a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
+++ b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
@@ -1,5 +1,6 @@
/*
Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2008 Holger Hans Peter Freyther
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -19,37 +20,47 @@
This class provides all functionality needed for loading images, style sheets and html
pages from the web. It has a memory cache for these objects.
*/
+
#include "config.h"
#include "SimpleFontData.h"
-#include "SVGFontData.h"
+#include <QFontMetrics>
namespace WebCore {
-SimpleFontData::SimpleFontData(const FontPlatformData& font, bool customFont, bool loading, SVGFontData*)
- : m_font(font)
- , m_isCustomFont(customFont)
- , m_isLoading(loading)
+void SimpleFontData::determinePitch()
{
+ m_treatAsFixedPitch = m_font.font().fixedPitch();
}
-SimpleFontData::~SimpleFontData()
+bool SimpleFontData::containsCharacters(const UChar*, int length) const
{
+ return true;
}
-bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+void SimpleFontData::platformInit()
{
- return true;
+ QFontMetrics fm(m_font.font());
+
+ m_ascent = fm.ascent();
+ m_descent = fm.descent();
+ m_lineSpacing = fm.lineSpacing();
+ m_xHeight = fm.xHeight();
+ m_spaceWidth = fm.width(QLatin1Char(' '));
+ m_lineGap = fm.leading();
}
-const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
+void SimpleFontData::platformGlyphInit()
{
- return this;
+ m_spaceGlyph = 0;
+ m_adjustedSpaceWidth = m_spaceWidth;
+ determinePitch();
+ m_missingGlyphData.fontData = this;
+ m_missingGlyphData.glyph = 0;
}
-bool SimpleFontData::isSegmented() const
+void SimpleFontData::platformDestroy()
{
- return false;
}
}
diff --git a/WebCore/platform/graphics/qt/StillImageQt.h b/WebCore/platform/graphics/qt/StillImageQt.h
index 37b8b2c..2b2c1f7 100644
--- a/WebCore/platform/graphics/qt/StillImageQt.h
+++ b/WebCore/platform/graphics/qt/StillImageQt.h
@@ -41,7 +41,7 @@ namespace WebCore {
// FIXME: StillImages are underreporting decoded sizes and will be unable
// to prune because these functions are not implemented yet.
- virtual void destroyDecodedData(bool incremental = false, bool preserveNearbyFrames = false) { }
+ virtual void destroyDecodedData(bool destroyAll = true) { }
virtual unsigned decodedSize() const { return 0; }
virtual IntSize size() const;
diff --git a/WebCore/platform/graphics/qt/AffineTransformQt.cpp b/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp
index 2793043..47abd17 100644
--- a/WebCore/platform/graphics/qt/AffineTransformQt.cpp
+++ b/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp
@@ -24,34 +24,34 @@
*/
#include "config.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "IntRect.h"
#include "FloatRect.h"
namespace WebCore {
-AffineTransform::AffineTransform()
+TransformationMatrix::TransformationMatrix()
: m_transform()
{
}
-AffineTransform::AffineTransform(double a, double b, double c, double d, double tx, double ty)
+TransformationMatrix::TransformationMatrix(double a, double b, double c, double d, double tx, double ty)
: m_transform(a, b, c, d, tx, ty)
{
}
-AffineTransform::AffineTransform(const PlatformAffineTransform& matrix)
+TransformationMatrix::TransformationMatrix(const PlatformTransformationMatrix& matrix)
: m_transform(matrix)
{
}
-void AffineTransform::setMatrix(double a, double b, double c, double d, double tx, double ty)
+void TransformationMatrix::setMatrix(double a, double b, double c, double d, double tx, double ty)
{
m_transform.setMatrix(a, b, c, d, tx, ty);
}
-void AffineTransform::map(double x, double y, double* x2, double* y2) const
+void TransformationMatrix::map(double x, double y, double* x2, double* y2) const
{
qreal tx2, ty2;
m_transform.map(qreal(x), qreal(y), &tx2, &ty2);
@@ -59,140 +59,140 @@ void AffineTransform::map(double x, double y, double* x2, double* y2) const
*y2 = ty2;
}
-IntRect AffineTransform::mapRect(const IntRect& rect) const
+IntRect TransformationMatrix::mapRect(const IntRect& rect) const
{
return m_transform.mapRect(rect);
}
-FloatRect AffineTransform::mapRect(const FloatRect& rect) const
+FloatRect TransformationMatrix::mapRect(const FloatRect& rect) const
{
return m_transform.mapRect(rect);
}
-bool AffineTransform::isIdentity() const
+bool TransformationMatrix::isIdentity() const
{
return m_transform.isIdentity();
}
-double AffineTransform::a() const
+double TransformationMatrix::a() const
{
return m_transform.m11();
}
-void AffineTransform::setA(double a)
+void TransformationMatrix::setA(double a)
{
m_transform.setMatrix(a, b(), c(), d(), e(), f());
}
-double AffineTransform::b() const
+double TransformationMatrix::b() const
{
return m_transform.m12();
}
-void AffineTransform::setB(double b)
+void TransformationMatrix::setB(double b)
{
m_transform.setMatrix(a(), b, c(), d(), e(), f());
}
-double AffineTransform::c() const
+double TransformationMatrix::c() const
{
return m_transform.m21();
}
-void AffineTransform::setC(double c)
+void TransformationMatrix::setC(double c)
{
m_transform.setMatrix(a(), b(), c, d(), e(), f());
}
-double AffineTransform::d() const
+double TransformationMatrix::d() const
{
return m_transform.m22();
}
-void AffineTransform::setD(double d)
+void TransformationMatrix::setD(double d)
{
m_transform.setMatrix(a(), b(), c(), d, e(), f());
}
-double AffineTransform::e() const
+double TransformationMatrix::e() const
{
return m_transform.dx();
}
-void AffineTransform::setE(double e)
+void TransformationMatrix::setE(double e)
{
m_transform.setMatrix(a(), b(), c(), d(), e, f());
}
-double AffineTransform::f() const
+double TransformationMatrix::f() const
{
return m_transform.dy();
}
-void AffineTransform::setF(double f)
+void TransformationMatrix::setF(double f)
{
m_transform.setMatrix(a(), b(), c(), d(), e(), f);
}
-void AffineTransform::reset()
+void TransformationMatrix::reset()
{
m_transform.reset();
}
-AffineTransform& AffineTransform::scale(double sx, double sy)
+TransformationMatrix& TransformationMatrix::scale(double sx, double sy)
{
m_transform.scale(sx, sy);
return *this;
}
-AffineTransform& AffineTransform::rotate(double d)
+TransformationMatrix& TransformationMatrix::rotate(double d)
{
m_transform.rotate(d);
return *this;
}
-AffineTransform& AffineTransform::translate(double tx, double ty)
+TransformationMatrix& TransformationMatrix::translate(double tx, double ty)
{
m_transform.translate(tx, ty);
return *this;
}
-AffineTransform& AffineTransform::shear(double sx, double sy)
+TransformationMatrix& TransformationMatrix::shear(double sx, double sy)
{
m_transform.shear(sx, sy);
return *this;
}
-double AffineTransform::det() const
+double TransformationMatrix::det() const
{
return m_transform.det();
}
-AffineTransform AffineTransform::inverse() const
+TransformationMatrix TransformationMatrix::inverse() const
{
if(!isInvertible())
- return AffineTransform();
+ return TransformationMatrix();
return m_transform.inverted();
}
-AffineTransform::operator QMatrix() const
+TransformationMatrix::operator QMatrix() const
{
return m_transform;
}
-bool AffineTransform::operator==(const AffineTransform& other) const
+bool TransformationMatrix::operator==(const TransformationMatrix& other) const
{
return m_transform == other.m_transform;
}
-AffineTransform& AffineTransform::operator*=(const AffineTransform& other)
+TransformationMatrix& TransformationMatrix::operator*=(const TransformationMatrix& other)
{
m_transform *= other.m_transform;
return *this;
}
-AffineTransform AffineTransform::operator*(const AffineTransform& other)
+TransformationMatrix TransformationMatrix::operator*(const TransformationMatrix& other)
{
return m_transform * other.m_transform;
}
diff --git a/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h b/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
new file mode 100644
index 0000000..5d85652
--- /dev/null
+++ b/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2006,2007,2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BitmapImageSingleFrameSkia_h
+#define BitmapImageSingleFrameSkia_h
+
+#include "Image.h"
+#include "NativeImageSkia.h"
+
+namespace WebCore {
+
+// This image class can be used in places which need an Image, but have
+// raw pixel data rather than undecoded image data.
+// The Image is simpler than a BitmapImage, as it does not have image
+// observers, animation, multiple frames, or non-decoded data.
+// Therefore trimming the decoded data (destroyDecodedData()) has no effect.
+//
+// The difficulty with putting this in BitmapImage::create(NativeImagePtr)
+// is that NativeImagePtr = NativeImageSkia, yet callers have SkBitmap.
+class BitmapImageSingleFrameSkia : public Image {
+public:
+ // Creates a new Image, by copying the pixel values out of |bitmap|.
+ // If creation failed, returns null.
+ static PassRefPtr<BitmapImageSingleFrameSkia> create(const SkBitmap&);
+
+ virtual bool isBitmapImage() const { return true; }
+
+ virtual IntSize size() const
+ {
+ return IntSize(m_nativeImage.width(), m_nativeImage.height());
+ }
+
+ // Do nothing, as we only have the one representation of data (decoded).
+ virtual void destroyDecodedData(bool destroyAll = true) { }
+
+ virtual unsigned decodedSize() const
+ {
+ return m_nativeImage.decodedSize();
+ }
+
+ // We only have a single frame.
+ virtual NativeImagePtr nativeImageForCurrentFrame()
+ {
+ return &m_nativeImage;
+ }
+
+protected:
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+
+private:
+ NativeImageSkia m_nativeImage;
+
+ // Use create().
+ BitmapImageSingleFrameSkia() { }
+};
+
+} // namespace WebCore
+
+#endif // BitmapImageSingleFrameSkia_h
diff --git a/WebCore/platform/graphics/skia/FloatPointSkia.cpp b/WebCore/platform/graphics/skia/FloatPointSkia.cpp
new file mode 100644
index 0000000..054a772
--- /dev/null
+++ b/WebCore/platform/graphics/skia/FloatPointSkia.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FloatPoint.h"
+
+#include "SkPoint.h"
+#include "SkiaUtils.h"
+
+namespace WebCore {
+
+FloatPoint::FloatPoint(const SkPoint& p)
+ : m_x(p.fX)
+ , m_y(p.fY)
+{
+}
+
+FloatPoint::operator SkPoint() const
+{
+ SkPoint p = { WebCoreFloatToSkScalar(m_x), WebCoreFloatToSkScalar(m_y) };
+ return p;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/FloatRectSkia.cpp b/WebCore/platform/graphics/skia/FloatRectSkia.cpp
new file mode 100644
index 0000000..a10371f
--- /dev/null
+++ b/WebCore/platform/graphics/skia/FloatRectSkia.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FloatRect.h"
+
+#include "SkRect.h"
+
+namespace WebCore {
+
+FloatRect::FloatRect(const SkRect& r)
+ : m_location(r.fLeft, r.fTop)
+ , m_size(r.width(), r.height())
+{
+}
+
+FloatRect::operator SkRect() const
+{
+ SkRect rect = { x(), y(), right(), bottom() };
+ return rect;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/GradientSkia.cpp b/WebCore/platform/graphics/skia/GradientSkia.cpp
new file mode 100644
index 0000000..eff7c66
--- /dev/null
+++ b/WebCore/platform/graphics/skia/GradientSkia.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Gradient.h"
+
+#include "CSSParser.h"
+#include "GraphicsContext.h"
+
+#include "SkGradientShader.h"
+#include "SkiaUtils.h"
+
+namespace WebCore {
+
+void Gradient::platformDestroy()
+{
+ if (m_gradient)
+ m_gradient->safeUnref();
+ m_gradient = 0;
+}
+
+static inline U8CPU F2B(float x)
+{
+ return static_cast<int>(x * 255);
+}
+
+static SkColor makeSkColor(float a, float r, float g, float b)
+{
+ return SkColorSetARGB(F2B(a), F2B(r), F2B(g), F2B(b));
+}
+
+// Determine the total number of stops needed, including pseudo-stops at the
+// ends as necessary.
+static size_t totalStopsNeeded(const Gradient::ColorStop* stopData, size_t count)
+{
+ 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)
+ countUsed++;
+ return countUsed;
+}
+
+// Collect sorted stop position and color information into the pos and colors
+// buffers, ensuring stops at both 0.0 and 1.0. The buffers must be large
+// enough to hold information for all stops, including the new endpoints if
+// stops at 0.0 and 1.0 aren't already included.
+static void fillStops(const Gradient::ColorStop* stopData,
+ size_t count, SkScalar* pos, SkColor* colors)
+{
+ const Gradient::ColorStop* stop = stopData;
+ size_t start = 0;
+ if (count < 1) {
+ // A gradient with no stops must be transparent black.
+ pos[0] = WebCoreFloatToSkScalar(0.0);
+ colors[0] = makeSkColor(0.0, 0.0, 0.0, 0.0);
+ start = 1;
+ } else if (stop->stop > 0.0) {
+ // Copy the first stop to 0.0. The first stop position may have a slight
+ // rounding error, but we don't care in this float comparison, since
+ // 0.0 comes through cleanly and people aren't likely to want a gradient
+ // with a stop at (0 + epsilon).
+ pos[0] = WebCoreFloatToSkScalar(0.0);
+ colors[0] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
+ start = 1;
+ }
+
+ for (size_t i = start; i < start + count; i++) {
+ pos[i] = WebCoreFloatToSkScalar(stop->stop);
+ colors[i] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
+ ++stop;
+ }
+
+ // Copy the last stop to 1.0 if needed. See comment above about this float
+ // comparison.
+ if (count < 1 || (--stop)->stop < 1.0) {
+ pos[start + count] = WebCoreFloatToSkScalar(1.0);
+ colors[start + count] = colors[start + count - 1];
+ }
+}
+
+static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b)
+{
+ return a.stop < b.stop;
+}
+
+SkShader* Gradient::platformGradient()
+{
+ if (m_gradient)
+ return m_gradient;
+
+ // FIXME: This and compareStops() are also in Gradient.cpp and
+ // CSSGradientValue.cpp; probably should refactor in WebKit.
+ if (!m_stopsSorted) {
+ if (m_stops.size())
+ std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
+ m_stopsSorted = true;
+ }
+ size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size());
+ ASSERT(countUsed >= 2);
+ ASSERT(countUsed >= m_stops.size());
+
+ // FIXME: Why is all this manual pointer math needed?!
+ SkAutoMalloc storage(countUsed * (sizeof(SkColor) + sizeof(SkScalar)));
+ SkColor* colors = (SkColor*)storage.get();
+ SkScalar* pos = (SkScalar*)(colors + countUsed);
+
+ fillStops(m_stops.data(), m_stops.size(), pos, colors);
+
+ if (m_radial) {
+ // FIXME: CSS radial Gradients allow an offset focal point (the
+ // "start circle"), but skia doesn't seem to support that, so this just
+ // ignores m_p0/m_r0 and draws the gradient centered in the "end
+ // circle" (m_p1/m_r1).
+ // See http://webkit.org/blog/175/introducing-css-gradients/ for a
+ // description of the expected behavior.
+ m_gradient = SkGradientShader::CreateRadial(m_p1,
+ WebCoreFloatToSkScalar(m_r1), colors, pos,
+ static_cast<int>(countUsed), SkShader::kClamp_TileMode);
+ } else {
+ SkPoint pts[2] = { m_p0, m_p1 };
+ m_gradient = SkGradientShader::CreateLinear(pts, colors, pos,
+ static_cast<int>(countUsed), SkShader::kClamp_TileMode);
+ }
+
+ return m_gradient;
+}
+
+void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
+{
+ context->setFillGradient(this);
+ context->fillRect(rect);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/GraphicsContextPlatformPrivate.h b/WebCore/platform/graphics/skia/GraphicsContextPlatformPrivate.h
new file mode 100644
index 0000000..29738f4
--- /dev/null
+++ b/WebCore/platform/graphics/skia/GraphicsContextPlatformPrivate.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GraphicsContextPlatformPrivate_h
+#define GraphicsContextPlatformPrivate_h
+
+#include <wtf/Noncopyable.h>
+
+class PlatformContextSkia;
+
+namespace WebCore {
+
+// This class just holds onto a PlatformContextSkia for GraphicsContext.
+class GraphicsContextPlatformPrivate : Noncopyable {
+public:
+ GraphicsContextPlatformPrivate(PlatformContextSkia* platformContext)
+ : m_context(platformContext) { }
+
+ PlatformContextSkia* context() { return m_context; }
+
+private:
+ // Non-owning pointer to the PlatformContext.
+ PlatformContextSkia* m_context;
+};
+
+} // namespace WebCore
+
+#endif // GraphicsContextPlatformPrivate_h
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
new file mode 100644
index 0000000..e6c7783
--- /dev/null
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -0,0 +1,1122 @@
+/*
+ * Copyright (c) 2006, 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 "GraphicsContext.h"
+
+#include "GraphicsContextPlatformPrivate.h"
+#include "GraphicsContextPrivate.h"
+#include "Color.h"
+#include "FloatRect.h"
+#include "Gradient.h"
+#include "IntRect.h"
+#include "NativeImageSkia.h"
+#include "NotImplemented.h"
+#include "PlatformContextSkia.h"
+#include "TransformationMatrix.h"
+
+#include "SkBitmap.h"
+#include "SkBlurDrawLooper.h"
+#include "SkCornerPathEffect.h"
+#include "skia/ext/platform_canvas.h"
+#include "SkiaUtils.h"
+#include "SkShader.h"
+
+#include <math.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+namespace {
+
+// "Seatbelt" functions ------------------------------------------------------
+//
+// These functions check certain graphics primitives for being "safe".
+// Skia has historically crashed when sent crazy data. These functions do
+// additional checking to prevent crashes.
+//
+// Ideally, all of these would be fixed in the graphics layer and we would not
+// have to do any checking. You can uncomment the ENSURE_VALUE_SAFETY_FOR_SKIA
+// flag to check the graphics layer.
+#define ENSURE_VALUE_SAFETY_FOR_SKIA
+
+static bool isCoordinateSkiaSafe(float coord)
+{
+#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA
+ // First check for valid floats.
+#if defined(_MSC_VER)
+ if (!_finite(coord))
+#else
+ if (!finite(coord))
+#endif
+ return false;
+
+ // Skia uses 16.16 fixed point and 26.6 fixed point in various places. If
+ // the transformed point exceeds 15 bits, we just declare that it's
+ // unreasonable to catch both of these cases.
+ static const int maxPointMagnitude = 32767;
+ if (coord > maxPointMagnitude || coord < -maxPointMagnitude)
+ return false;
+
+ return true;
+#else
+ return true;
+#endif
+}
+
+static bool isPointSkiaSafe(const SkMatrix& transform, const SkPoint& pt)
+{
+#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA
+ // Now check for points that will overflow. We check the *transformed*
+ // points since this is what will be rasterized.
+ SkPoint xPt;
+ transform.mapPoints(&xPt, &pt, 1);
+ return isCoordinateSkiaSafe(xPt.fX) && isCoordinateSkiaSafe(xPt.fY);
+#else
+ return true;
+#endif
+}
+
+static bool isRectSkiaSafe(const SkMatrix& transform, const SkRect& rc)
+{
+#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA
+ SkPoint topleft = {rc.fLeft, rc.fTop};
+ SkPoint bottomright = {rc.fRight, rc.fBottom};
+ return isPointSkiaSafe(transform, topleft) && isPointSkiaSafe(transform, bottomright);
+#else
+ return true;
+#endif
+}
+
+bool isPathSkiaSafe(const SkMatrix& transform, const SkPath& path)
+{
+#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA
+ SkPoint current_points[4];
+ SkPath::Iter iter(path, false);
+ for (SkPath::Verb verb = iter.next(current_points);
+ verb != SkPath::kDone_Verb;
+ verb = iter.next(current_points)) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ // This move will be duplicated in the next verb, so we can ignore.
+ break;
+ case SkPath::kLine_Verb:
+ // iter.next returns 2 points.
+ if (!isPointSkiaSafe(transform, current_points[0])
+ || !isPointSkiaSafe(transform, current_points[1]))
+ return false;
+ break;
+ case SkPath::kQuad_Verb:
+ // iter.next returns 3 points.
+ if (!isPointSkiaSafe(transform, current_points[0])
+ || !isPointSkiaSafe(transform, current_points[1])
+ || !isPointSkiaSafe(transform, current_points[2]))
+ return false;
+ break;
+ case SkPath::kCubic_Verb:
+ // iter.next returns 4 points.
+ if (!isPointSkiaSafe(transform, current_points[0])
+ || !isPointSkiaSafe(transform, current_points[1])
+ || !isPointSkiaSafe(transform, current_points[2])
+ || !isPointSkiaSafe(transform, current_points[3]))
+ return false;
+ break;
+ case SkPath::kClose_Verb:
+ case SkPath::kDone_Verb:
+ default:
+ break;
+ }
+ }
+ return true;
+#else
+ return true;
+#endif
+}
+
+// Local helper functions ------------------------------------------------------
+
+void addCornerArc(SkPath* path, const SkRect& rect, const IntSize& size, int startAngle)
+{
+ SkIRect ir;
+ int rx = SkMin32(SkScalarRound(rect.width()), size.width());
+ int ry = SkMin32(SkScalarRound(rect.height()), size.height());
+
+ ir.set(-rx, -ry, rx, ry);
+ switch (startAngle) {
+ case 0:
+ ir.offset(rect.fRight - ir.fRight, rect.fBottom - ir.fBottom);
+ break;
+ case 90:
+ ir.offset(rect.fLeft - ir.fLeft, rect.fBottom - ir.fBottom);
+ break;
+ case 180:
+ ir.offset(rect.fLeft - ir.fLeft, rect.fTop - ir.fTop);
+ break;
+ case 270:
+ ir.offset(rect.fRight - ir.fRight, rect.fTop - ir.fTop);
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ SkRect r;
+ r.set(ir);
+ path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false);
+}
+
+inline int fastMod(int value, int max)
+{
+ int sign = SkExtractSign(value);
+
+ value = SkApplySign(value, sign);
+ if (value >= max)
+ value %= max;
+ return SkApplySign(value, sign);
+}
+
+inline float square(float n)
+{
+ return n * n;
+}
+
+} // namespace
+
+// -----------------------------------------------------------------------------
+
+// This may be called with a NULL pointer to create a graphics context that has
+// no painting.
+GraphicsContext::GraphicsContext(PlatformGraphicsContext* gc)
+ : m_common(createGraphicsContextPrivate())
+ , m_data(new GraphicsContextPlatformPrivate(gc))
+{
+ setPaintingDisabled(!gc || !platformContext()->canvas());
+}
+
+GraphicsContext::~GraphicsContext()
+{
+ delete m_data;
+ this->destroyGraphicsContextPrivate(m_common);
+}
+
+PlatformGraphicsContext* GraphicsContext::platformContext() const
+{
+ ASSERT(!paintingDisabled());
+ return m_data->context();
+}
+
+// State saving ----------------------------------------------------------------
+
+void GraphicsContext::savePlatformState()
+{
+ if (paintingDisabled())
+ return;
+
+ // Save our private State.
+ platformContext()->save();
+}
+
+void GraphicsContext::restorePlatformState()
+{
+ if (paintingDisabled())
+ return;
+
+ // Restore our private State.
+ platformContext()->restore();
+}
+
+void GraphicsContext::beginTransparencyLayer(float opacity)
+{
+ if (paintingDisabled())
+ return;
+
+ // We need the "alpha" layer flag here because the base layer is opaque
+ // (the surface of the page) but layers on top may have transparent parts.
+ // Without explicitly setting the alpha flag, the layer will inherit the
+ // opaque setting of the base and some things won't work properly.
+ platformContext()->canvas()->saveLayerAlpha(
+ 0,
+ static_cast<unsigned char>(opacity * 255),
+ static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag |
+ SkCanvas::kFullColorLayer_SaveFlag));
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+ if (paintingDisabled())
+ return;
+
+#if PLATFORM(WIN_OS)
+ platformContext()->canvas()->getTopPlatformDevice().
+ fixupAlphaBeforeCompositing();
+#endif
+ platformContext()->canvas()->restore();
+}
+
+// Graphics primitives ---------------------------------------------------------
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r(rect);
+ if (!isRectSkiaSafe(getCTM(), r))
+ return;
+
+ SkPath path;
+ path.addOval(r, SkPath::kCW_Direction);
+ // only perform the inset if we won't invert r
+ if (2 * thickness < rect.width() && 2 * thickness < rect.height()) {
+ r.inset(SkIntToScalar(thickness) ,SkIntToScalar(thickness));
+ path.addOval(r, SkPath::kCCW_Direction);
+ }
+ platformContext()->canvas()->clipPath(path);
+}
+
+void GraphicsContext::addPath(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->addPath(*path.platformPath());
+}
+
+void GraphicsContext::beginPath()
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->beginPath();
+}
+
+void GraphicsContext::clearPlatformShadow()
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->setDrawLooper(0);
+}
+
+void GraphicsContext::clearRect(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r = rect;
+ if (!isRectSkiaSafe(getCTM(), r))
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
+
+ SkPaint paint;
+ platformContext()->setupPaintForFilling(&paint);
+ paint.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ platformContext()->canvas()->drawRect(r, paint);
+}
+
+void GraphicsContext::clip(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r(rect);
+ if (!isRectSkiaSafe(getCTM(), r))
+ return;
+
+ platformContext()->canvas()->clipRect(r);
+}
+
+void GraphicsContext::clip(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ const SkPath& p = *path.platformPath();
+ if (!isPathSkiaSafe(getCTM(), p))
+ return;
+
+ platformContext()->canvas()->clipPath(p);
+}
+
+void GraphicsContext::clipOut(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r(rect);
+ if (!isRectSkiaSafe(getCTM(), r))
+ return;
+
+ platformContext()->canvas()->clipRect(r, SkRegion::kDifference_Op);
+}
+
+void GraphicsContext::clipOut(const Path& p)
+{
+ if (paintingDisabled())
+ return;
+
+ const SkPath& path = *p.platformPath();
+ if (!isPathSkiaSafe(getCTM(), path))
+ return;
+
+ platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op);
+}
+
+void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect oval(rect);
+ if (!isRectSkiaSafe(getCTM(), oval))
+ return;
+
+ SkPath path;
+ path.addOval(oval, SkPath::kCCW_Direction);
+ platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op);
+}
+
+void GraphicsContext::clipPath(WindRule clipRule)
+{
+ if (paintingDisabled())
+ return;
+
+ const SkPath* oldPath = platformContext()->currentPath();
+ SkPath path(*oldPath);
+ path.setFillType(clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
+ platformContext()->canvas()->clipPath(path);
+}
+
+void GraphicsContext::clipToImageBuffer(const FloatRect& rect,
+ const ImageBuffer* imageBuffer)
+{
+ if (paintingDisabled())
+ return;
+
+ // FIXME: This is needed for image masking and complex text fills.
+ notImplemented();
+}
+
+void GraphicsContext::concatCTM(const TransformationMatrix& xform)
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->canvas()->concat(xform);
+}
+
+void GraphicsContext::drawConvexPolygon(size_t numPoints,
+ const FloatPoint* points,
+ bool shouldAntialias)
+{
+ if (paintingDisabled())
+ return;
+
+ if (numPoints <= 1)
+ return;
+
+ SkPath path;
+
+ path.incReserve(numPoints);
+ path.moveTo(WebCoreFloatToSkScalar(points[0].x()),
+ WebCoreFloatToSkScalar(points[0].y()));
+ for (size_t i = 1; i < numPoints; i++) {
+ path.lineTo(WebCoreFloatToSkScalar(points[i].x()),
+ WebCoreFloatToSkScalar(points[i].y()));
+ }
+
+ if (!isPathSkiaSafe(getCTM(), path))
+ return;
+
+ SkPaint paint;
+ if (fillColor().alpha() > 0) {
+ platformContext()->setupPaintForFilling(&paint);
+ platformContext()->canvas()->drawPath(path, paint);
+ }
+
+ if (strokeStyle() != NoStroke) {
+ paint.reset();
+ platformContext()->setupPaintForStroking(&paint, 0, 0);
+ platformContext()->canvas()->drawPath(path, paint);
+ }
+}
+
+// This method is only used to draw the little circles used in lists.
+void GraphicsContext::drawEllipse(const IntRect& elipseRect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect rect = elipseRect;
+ if (!isRectSkiaSafe(getCTM(), rect))
+ return;
+
+ SkPaint paint;
+ if (fillColor().alpha() > 0) {
+ platformContext()->setupPaintForFilling(&paint);
+ platformContext()->canvas()->drawOval(rect, paint);
+ }
+
+ if (strokeStyle() != NoStroke) {
+ paint.reset();
+ platformContext()->setupPaintForStroking(&paint, &rect, 0);
+ platformContext()->canvas()->drawOval(rect, paint);
+ }
+}
+
+void GraphicsContext::drawFocusRing(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ const Vector<IntRect>& rects = focusRingRects();
+ unsigned rectCount = rects.size();
+ if (0 == rectCount)
+ return;
+
+ SkRegion focusRingRegion;
+ const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.5);
+ for (unsigned i = 0; i < rectCount; i++) {
+ SkIRect r = rects[i];
+ r.inset(-focusRingOutset, -focusRingOutset);
+ focusRingRegion.op(r, SkRegion::kUnion_Op);
+ }
+
+ SkPath path;
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+
+ paint.setColor(focusRingColor().rgb());
+ paint.setStrokeWidth(focusRingOutset * 2);
+ paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref();
+ focusRingRegion.getBoundaryPath(&path);
+ platformContext()->canvas()->drawPath(path, paint);
+}
+
+// This is only used to draw borders.
+void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
+{
+ if (paintingDisabled())
+ return;
+
+ StrokeStyle penStyle = strokeStyle();
+ if (penStyle == NoStroke)
+ return;
+
+ SkPaint paint;
+ SkPoint pts[2] = { (SkPoint)point1, (SkPoint)point2 };
+ if (!isPointSkiaSafe(getCTM(), pts[0]) || !isPointSkiaSafe(getCTM(), pts[1]))
+ return;
+
+ // We know these are vertical or horizontal lines, so the length will just
+ // be the sum of the displacement component vectors give or take 1 -
+ // probably worth the speed up of no square root, which also won't be exact.
+ SkPoint disp = pts[1] - pts[0];
+ int length = SkScalarRound(disp.fX + disp.fY);
+ int width = roundf(
+ platformContext()->setupPaintForStroking(&paint, 0, length));
+
+ // "Borrowed" this comment and idea from GraphicsContextCG.cpp
+ // For odd widths, we add in 0.5 to the appropriate x/y so that the float
+ // arithmetic works out. For example, with a border width of 3, KHTML will
+ // pass us (y1+y2)/2, e.g., (50+53)/2 = 103/2 = 51 when we want 51.5. It is
+ // always true that an even width gave us a perfect position, but an odd
+ // width gave us a position that is off by exactly 0.5.
+ bool isVerticalLine = pts[0].fX == pts[1].fX;
+
+ if (width & 1) { // Odd.
+ if (isVerticalLine) {
+ pts[0].fX = pts[0].fX + SK_ScalarHalf;
+ pts[1].fX = pts[0].fX;
+ } else { // Horizontal line
+ pts[0].fY = pts[0].fY + SK_ScalarHalf;
+ pts[1].fY = pts[0].fY;
+ }
+ }
+ platformContext()->canvas()->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);
+}
+
+void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& pt,
+ int width,
+ bool grammar)
+{
+ if (paintingDisabled())
+ return;
+
+ // Create the pattern we'll use to draw the underline.
+ static SkBitmap* misspellBitmap = 0;
+ if (!misspellBitmap) {
+ // We use a 2-pixel-high misspelling indicator because that seems to be
+ // what WebKit is designed for, and how much room there is in a typical
+ // page for it.
+ const int rowPixels = 32; // Must be multiple of 4 for pattern below.
+ const int colPixels = 2;
+ misspellBitmap = new SkBitmap;
+ misspellBitmap->setConfig(SkBitmap::kARGB_8888_Config,
+ rowPixels, colPixels);
+ misspellBitmap->allocPixels();
+
+ misspellBitmap->eraseARGB(0, 0, 0, 0);
+ const uint32_t lineColor = 0xFFFF0000; // Opaque red.
+ const uint32_t antiColor = 0x60600000; // Semitransparent red.
+
+ // Pattern: X o o X o o X
+ // o X o o X o
+ uint32_t* row1 = misspellBitmap->getAddr32(0, 0);
+ uint32_t* row2 = misspellBitmap->getAddr32(0, 1);
+ for (int x = 0; x < rowPixels; x++) {
+ switch (x % 4) {
+ case 0:
+ row1[x] = lineColor;
+ break;
+ case 1:
+ row1[x] = antiColor;
+ row2[x] = antiColor;
+ break;
+ case 2:
+ row2[x] = lineColor;
+ break;
+ case 3:
+ row1[x] = antiColor;
+ row2[x] = antiColor;
+ break;
+ }
+ }
+ }
+
+ // Offset it vertically by 1 so that there's some space under the text.
+ SkScalar originX = SkIntToScalar(pt.x());
+ SkScalar originY = SkIntToScalar(pt.y()) + 1;
+
+ // Make a shader for the bitmap with an origin of the box we'll draw. This
+ // shader is refcounted and will have an initial refcount of 1.
+ SkShader* shader = SkShader::CreateBitmapShader(
+ *misspellBitmap, SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+ SkMatrix matrix;
+ matrix.reset();
+ matrix.postTranslate(originX, originY);
+ shader->setLocalMatrix(matrix);
+
+ // Assign the shader to the paint & release our reference. The paint will
+ // now own the shader and the shader will be destroyed when the paint goes
+ // out of scope.
+ SkPaint paint;
+ paint.setShader(shader);
+ shader->unref();
+
+ SkRect rect;
+ rect.set(originX,
+ originY,
+ originX + SkIntToScalar(width),
+ originY + SkIntToScalar(misspellBitmap->height()));
+ platformContext()->canvas()->drawRect(rect, paint);
+}
+
+void GraphicsContext::drawLineForText(const IntPoint& pt,
+ int width,
+ bool printing)
+{
+ if (paintingDisabled())
+ return;
+
+ int thickness = SkMax32(static_cast<int>(strokeThickness()), 1);
+ SkRect r;
+ r.fLeft = SkIntToScalar(pt.x());
+ r.fTop = SkIntToScalar(pt.y());
+ r.fRight = r.fLeft + SkIntToScalar(width);
+ r.fBottom = r.fTop + SkIntToScalar(thickness);
+
+ SkPaint paint;
+ paint.setColor(strokeColor().rgb());
+ platformContext()->canvas()->drawRect(r, paint);
+}
+
+// Draws a filled rectangle with a stroked border.
+void GraphicsContext::drawRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r = rect;
+ if (!isRectSkiaSafe(getCTM(), r))
+ // See the fillRect below.
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
+
+ platformContext()->drawRect(r);
+}
+
+void GraphicsContext::fillPath()
+{
+ if (paintingDisabled())
+ return;
+
+ const SkPath& path = *platformContext()->currentPath();
+ if (!isPathSkiaSafe(getCTM(), path))
+ return;
+
+ const GraphicsContextState& state = m_common->state;
+ ColorSpace colorSpace = state.fillColorSpace;
+
+ if (colorSpace == SolidColorSpace && !fillColor().alpha())
+ return;
+
+ platformContext()->setFillRule(state.fillRule == RULE_EVENODD ?
+ SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
+
+ SkPaint paint;
+ platformContext()->setupPaintForFilling(&paint);
+
+ if (colorSpace == PatternColorSpace) {
+ SkShader* pat = state.fillPattern->createPlatformPattern(getCTM());
+ paint.setShader(pat);
+ pat->unref();
+ } else if (colorSpace == GradientColorSpace)
+ paint.setShader(state.fillGradient->platformGradient());
+
+ platformContext()->canvas()->drawPath(path, paint);
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r = rect;
+ if (!isRectSkiaSafe(getCTM(), r))
+ // See the other version of fillRect below.
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
+
+ const GraphicsContextState& state = m_common->state;
+ ColorSpace colorSpace = state.fillColorSpace;
+
+ if (colorSpace == SolidColorSpace && !fillColor().alpha())
+ return;
+
+ SkPaint paint;
+ platformContext()->setupPaintForFilling(&paint);
+
+ if (colorSpace == PatternColorSpace) {
+ SkShader* pat = state.fillPattern->createPlatformPattern(getCTM());
+ paint.setShader(pat);
+ pat->unref();
+ } else if (colorSpace == GradientColorSpace)
+ paint.setShader(state.fillGradient->platformGradient());
+
+ platformContext()->canvas()->drawRect(r, paint);
+}
+
+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
+ // workaround to fix bug 1212844. When the input rectangle is very
+ // large, it can overflow Skia's internal fixed point rect. This
+ // should be fixable in Skia (since the output bitmap isn't that
+ // large), but until that is fixed, we try to handle it ourselves.
+ //
+ // We manually clip the rectangle to the current clip rect. This
+ // will prevent overflow. The rectangle will be transformed to the
+ // canvas' coordinate space before it is converted to fixed point
+ // so we are guaranteed not to overflow after doing this.
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
+ }
+
+ SkPaint paint;
+ platformContext()->setupPaintCommon(&paint);
+ paint.setColor(color.rgb());
+ platformContext()->canvas()->drawRect(r, paint);
+}
+
+void GraphicsContext::fillRoundedRect(const IntRect& rect,
+ const IntSize& topLeft,
+ const IntSize& topRight,
+ const IntSize& bottomLeft,
+ const IntSize& bottomRight,
+ const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r = rect;
+ if (!isRectSkiaSafe(getCTM(), r))
+ // See fillRect().
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
+
+ SkPath path;
+ addCornerArc(&path, r, topRight, 270);
+ addCornerArc(&path, r, bottomRight, 0);
+ addCornerArc(&path, r, bottomLeft, 90);
+ addCornerArc(&path, r, topLeft, 180);
+
+ SkPaint paint;
+ platformContext()->setupPaintForFilling(&paint);
+ platformContext()->canvas()->drawPath(path, paint);
+ return fillRect(rect, color);
+}
+
+TransformationMatrix GraphicsContext::getCTM() const
+{
+ return platformContext()->canvas()->getTotalMatrix();
+}
+
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
+{
+ // This logic is copied from GraphicsContextCG, eseidel 5/05/08
+
+ // It is not enough just to round to pixels in device space. The rotation
+ // part of the affine transform matrix to device space can mess with this
+ // conversion if we have a rotating image like the hands of the world clock
+ // widget. We just need the scale, so we get the affine transform matrix and
+ // extract the scale.
+
+ const SkMatrix& deviceMatrix = platformContext()->canvas()->getTotalMatrix();
+ if (deviceMatrix.isIdentity())
+ return rect;
+
+ float deviceScaleX = sqrtf(square(deviceMatrix.getScaleX())
+ + square(deviceMatrix.getSkewY()));
+ float deviceScaleY = sqrtf(square(deviceMatrix.getSkewX())
+ + square(deviceMatrix.getScaleY()));
+
+ FloatPoint deviceOrigin(rect.x() * deviceScaleX, rect.y() * deviceScaleY);
+ FloatPoint deviceLowerRight((rect.x() + rect.width()) * deviceScaleX,
+ (rect.y() + rect.height()) * deviceScaleY);
+
+ deviceOrigin.setX(roundf(deviceOrigin.x()));
+ deviceOrigin.setY(roundf(deviceOrigin.y()));
+ deviceLowerRight.setX(roundf(deviceLowerRight.x()));
+ deviceLowerRight.setY(roundf(deviceLowerRight.y()));
+
+ // Don't let the height or width round to 0 unless either was originally 0
+ if (deviceOrigin.y() == deviceLowerRight.y() && rect.height() != 0)
+ deviceLowerRight.move(0, 1);
+ if (deviceOrigin.x() == deviceLowerRight.x() && rect.width() != 0)
+ deviceLowerRight.move(1, 0);
+
+ FloatPoint roundedOrigin(deviceOrigin.x() / deviceScaleX,
+ deviceOrigin.y() / deviceScaleY);
+ FloatPoint roundedLowerRight(deviceLowerRight.x() / deviceScaleX,
+ deviceLowerRight.y() / deviceScaleY);
+ return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin);
+}
+
+void GraphicsContext::scale(const FloatSize& size)
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->canvas()->scale(WebCoreFloatToSkScalar(size.width()),
+ WebCoreFloatToSkScalar(size.height()));
+}
+
+void GraphicsContext::setAlpha(float alpha)
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->setAlpha(alpha);
+}
+
+void GraphicsContext::setCompositeOperation(CompositeOperator op)
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->setPorterDuffMode(WebCoreCompositeToSkiaComposite(op));
+}
+
+void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setLineCap(LineCap cap)
+{
+ if (paintingDisabled())
+ return;
+ switch (cap) {
+ case ButtCap:
+ platformContext()->setLineCap(SkPaint::kButt_Cap);
+ break;
+ case RoundCap:
+ platformContext()->setLineCap(SkPaint::kRound_Cap);
+ break;
+ case SquareCap:
+ platformContext()->setLineCap(SkPaint::kSquare_Cap);
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+}
+
+void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
+{
+ if (paintingDisabled())
+ return;
+
+ // 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)
+ return;
+
+ size_t count = (dashLength % 2) == 0 ? dashLength : dashLength * 2;
+ SkScalar* intervals = new SkScalar[count];
+
+ for (unsigned int i = 0; i < count; i++)
+ intervals[i] = dashes[i % dashLength];
+
+ platformContext()->setDashPathEffect(new SkDashPathEffect(intervals, count, dashOffset));
+
+ delete[] intervals;
+}
+
+void GraphicsContext::setLineJoin(LineJoin join)
+{
+ if (paintingDisabled())
+ return;
+ switch (join) {
+ case MiterJoin:
+ platformContext()->setLineJoin(SkPaint::kMiter_Join);
+ break;
+ case RoundJoin:
+ platformContext()->setLineJoin(SkPaint::kRound_Join);
+ break;
+ case BevelJoin:
+ platformContext()->setLineJoin(SkPaint::kBevel_Join);
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+}
+
+void GraphicsContext::setMiterLimit(float limit)
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->setMiterLimit(limit);
+}
+
+void GraphicsContext::setPlatformFillColor(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->setFillColor(color.rgb());
+}
+
+void GraphicsContext::setPlatformShadow(const IntSize& size,
+ int blurInt,
+ const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ double width = size.width();
+ double height = size.height();
+ double blur = blurInt;
+
+ // TODO(tc): This still does not address the issue that shadows
+ // within canvas elements should ignore transforms.
+ if (m_common->state.shadowsIgnoreTransforms) {
+ // Currently only the GraphicsContext associated with the
+ // CanvasRenderingContext for HTMLCanvasElement have shadows ignore
+ // Transforms. So with this flag set, we know this state is associated
+ // with a CanvasRenderingContext.
+ // CG uses natural orientation for Y axis, but the HTML5 canvas spec
+ // does not.
+ // So we now flip the height since it was flipped in
+ // CanvasRenderingContext in order to work with CG.
+ height = -height;
+ }
+
+ SkColor c;
+ if (color.isValid())
+ c = color.rgb();
+ else
+ c = SkColorSetARGB(0xFF/3, 0, 0, 0); // "std" apple shadow color.
+
+ // TODO(tc): Should we have a max value for the blur? CG clamps at 1000.0
+ // for perf reasons.
+ SkDrawLooper* dl = new SkBlurDrawLooper(blur / 2, width, height, c);
+ platformContext()->setDrawLooper(dl);
+ dl->unref();
+}
+
+void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor)
+{
+ if (paintingDisabled())
+ return;
+
+ platformContext()->setStrokeColor(strokecolor.rgb());
+}
+
+void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& stroke)
+{
+ if (paintingDisabled())
+ return;
+
+ platformContext()->setStrokeStyle(stroke);
+}
+
+void GraphicsContext::setPlatformStrokeThickness(float thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ platformContext()->setStrokeThickness(thickness);
+}
+
+void GraphicsContext::setPlatformTextDrawingMode(int mode)
+{
+ if (paintingDisabled())
+ return;
+
+ platformContext()->setTextDrawingMode(mode);
+}
+
+void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
+{
+}
+
+void GraphicsContext::setPlatformShouldAntialias(bool enable)
+{
+ if (paintingDisabled())
+ return;
+
+ platformContext()->setUseAntialiasing(enable);
+}
+
+void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
+{
+ if (paintingDisabled())
+ return;
+
+ SkPaint paint;
+ SkRect oval = r;
+ if (strokeStyle() == NoStroke) {
+ // Stroke using the fill color.
+ // TODO(brettw) is this really correct? It seems unreasonable.
+ platformContext()->setupPaintForFilling(&paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(WebCoreFloatToSkScalar(strokeThickness()));
+ } else
+ platformContext()->setupPaintForStroking(&paint, 0, 0);
+
+ // We do this before converting to scalar, so we don't overflow SkFixed.
+ startAngle = fastMod(startAngle, 360);
+ angleSpan = fastMod(angleSpan, 360);
+
+ SkPath path;
+ path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
+ if (!isPathSkiaSafe(getCTM(), path))
+ return;
+ platformContext()->canvas()->drawPath(path, paint);
+}
+
+void GraphicsContext::strokePath()
+{
+ if (paintingDisabled())
+ return;
+
+ const SkPath& path = *platformContext()->currentPath();
+ if (!isPathSkiaSafe(getCTM(), path))
+ return;
+
+ const GraphicsContextState& state = m_common->state;
+ ColorSpace colorSpace = state.strokeColorSpace;
+
+ if (colorSpace == SolidColorSpace && !strokeColor().alpha())
+ return;
+
+ SkPaint paint;
+ platformContext()->setupPaintForStroking(&paint, 0, 0);
+
+ if (colorSpace == PatternColorSpace) {
+ SkShader* pat = state.strokePattern->createPlatformPattern(getCTM());
+ paint.setShader(pat);
+ pat->unref();
+ } else if (colorSpace == GradientColorSpace)
+ paint.setShader(state.strokeGradient->platformGradient());
+
+ platformContext()->canvas()->drawPath(path, paint);
+}
+
+void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
+{
+ if (paintingDisabled())
+ return;
+
+ if (!isRectSkiaSafe(getCTM(), rect))
+ return;
+
+ 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));
+
+ if (colorSpace == PatternColorSpace) {
+ SkShader* pat = state.strokePattern->createPlatformPattern(getCTM());
+ paint.setShader(pat);
+ pat->unref();
+ } else if (colorSpace == GradientColorSpace)
+ paint.setShader(state.strokeGradient->platformGradient());
+
+ platformContext()->canvas()->drawRect(rect, paint);
+}
+
+void GraphicsContext::rotate(float angleInRadians)
+{
+ if (paintingDisabled())
+ return;
+
+ platformContext()->canvas()->rotate(WebCoreFloatToSkScalar(
+ angleInRadians * (180.0f / 3.14159265f)));
+}
+
+void GraphicsContext::translate(float w, float h)
+{
+ if (paintingDisabled())
+ return;
+
+ platformContext()->canvas()->translate(WebCoreFloatToSkScalar(w),
+ WebCoreFloatToSkScalar(h));
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
new file mode 100644
index 0000000..fdfcb85
--- /dev/null
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ImageBuffer.h"
+
+#include "BitmapImage.h"
+#include "BitmapImageSingleFrameSkia.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include "NotImplemented.h"
+#include "PlatformContextSkia.h"
+#include "SkiaUtils.h"
+
+using namespace std;
+
+namespace WebCore {
+
+// We pass a technically-uninitialized canvas to the platform context here since
+// the canvas initialization completes in ImageBuffer::ImageBuffer. But
+// PlatformContext doesn't actually need to use the object, and this makes all
+// the ownership easier to manage.
+ImageBufferData::ImageBufferData(const IntSize& size)
+ : m_platformContext(0) // Canvas is set in ImageBuffer constructor.
+{
+}
+
+ImageBuffer::ImageBuffer(const IntSize& size, bool grayScale, bool& success)
+ : m_data(size)
+ , m_size(size)
+{
+ if (!m_data.m_canvas.initialize(size.width(), size.height(), false)) {
+ success = false;
+ return;
+ }
+
+ m_data.m_platformContext.setCanvas(&m_data.m_canvas);
+ m_context.set(new GraphicsContext(&m_data.m_platformContext));
+
+ // Make the background transparent. It would be nice if this wasn't
+ // required, but the canvas is currently filled with the magic transparency
+ // color. Can we have another way to manage this?
+ m_data.m_canvas.drawARGB(0, 0, 0, 0, SkPorterDuff::kClear_Mode);
+ success = true;
+}
+
+ImageBuffer::~ImageBuffer()
+{
+}
+
+GraphicsContext* ImageBuffer::context() const
+{
+ return m_context.get();
+}
+
+Image* ImageBuffer::image() const
+{
+ if (!m_image) {
+ // This creates a COPY of the image and will cache that copy. This means
+ // that if subsequent operations take place on the context, neither the
+ // currently-returned image, nor the results of future image() calls,
+ // will contain that operation.
+ //
+ // This seems silly, but is the way the CG port works: image() is
+ // intended to be used only when rendering is "complete."
+ m_image = BitmapImageSingleFrameSkia::create(
+ *m_data.m_platformContext.bitmap());
+ }
+ return m_image.get();
+}
+
+PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+{
+ ASSERT(context());
+
+ RefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
+ unsigned char* data = result->data()->data();
+
+ if (rect.x() < 0 || rect.y() < 0 ||
+ (rect.x() + rect.width()) > m_size.width() ||
+ (rect.y() + rect.height()) > m_size.height())
+ memset(data, 0, result->data()->length());
+
+ int originX = rect.x();
+ int destX = 0;
+ if (originX < 0) {
+ destX = -originX;
+ originX = 0;
+ }
+ int endX = rect.x() + rect.width();
+ if (endX > m_size.width())
+ endX = m_size.width();
+ int numColumns = endX - originX;
+
+ int originY = rect.y();
+ int destY = 0;
+ if (originY < 0) {
+ destY = -originY;
+ originY = 0;
+ }
+ int endY = rect.y() + rect.height();
+ if (endY > m_size.height())
+ endY = m_size.height();
+ int numRows = endY - originY;
+
+ const SkBitmap& bitmap = *context()->platformContext()->bitmap();
+ ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
+ SkAutoLockPixels bitmapLock(bitmap);
+
+ unsigned destBytesPerRow = 4 * rect.width();
+ unsigned char* destRow = data + destY * destBytesPerRow + destX * 4;
+
+ for (int y = 0; y < numRows; ++y) {
+ uint32_t* srcRow = bitmap.getAddr32(originX, originY + y);
+ for (int x = 0; x < numColumns; ++x) {
+ SkColor color = SkPMColorToColor(srcRow[x]);
+ unsigned char* destPixel = &destRow[x * 4];
+ destPixel[0] = SkColorGetR(color);
+ destPixel[1] = SkColorGetG(color);
+ destPixel[2] = SkColorGetB(color);
+ destPixel[3] = SkColorGetA(color);
+ }
+ destRow += destBytesPerRow;
+ }
+
+ return result;
+}
+
+void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect,
+ const IntPoint& destPoint)
+{
+ ASSERT(sourceRect.width() > 0);
+ ASSERT(sourceRect.height() > 0);
+
+ int originX = sourceRect.x();
+ int destX = destPoint.x() + sourceRect.x();
+ ASSERT(destX >= 0);
+ ASSERT(destX < m_size.width());
+ ASSERT(originX >= 0);
+ ASSERT(originX < sourceRect.right());
+
+ int endX = destPoint.x() + sourceRect.right();
+ ASSERT(endX <= m_size.width());
+
+ int numColumns = endX - destX;
+
+ int originY = sourceRect.y();
+ int destY = destPoint.y() + sourceRect.y();
+ ASSERT(destY >= 0);
+ ASSERT(destY < m_size.height());
+ ASSERT(originY >= 0);
+ ASSERT(originY < sourceRect.bottom());
+
+ int endY = destPoint.y() + sourceRect.bottom();
+ ASSERT(endY <= m_size.height());
+ int numRows = endY - destY;
+
+ const SkBitmap& bitmap = *context()->platformContext()->bitmap();
+ ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
+ SkAutoLockPixels bitmapLock(bitmap);
+
+ unsigned srcBytesPerRow = 4 * source->width();
+
+ const unsigned char* srcRow = source->data()->data() + originY * srcBytesPerRow + originX * 4;
+
+ for (int y = 0; y < numRows; ++y) {
+ uint32_t* destRow = bitmap.getAddr32(destX, destY + y);
+ for (int x = 0; x < numColumns; ++x) {
+ const unsigned char* srcPixel = &srcRow[x * 4];
+ destRow[x] = SkPreMultiplyARGB(srcPixel[3], srcPixel[0],
+ srcPixel[1], srcPixel[2]);
+ }
+ srcRow += srcBytesPerRow;
+ }
+}
+
+String ImageBuffer::toDataURL(const String&) const
+{
+ notImplemented();
+ return String();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp
new file mode 100644
index 0000000..1123fe9
--- /dev/null
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "BitmapImage.h"
+#include "BitmapImageSingleFrameSkia.h"
+#include "ChromiumBridge.h"
+#include "FloatConversion.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "Logging.h"
+#include "NativeImageSkia.h"
+#include "NotImplemented.h"
+#include "PlatformContextSkia.h"
+#include "PlatformString.h"
+#include "SkiaUtils.h"
+#include "SkShader.h"
+#include "TransformationMatrix.h"
+
+#include "skia/ext/image_operations.h"
+#include "skia/ext/platform_canvas.h"
+
+namespace WebCore {
+
+// Used by computeResamplingMode to tell how bitmaps should be resampled.
+enum ResamplingMode {
+ // Nearest neighbor resampling. Used when we detect that the page is
+ // trying to make a pattern by stretching a small bitmap very large.
+ RESAMPLE_NONE,
+
+ // Default skia resampling. Used for large growing of images where high
+ // quality resampling doesn't get us very much except a slowdown.
+ RESAMPLE_LINEAR,
+
+ // High quality resampling.
+ RESAMPLE_AWESOME,
+};
+
+static ResamplingMode computeResamplingMode(const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight)
+{
+ int destIWidth = static_cast<int>(destWidth);
+ int destIHeight = static_cast<int>(destHeight);
+
+ // The percent change below which we will not resample. This usually means
+ // an off-by-one error on the web page, and just doing nearest neighbor
+ // sampling is usually good enough.
+ const float kFractionalChangeThreshold = 0.025f;
+
+ // Images smaller than this in either direction are considered "small" and
+ // are not resampled ever (see below).
+ const int kSmallImageSizeThreshold = 8;
+
+ // The amount an image can be stretched in a single direction before we
+ // say that it is being stretched so much that it must be a line or
+ // background that doesn't need resampling.
+ const float kLargeStretch = 3.0f;
+
+ // Figure out if we should resample this image. We try to prune out some
+ // common cases where resampling won't give us anything, since it is much
+ // slower than drawing stretched.
+ if (srcWidth == destIWidth && srcHeight == destIHeight) {
+ // We don't need to resample if the source and destination are the same.
+ return RESAMPLE_NONE;
+ }
+
+ if (srcWidth <= kSmallImageSizeThreshold
+ || srcHeight <= kSmallImageSizeThreshold
+ || destWidth <= kSmallImageSizeThreshold
+ || destHeight <= kSmallImageSizeThreshold) {
+ // Never resample small images. These are often used for borders and
+ // rules (think 1x1 images used to make lines).
+ return RESAMPLE_NONE;
+ }
+
+ if (srcHeight * kLargeStretch <= destHeight || srcWidth * kLargeStretch <= destWidth) {
+ // Large image detected.
+
+ // Don't resample if it is being stretched a lot in only one direction.
+ // This is trying to catch cases where somebody has created a border
+ // (which might be large) and then is stretching it to fill some part
+ // of the page.
+ if (srcWidth == destWidth || srcHeight == destHeight)
+ return RESAMPLE_NONE;
+
+ // The image is growing a lot and in more than one direction. Resampling
+ // is slow and doesn't give us very much when growing a lot.
+ return RESAMPLE_LINEAR;
+ }
+
+ if ((fabs(destWidth - srcWidth) / srcWidth < kFractionalChangeThreshold)
+ && (fabs(destHeight - srcHeight) / srcHeight < kFractionalChangeThreshold)) {
+ // It is disappointingly common on the web for image sizes to be off by
+ // one or two pixels. We don't bother resampling if the size difference
+ // is a small fraction of the original size.
+ return RESAMPLE_NONE;
+ }
+
+ // When the image is not yet done loading, use linear. We don't cache the
+ // partially resampled images, and as they come in incrementally, it causes
+ // us to have to resample the whole thing every time.
+ if (!bitmap.isDataComplete())
+ return RESAMPLE_LINEAR;
+
+ // Everything else gets resampled.
+ return RESAMPLE_AWESOME;
+}
+
+// Draws the given bitmap to the given canvas. The subset of the source bitmap
+// identified by src_rect is drawn to the given destination rect. The bitmap
+// will be resampled to resample_width * resample_height (this is the size of
+// the whole image, not the subset). See shouldResampleBitmap for more.
+//
+// This does a lot of computation to resample only the portion of the bitmap
+// that will only be drawn. This is critical for performance since when we are
+// scrolling, for example, we are only drawing a small strip of the image.
+// Resampling the whole image every time is very slow, so this speeds up things
+// dramatically.
+static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeImageSkia& bitmap, const SkIRect& srcIRect, const SkRect& destRect)
+{
+ // First get the subset we need. This is efficient and does not copy pixels.
+ SkBitmap subset;
+ bitmap.extractSubset(&subset, srcIRect);
+ SkRect srcRect;
+ srcRect.set(srcIRect);
+
+ // Whether we're doing a subset or using the full source image.
+ bool srcIsFull = srcIRect.fLeft == 0 && srcIRect.fTop == 0
+ && srcIRect.width() == bitmap.width()
+ && srcIRect.height() == bitmap.height();
+
+ // We will always draw in integer sizes, so round the destination rect.
+ SkIRect destRectRounded;
+ destRect.round(&destRectRounded);
+ SkIRect resizedImageRect; // Represents the size of the resized image.
+ resizedImageRect.set(0, 0, destRectRounded.width(), destRectRounded.height());
+
+ if (srcIsFull && bitmap.hasResizedBitmap(destRectRounded.width(), destRectRounded.height())) {
+ // Yay, this bitmap frame already has a resized version.
+ SkBitmap resampled = bitmap.resizedBitmap(destRectRounded.width(), destRectRounded.height());
+ canvas.drawBitmapRect(resampled, 0, destRect, &paint);
+ return;
+ }
+
+ // Compute the visible portion of our rect.
+ SkRect destBitmapSubsetSk;
+ ClipRectToCanvas(canvas, destRect, &destBitmapSubsetSk);
+ destBitmapSubsetSk.offset(-destRect.fLeft, -destRect.fTop);
+
+ // The matrix inverting, etc. could have introduced rounding error which
+ // causes the bounds to be outside of the resized bitmap. We round outward
+ // so we always lean toward it being larger rather than smaller than we
+ // need, and then clamp to the bitmap bounds so we don't get any invalid
+ // data.
+ SkIRect destBitmapSubsetSkI;
+ destBitmapSubsetSk.roundOut(&destBitmapSubsetSkI);
+ if (!destBitmapSubsetSkI.intersect(resizedImageRect))
+ return; // Resized image does not intersect.
+
+ if (srcIsFull && bitmap.shouldCacheResampling(
+ resizedImageRect.width(),
+ resizedImageRect.height(),
+ destBitmapSubsetSkI.width(),
+ destBitmapSubsetSkI.height())) {
+ // We're supposed to resize the entire image and cache it, even though
+ // we don't need all of it.
+ SkBitmap resampled = bitmap.resizedBitmap(destRectRounded.width(),
+ destRectRounded.height());
+ canvas.drawBitmapRect(resampled, 0, destRect, &paint);
+ } else {
+ // We should only resize the exposed part of the bitmap to do the
+ // minimal possible work.
+ gfx::Rect destBitmapSubset(destBitmapSubsetSkI.fLeft,
+ destBitmapSubsetSkI.fTop,
+ destBitmapSubsetSkI.width(),
+ destBitmapSubsetSkI.height());
+
+ // Resample the needed part of the image.
+ SkBitmap resampled = skia::ImageOperations::Resize(subset,
+ skia::ImageOperations::RESIZE_LANCZOS3,
+ destRectRounded.width(), destRectRounded.height(),
+ destBitmapSubset);
+
+ // Compute where the new bitmap should be drawn. Since our new bitmap
+ // may be smaller than the original, we have to shift it over by the
+ // same amount that we cut off the top and left.
+ SkRect offsetDestRect = {
+ destBitmapSubset.x() + destRect.fLeft,
+ destBitmapSubset.y() + destRect.fTop,
+ destBitmapSubset.right() + destRect.fLeft,
+ destBitmapSubset.bottom() + destRect.fTop };
+
+ canvas.drawBitmapRect(resampled, 0, offsetDestRect, &paint);
+ }
+}
+
+static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkPorterDuff::Mode& compOp)
+{
+ SkPaint paint;
+ paint.setPorterDuffXfermode(compOp);
+
+ skia::PlatformCanvas* canvas = platformContext->canvas();
+
+ ResamplingMode resampling = platformContext->isPrinting() ? RESAMPLE_NONE :
+ computeResamplingMode(bitmap, srcRect.width(), srcRect.height(),
+ SkScalarToFloat(destRect.width()),
+ SkScalarToFloat(destRect.height()));
+ if (resampling == RESAMPLE_AWESOME) {
+ paint.setFilterBitmap(false);
+ drawResampledBitmap(*canvas, paint, bitmap, srcRect, destRect);
+ } else {
+ // No resampling necessary, we can just draw the bitmap. We want to
+ // filter it if we decided to do linear interpolation above, or if there
+ // is something interesting going on with the matrix (like a rotation).
+ // Note: for serialization, we will want to subset the bitmap first so
+ // we don't send extra pixels.
+ paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);
+ canvas->drawBitmapRect(bitmap, &srcRect, destRect, &paint);
+ }
+}
+
+// Transforms the given dimensions with the given matrix. Used to see how big
+// images will be once transformed.
+static void TransformDimensions(const SkMatrix& matrix, float srcWidth, float srcHeight, float* destWidth, float* destHeight) {
+ // Transform 3 points to see how long each side of the bitmap will be.
+ SkPoint src_points[3]; // (0, 0), (width, 0), (0, height).
+ src_points[0].set(0, 0);
+ src_points[1].set(SkFloatToScalar(srcWidth), 0);
+ src_points[2].set(0, SkFloatToScalar(srcHeight));
+
+ // Now measure the length of the two transformed vectors relative to the
+ // transformed origin to see how big the bitmap will be. Note: for skews,
+ // this isn't the best thing, but we don't have skews.
+ SkPoint dest_points[3];
+ matrix.mapPoints(dest_points, src_points, 3);
+ *destWidth = SkScalarToFloat((dest_points[1] - dest_points[0]).length());
+ *destHeight = SkScalarToFloat((dest_points[2] - dest_points[0]).length());
+}
+
+// A helper method for translating negative width and height values.
+static FloatRect normalizeRect(const FloatRect& rect)
+{
+ FloatRect norm = rect;
+ if (norm.width() < 0) {
+ norm.setX(norm.x() + norm.width());
+ norm.setWidth(-norm.width());
+ }
+ if (norm.height() < 0) {
+ norm.setY(norm.y() + norm.height());
+ norm.setHeight(-norm.height());
+ }
+ return norm;
+}
+
+bool FrameData::clear(bool clearMetadata)
+{
+ if (clearMetadata)
+ m_haveMetadata = false;
+
+ if (m_frame) {
+ // ImageSource::createFrameAtIndex() allocated |m_frame| and passed
+ // ownership to BitmapImage; we must delete it here.
+ delete m_frame;
+ m_frame = 0;
+ return true;
+ }
+ return false;
+}
+
+PassRefPtr<Image> Image::loadPlatformResource(const char *name)
+{
+ return ChromiumBridge::loadPlatformImageResource(name);
+}
+
+void Image::drawPattern(GraphicsContext* context,
+ const FloatRect& floatSrcRect,
+ const TransformationMatrix& patternTransform,
+ const FloatPoint& phase,
+ CompositeOperator compositeOp,
+ const FloatRect& destRect)
+{
+ if (destRect.isEmpty() || floatSrcRect.isEmpty())
+ return; // nothing to draw
+
+ NativeImageSkia* bitmap = nativeImageForCurrentFrame();
+ if (!bitmap)
+ return;
+
+ // This is a very inexpensive operation. It will generate a new bitmap but
+ // 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);
+ bitmap->extractSubset(&srcSubset, srcRect);
+
+ SkBitmap resampled;
+ SkShader* shader;
+
+ // Figure out what size the bitmap will be in the destination. The
+ // destination rect is the bounds of the pattern, we need to use the
+ // matrix to see how bit it will be.
+ float destBitmapWidth, destBitmapHeight;
+ TransformDimensions(patternTransform, srcRect.width(), srcRect.height(),
+ &destBitmapWidth, &destBitmapHeight);
+
+ // Compute the resampling mode.
+ ResamplingMode resampling;
+ if (context->platformContext()->isPrinting())
+ resampling = RESAMPLE_LINEAR;
+ else {
+ resampling = computeResamplingMode(*bitmap,
+ srcRect.width(), srcRect.height(),
+ destBitmapWidth, destBitmapHeight);
+ }
+
+ // Load the transform WebKit requested.
+ SkMatrix matrix(patternTransform);
+
+ if (resampling == RESAMPLE_AWESOME) {
+ // Do nice resampling.
+ SkBitmap resampled = skia::ImageOperations::Resize(srcSubset,
+ skia::ImageOperations::RESIZE_LANCZOS3,
+ static_cast<int>(destBitmapWidth),
+ static_cast<int>(destBitmapHeight));
+ shader = SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
+
+ // Since we just resized the bitmap, we need to undo the scale set in
+ // the image transform.
+ matrix.setScaleX(SkIntToScalar(1));
+ matrix.setScaleY(SkIntToScalar(1));
+ } else {
+ // No need to do nice resampling.
+ shader = SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
+ }
+
+ // We also need to translate it such that the origin of the pattern is the
+ // 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() *
+ narrowPrecisionToFloat(patternTransform.a());
+ float adjustedY = phase.y() + floatSrcRect.y() *
+ narrowPrecisionToFloat(patternTransform.d());
+ matrix.postTranslate(SkFloatToScalar(adjustedX),
+ SkFloatToScalar(adjustedY));
+ shader->setLocalMatrix(matrix);
+
+ SkPaint paint;
+ paint.setShader(shader)->unref();
+ paint.setPorterDuffXfermode(WebCoreCompositeToSkiaComposite(compositeOp));
+ paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);
+
+ context->platformContext()->paintSkPaint(destRect, paint);
+}
+
+// ================================================
+// BitmapImage Class
+// ================================================
+
+// FIXME: These should go to BitmapImageSkia.cpp
+
+void BitmapImage::initPlatformData()
+{
+ // This is not used. On Mac, the "platform" data is a cache of some OS
+ // specific versions of the image that are created is some cases. These
+ // aren't normally used, it is equivalent to getHBITMAP on Windows, and
+ // the platform data is the cache.
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+ // See initPlatformData above.
+}
+
+void BitmapImage::checkForSolidColor()
+{
+}
+
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
+ const FloatRect& srcRect, CompositeOperator compositeOp)
+{
+ if (!m_source.initialized())
+ return;
+
+ // Spin the animation to the correct frame before we try to draw it, so we
+ // don't draw an old frame and then immediately need to draw a newer one,
+ // causing flicker and wasting CPU.
+ startAnimation();
+
+ const NativeImageSkia* bm = nativeImageForCurrentFrame();
+ if (!bm)
+ return; // It's too early and we don't have an image yet.
+
+ FloatRect normDstRect = normalizeRect(dstRect);
+ FloatRect normSrcRect = normalizeRect(srcRect);
+
+ if (normSrcRect.isEmpty() || normDstRect.isEmpty())
+ return; // Nothing to draw.
+
+ paintSkBitmap(ctxt->platformContext(),
+ *bm,
+ enclosingIntRect(normSrcRect),
+ enclosingIntRect(normDstRect),
+ WebCoreCompositeToSkiaComposite(compositeOp));
+}
+
+// FIXME: These should go into BitmapImageSingleFrameSkia.cpp
+
+void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt,
+ const FloatRect& dstRect,
+ const FloatRect& srcRect,
+ CompositeOperator compositeOp)
+{
+ FloatRect normDstRect = normalizeRect(dstRect);
+ FloatRect normSrcRect = normalizeRect(srcRect);
+
+ if (normSrcRect.isEmpty() || normDstRect.isEmpty())
+ return; // Nothing to draw.
+
+ paintSkBitmap(ctxt->platformContext(),
+ m_nativeImage,
+ enclosingIntRect(normSrcRect),
+ enclosingIntRect(normDstRect),
+ WebCoreCompositeToSkiaComposite(compositeOp));
+}
+
+PassRefPtr<BitmapImageSingleFrameSkia> BitmapImageSingleFrameSkia::create(const SkBitmap& bitmap)
+{
+ RefPtr<BitmapImageSingleFrameSkia> image(adoptRef(new BitmapImageSingleFrameSkia()));
+ if (!bitmap.copyTo(&image->m_nativeImage, bitmap.config()))
+ return 0;
+ return image.release();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/ImageSourceSkia.cpp b/WebCore/platform/graphics/skia/ImageSourceSkia.cpp
new file mode 100644
index 0000000..f77620b
--- /dev/null
+++ b/WebCore/platform/graphics/skia/ImageSourceSkia.cpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "ImageSourceSkia.h"
+#include "SharedBuffer.h"
+
+#include "GIFImageDecoder.h"
+#include "JPEGImageDecoder.h"
+#include "PNGImageDecoder.h"
+#include "BMPImageDecoder.h"
+#include "XBMImageDecoder.h"
+#include "ICOImageDecoder.h"
+
+#include "SkBitmap.h"
+
+namespace WebCore {
+
+ImageDecoder* createDecoder(const Vector<char>& data, const IntSize& preferredIconSize)
+{
+ // We need at least 4 bytes to figure out what kind of image we're dealing with.
+ int length = data.size();
+ if (length < 4)
+ return 0;
+
+ const unsigned char* uContents = (const unsigned char*)data.data();
+ const char* contents = data.data();
+
+ // GIFs begin with GIF8(7 or 9).
+ if (strncmp(contents, "GIF8", 4) == 0)
+ return new GIFImageDecoder();
+
+ // Test for PNG.
+ if (uContents[0]==0x89 &&
+ uContents[1]==0x50 &&
+ uContents[2]==0x4E &&
+ uContents[3]==0x47)
+ return new PNGImageDecoder();
+
+ // JPEG
+ if (uContents[0]==0xFF &&
+ uContents[1]==0xD8 &&
+ uContents[2]==0xFF)
+ return new JPEGImageDecoder();
+
+ // BMP
+ if (strncmp(contents, "BM", 2) == 0)
+ return new BMPImageDecoder();
+
+ // ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
+ // CURs begin with 2-byte 0 followed by 2-byte 2.
+ if (!memcmp(contents, "\000\000\001\000", 4) ||
+ !memcmp(contents, "\000\000\002\000", 4))
+ return new ICOImageDecoder(preferredIconSize);
+
+ // XBMs require 8 bytes of info.
+ if (length >= 8 && strncmp(contents, "#define ", 8) == 0)
+ return new XBMImageDecoder();
+
+ // Give up. We don't know what the heck this is.
+ return 0;
+}
+
+ImageSource::ImageSource()
+ : m_decoder(0)
+{}
+
+ImageSource::~ImageSource()
+{
+ clear(true);
+}
+
+void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
+{
+ // TODO(darin): Figure out what to do with the |data| and |allDataReceived| params.
+
+ if (destroyAll) {
+ delete m_decoder;
+ m_decoder = 0;
+ return;
+ }
+
+ if (m_decoder)
+ m_decoder->clearFrameBufferCache(clearBeforeFrame);
+}
+
+bool ImageSource::initialized() const
+{
+ return m_decoder;
+}
+
+void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
+{
+ // Make the decoder by sniffing the bytes.
+ // This method will examine the data and instantiate an instance of the appropriate decoder plugin.
+ // If insufficient bytes are available to determine the image type, no decoder plugin will be
+ // made.
+ if (!m_decoder)
+ m_decoder = createDecoder(data->buffer(), IntSize());
+
+ // CreateDecoder will return NULL if the decoder could not be created. Plus,
+ // we should not send more data to a decoder which has already decided it
+ // has failed.
+ if (!m_decoder || m_decoder->failed())
+ return;
+ m_decoder->setData(data, allDataReceived);
+}
+
+bool ImageSource::isSizeAvailable()
+{
+ if (!m_decoder)
+ return false;
+
+ return m_decoder->isSizeAvailable();
+}
+
+IntSize ImageSource::size() const
+{
+ if (!m_decoder)
+ return IntSize();
+
+ return m_decoder->size();
+}
+
+IntSize ImageSource::frameSizeAtIndex(size_t) const
+{
+ // TODO(brettw) do we need anything here?
+ return size();
+}
+
+int ImageSource::repetitionCount()
+{
+ if (!m_decoder)
+ return cAnimationNone;
+
+ return m_decoder->repetitionCount();
+}
+
+size_t ImageSource::frameCount() const
+{
+ if (!m_decoder)
+ return 0;
+ return m_decoder->failed() ? 0 : m_decoder->frameCount();
+}
+
+NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
+{
+ if (!m_decoder)
+ return 0;
+
+ // Note that the buffer can have NULL bytes even when it is marked as
+ // non-empty. It seems "FrameEmpty" is only set before the frame has been
+ // initialized. If it is decoded and it happens to be empty, it will be
+ // marked as "FrameComplete" but will still have NULL bytes.
+ RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
+ if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
+ return 0;
+
+ // Copy the bitmap. The pixel data is refcounted internally by SkBitmap, so
+ // this doesn't cost much. This pointer will be owned by the BitmapImage
+ // and freed in FrameData::clear().
+ return new NativeImageSkia(buffer->bitmap());
+}
+
+bool ImageSource::frameIsCompleteAtIndex(size_t index)
+{
+ if (!m_decoder)
+ return false;
+
+ RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
+ return buffer && buffer->status() == RGBA32Buffer::FrameComplete;
+}
+
+float ImageSource::frameDurationAtIndex(size_t index)
+{
+ if (!m_decoder)
+ return 0;
+
+ RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
+ if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
+ return 0;
+
+ // Many annoying ads specify a 0 duration to make an image flash as quickly
+ // as possible. We follow WinIE's behavior and use a duration of 100 ms
+ // for any frames that specify a duration of <= 50 ms. See
+ // <http://bugs.webkit.org/show_bug.cgi?id=14413> or Radar 4051389 for
+ // more.
+ const float duration = buffer->duration() / 1000.0f;
+ return (duration < 0.051f) ? 0.100f : duration;
+}
+
+bool ImageSource::frameHasAlphaAtIndex(size_t index)
+{
+ if (!m_decoder || !m_decoder->supportsAlpha())
+ return false;
+
+ RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
+ if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
+ return false;
+
+ return buffer->hasAlpha();
+}
+
+void ImageSourceSkia::setData(SharedBuffer* data,
+ bool allDataReceived,
+ const IntSize& preferredIconSize)
+{
+ if (!m_decoder)
+ m_decoder = createDecoder(data->buffer(), preferredIconSize);
+
+ ImageSource::setData(data, allDataReceived);
+}
+
+String ImageSource::filenameExtension() const
+{
+ return m_decoder ? m_decoder->filenameExtension() : String();
+}
+
+}
diff --git a/WebCore/platform/graphics/skia/ImageSourceSkia.h b/WebCore/platform/graphics/skia/ImageSourceSkia.h
new file mode 100644
index 0000000..9cb4a95
--- /dev/null
+++ b/WebCore/platform/graphics/skia/ImageSourceSkia.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ImageSource.h"
+
+namespace WebCore {
+
+class ImageSourceSkia : public ImageSource {
+public:
+ // FIXME: This class is a hack to support Chromium's ICO decoder
+ // Currently our ICO decoder decodes all data during setData() instead of
+ // being lazy. In addition, it only decodes one frame (closest to the size
+ // passed to the decoder during createDecoder, called from setData) and
+ // discards all other data in the file.
+ //
+ // To fix this will require fixing the ICO decoder to be lazy, or to decode
+ // all frames. Apple's decoders (ImageIO) decode all frames, and return
+ // them all sorted in decreasing size. WebCore always draws the first frame.
+ //
+ // This is a special-purpose routine for the favicon decoder, which is used
+ // to specify a particular icon size for the ICOImageDecoder to prefer
+ // decoding. Note that not all favicons are ICOs, so this won't
+ // necessarily do anything differently than ImageSource::setData().
+ //
+ // Passing an empty IntSize for |preferredIconSize| here is exactly
+ // equivalent to just calling ImageSource::setData(). See also comments in
+ // ICOImageDecoder.cpp.
+ void setData(SharedBuffer* data,
+ bool allDataReceived,
+ const IntSize& preferredIconSize);
+};
+
+}
diff --git a/WebCore/platform/graphics/skia/IntPointSkia.cpp b/WebCore/platform/graphics/skia/IntPointSkia.cpp
new file mode 100644
index 0000000..fd9a6fd
--- /dev/null
+++ b/WebCore/platform/graphics/skia/IntPointSkia.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IntPoint.h"
+
+#include "SkPoint.h"
+
+namespace WebCore {
+
+IntPoint::IntPoint(const SkIPoint& p)
+ : m_x(p.fX)
+ , m_y(p.fY)
+{
+}
+
+IntPoint::operator SkIPoint() const
+{
+ SkIPoint p = { m_x, m_y };
+ return p;
+}
+
+IntPoint::operator SkPoint() const
+{
+ SkPoint p = { SkIntToScalar(m_x), SkIntToScalar(m_y) };
+ return p;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/IntRectSkia.cpp b/WebCore/platform/graphics/skia/IntRectSkia.cpp
new file mode 100644
index 0000000..ea138ee
--- /dev/null
+++ b/WebCore/platform/graphics/skia/IntRectSkia.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IntRect.h"
+
+#include "SkRect.h"
+
+namespace WebCore {
+
+IntRect::operator SkIRect() const
+{
+ SkIRect rect = { x(), y(), right(), bottom() };
+ return rect;
+}
+
+IntRect::operator SkRect() const
+{
+ SkRect rect;
+ rect.set(SkIntToScalar(x()), SkIntToScalar(y()), SkIntToScalar(right()), SkIntToScalar(bottom()));
+ return rect;
+}
+
+IntRect::IntRect(const SkIRect& r)
+ : m_location(r.fLeft, r.fTop)
+ , m_size(r.width(), r.height())
+{
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/NativeImageSkia.cpp b/WebCore/platform/graphics/skia/NativeImageSkia.cpp
new file mode 100644
index 0000000..e59d1e2
--- /dev/null
+++ b/WebCore/platform/graphics/skia/NativeImageSkia.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "skia/ext/image_operations.h"
+
+#include "NativeImageSkia.h"
+#include "SkiaUtils.h"
+
+NativeImageSkia::NativeImageSkia()
+ : m_isDataComplete(false),
+ m_lastRequestSize(0, 0),
+ m_resizeRequests(0)
+{
+}
+
+int NativeImageSkia::decodedSize() const
+{
+ return getSize() + m_resizedImage.getSize();
+}
+
+bool NativeImageSkia::hasResizedBitmap(int w, int h) const
+{
+ if (m_lastRequestSize.width() == w && m_lastRequestSize.height() == h)
+ m_resizeRequests++;
+ else {
+ m_lastRequestSize = WebCore::IntSize(w, h);
+ m_resizeRequests = 0;
+ }
+
+ return m_resizedImage.width() == w && m_resizedImage.height() == h;
+}
+
+// FIXME: don't cache when image is in-progress.
+
+SkBitmap NativeImageSkia::resizedBitmap(int w, int h) const
+{
+ if (m_resizedImage.width() != w || m_resizedImage.height() != h)
+ m_resizedImage = skia::ImageOperations::Resize(*this, skia::ImageOperations::RESIZE_LANCZOS3, w, h);
+
+ return m_resizedImage;
+}
+
+bool NativeImageSkia::shouldCacheResampling(int destWidth,
+ int destHeight,
+ int destSubsetWidth,
+ int destSubsetHeight) const
+{
+ // We can not cache incomplete frames. This might be a good optimization in
+ // the future, were we know how much of the frame has been decoded, so when
+ // we incrementally draw more of the image, we only have to resample the
+ // parts that are changed.
+ if (!m_isDataComplete)
+ return false;
+
+ // If the destination bitmap is small, we'll always allow caching, since
+ // there is not very much penalty for computing it and it may come in handy.
+ static const int kSmallBitmapSize = 4096;
+ if (destWidth * destHeight <= kSmallBitmapSize)
+ return true;
+
+ // If "too many" requests have been made for this bitmap, we assume that
+ // many more will be made as well, and we'll go ahead and cache it.
+ static const int kManyRequestThreshold = 4;
+ if (m_lastRequestSize.width() == destWidth &&
+ m_lastRequestSize.height() == destHeight) {
+ if (m_resizeRequests >= kManyRequestThreshold)
+ return true;
+ } else {
+ // When a different size is being requested, count this as a query
+ // (hasResizedBitmap) and reset the counter.
+ m_lastRequestSize = WebCore::IntSize(destWidth, destHeight);
+ m_resizeRequests = 0;
+ }
+
+ // Otherwise, use the heuristic that if more than 1/4 of the image is
+ // requested, it's worth caching.
+ int destSize = destWidth * destHeight;
+ int destSubsetSize = destSubsetWidth * destSubsetHeight;
+ return destSize / 4 < destSubsetSize;
+}
diff --git a/WebCore/platform/graphics/skia/NativeImageSkia.h b/WebCore/platform/graphics/skia/NativeImageSkia.h
new file mode 100644
index 0000000..5947238
--- /dev/null
+++ b/WebCore/platform/graphics/skia/NativeImageSkia.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NativeImageSkia_h
+#define NativeImageSkia_h
+
+#include "SkBitmap.h"
+#include "IntSize.h"
+
+// This object is used as the "native image" in our port. When WebKit uses
+// "NativeImagePtr", it is a pointer to this type. It is an SkBitmap, but also
+// stores a cached resized image.
+class NativeImageSkia : public SkBitmap {
+public:
+ NativeImageSkia();
+
+ // Returns the number of bytes of image data. This includes the cached
+ // resized version if there is one.
+ int decodedSize() const;
+
+ // Sets the data complete flag. This is called by the image decoder when
+ // all data is complete, and used by us to know whether we can cache
+ // resized images.
+ void setDataComplete() { m_isDataComplete = true; }
+
+ // Returns true if the entire image has been decoded.
+ bool isDataComplete() const { return m_isDataComplete; }
+
+ // We can keep a resized version of the bitmap cached on this object.
+ // This function will return true if there is a cached version of the
+ // given image subset with the given dimensions.
+ bool hasResizedBitmap(int width, int height) const;
+
+ // This will return an existing resized image, or generate a new one of
+ // the specified size and store it in the cache. Subsetted images can not
+ // be cached unless the subset is the entire bitmap.
+ SkBitmap resizedBitmap(int width, int height) const;
+
+ // Returns true if the given resize operation should either resize the whole
+ // image and cache it, or resize just the part it needs and throw the result
+ // away.
+ //
+ // On the one hand, if only a small subset is desired, then we will waste a
+ // lot of time resampling the entire thing, so we only want to do exactly
+ // what's required. On the other hand, resampling the entire bitmap is
+ // better if we're going to be using it more than once (like a bitmap
+ // scrolling on and off the screen. Since we only cache when doing the
+ // entire thing, it's best to just do it up front.
+ bool shouldCacheResampling(int destWidth,
+ int destHeight,
+ int destSubsetWidth,
+ int destSubsetHeight) const;
+
+private:
+ // Set to true when the data is complete. Before the entire image has
+ // loaded, we do not want to cache a resize.
+ bool m_isDataComplete;
+
+ // The cached bitmap. This will be empty() if there is no cached image.
+ mutable SkBitmap m_resizedImage;
+
+ // References how many times that the image size has been requested for
+ // the last size.
+ //
+ // Every time we get a request, if it matches the m_lastRequestSize, we'll
+ // increment the counter, and if not, we'll reset the counter and save the
+ // size.
+ //
+ // This allows us to see if many requests have been made for the same
+ // resized image, we know that we should probably cache it, even if all of
+ // those requests individually are small and would not otherwise be cached.
+ mutable WebCore::IntSize m_lastRequestSize;
+ mutable int m_resizeRequests;
+};
+
+#endif // NativeImageSkia_h
+
diff --git a/WebCore/platform/graphics/skia/PathSkia.cpp b/WebCore/platform/graphics/skia/PathSkia.cpp
new file mode 100644
index 0000000..ca99322
--- /dev/null
+++ b/WebCore/platform/graphics/skia/PathSkia.cpp
@@ -0,0 +1,316 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "config.h"
+#include "Path.h"
+
+#include "FloatRect.h"
+#include "ImageBuffer.h"
+#include "StrokeStyleApplier.h"
+
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkiaUtils.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+Path::Path()
+{
+ m_path = new SkPath;
+}
+
+Path::Path(const Path& other)
+{
+ m_path = new SkPath(*other.m_path);
+}
+
+Path::~Path()
+{
+ delete m_path;
+}
+
+Path& Path::operator=(const Path& other)
+{
+ *m_path = *other.m_path;
+ return *this;
+}
+
+bool Path::isEmpty() const
+{
+ return m_path->isEmpty();
+}
+
+bool Path::contains(const FloatPoint& point, WindRule rule) const
+{
+ return SkPathContainsPoint(m_path, point,
+ rule == RULE_NONZERO ? SkPath::kWinding_FillType : SkPath::kEvenOdd_FillType);
+}
+
+void Path::translate(const FloatSize& size)
+{
+ m_path->offset(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height()));
+}
+
+FloatRect Path::boundingRect() const
+{
+ SkRect rect;
+ m_path->computeBounds(&rect, SkPath::kExact_BoundsType);
+ return rect;
+}
+
+void Path::moveTo(const FloatPoint& point)
+{
+ m_path->moveTo(point);
+}
+
+void Path::addLineTo(const FloatPoint& point)
+{
+ m_path->lineTo(point);
+}
+
+void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& ep)
+{
+ m_path->quadTo(cp, ep);
+}
+
+void Path::addBezierCurveTo(const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& ep)
+{
+ m_path->cubicTo(p1, p2, ep);
+}
+
+void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
+{
+ m_path->arcTo(p1, p2, WebCoreFloatToSkScalar(radius));
+}
+
+void Path::closeSubpath()
+{
+ m_path->close();
+}
+
+void Path::addArc(const FloatPoint& p, float r, float sa, float ea, bool anticlockwise) {
+ SkScalar cx = WebCoreFloatToSkScalar(p.x());
+ SkScalar cy = WebCoreFloatToSkScalar(p.y());
+ SkScalar radius = WebCoreFloatToSkScalar(r);
+
+ SkRect oval;
+ oval.set(cx - radius, cy - radius, cx + radius, cy + radius);
+
+ float sweep = ea - sa;
+ // check for a circle
+ if (sweep >= 2 * piFloat || sweep <= -2 * piFloat)
+ m_path->addOval(oval);
+ else {
+ SkScalar startDegrees = WebCoreFloatToSkScalar(sa * 180 / piFloat);
+ SkScalar sweepDegrees = WebCoreFloatToSkScalar(sweep * 180 / piFloat);
+
+ // Counterclockwise arcs should be drawn with negative sweeps, while
+ // clockwise arcs should be drawn with positive sweeps. Check to see
+ // if the situation is reversed and correct it by adding or subtracting
+ // a full circle
+ if (anticlockwise && sweepDegrees > 0) {
+ sweepDegrees -= SkIntToScalar(360);
+ } else if (!anticlockwise && sweepDegrees < 0) {
+ sweepDegrees += SkIntToScalar(360);
+ }
+
+ m_path->arcTo(oval, startDegrees, sweepDegrees, false);
+ }
+}
+
+void Path::addRect(const FloatRect& rect)
+{
+ m_path->addRect(rect);
+}
+
+void Path::addEllipse(const FloatRect& rect)
+{
+ m_path->addOval(rect);
+}
+
+void Path::clear()
+{
+ m_path->reset();
+}
+
+static FloatPoint* convertPathPoints(FloatPoint dst[], const SkPoint src[], int count)
+{
+ for (int i = 0; i < count; i++) {
+ dst[i].setX(SkScalarToFloat(src[i].fX));
+ dst[i].setY(SkScalarToFloat(src[i].fY));
+ }
+ return dst;
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ SkPath::Iter iter(*m_path, false);
+ SkPoint pts[4];
+ PathElement pathElement;
+ FloatPoint pathPoints[3];
+
+ for (;;) {
+ switch (iter.next(pts)) {
+ case SkPath::kMove_Verb:
+ pathElement.type = PathElementMoveToPoint;
+ pathElement.points = convertPathPoints(pathPoints, &pts[0], 1);
+ break;
+ case SkPath::kLine_Verb:
+ pathElement.type = PathElementAddLineToPoint;
+ pathElement.points = convertPathPoints(pathPoints, &pts[1], 1);
+ break;
+ case SkPath::kQuad_Verb:
+ pathElement.type = PathElementAddQuadCurveToPoint;
+ pathElement.points = convertPathPoints(pathPoints, &pts[1], 2);
+ break;
+ case SkPath::kCubic_Verb:
+ pathElement.type = PathElementAddCurveToPoint;
+ pathElement.points = convertPathPoints(pathPoints, &pts[1], 3);
+ break;
+ case SkPath::kClose_Verb:
+ pathElement.type = PathElementCloseSubpath;
+ pathElement.points = convertPathPoints(pathPoints, 0, 0);
+ break;
+ case SkPath::kDone_Verb:
+ return;
+ }
+ function(info, &pathElement);
+ }
+}
+
+void Path::transform(const TransformationMatrix& xform)
+{
+ m_path->transform(xform);
+}
+
+String Path::debugString() const
+{
+ String result;
+
+ SkPath::Iter iter(*m_path, false);
+ SkPoint pts[4];
+
+ int numPoints = m_path->getPoints(0, 0);
+ SkPath::Verb verb;
+
+ do {
+ verb = iter.next(pts);
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ result += String::format("M%.2f,%.2f ", pts[0].fX, pts[0].fY);
+ numPoints -= 1;
+ break;
+ case SkPath::kLine_Verb:
+ if (!iter.isCloseLine()) {
+ result += String::format("L%.2f,%.2f ", pts[1].fX, pts[1].fY);
+ numPoints -= 1;
+ }
+ break;
+ case SkPath::kQuad_Verb:
+ result += String::format("Q%.2f,%.2f,%.2f,%.2f ",
+ pts[1].fX, pts[1].fY,
+ pts[2].fX, pts[2].fY);
+ numPoints -= 2;
+ break;
+ case SkPath::kCubic_Verb:
+ result += String::format("C%.2f,%.2f,%.2f,%.2f,%.2f,%.2f ",
+ pts[1].fX, pts[1].fY,
+ pts[2].fX, pts[2].fY,
+ pts[3].fX, pts[3].fY);
+ numPoints -= 3;
+ break;
+ case SkPath::kClose_Verb:
+ result += "Z ";
+ break;
+ case SkPath::kDone_Verb:
+ break;
+ }
+ } while (verb != SkPath::kDone_Verb);
+
+ // If you have a path that ends with an M, Skia will not iterate the
+ // trailing M. That's nice of it, but Apple's paths output the trailing M
+ // and we want out layout dumps to look like theirs
+ if (numPoints) {
+ ASSERT(numPoints==1);
+ m_path->getLastPt(pts);
+ result += String::format("M%.2f,%.2f ", pts[0].fX, pts[0].fY);
+ }
+
+ return result.stripWhiteSpace();
+}
+
+// Computes the bounding box for the stroke and style currently selected into
+// the given bounding box. This also takes into account the stroke width.
+static FloatRect boundingBoxForCurrentStroke(const GraphicsContext* context)
+{
+ SkPaint paint;
+ context->platformContext()->setupPaintForStroking(&paint, 0, 0);
+ SkPath boundingPath;
+ paint.getFillPath(context->platformContext()->currentPath(), &boundingPath);
+ SkRect r;
+ boundingPath.computeBounds(&r, SkPath::kExact_BoundsType);
+ return r;
+}
+
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+{
+ GraphicsContext* scratch = scratchContext();
+ scratch->save();
+ scratch->beginPath();
+ scratch->addPath(*this);
+
+ if (applier)
+ applier->strokeStyle(scratch);
+
+ FloatRect r = boundingBoxForCurrentStroke(scratch);
+ scratch->restore();
+ return r;
+}
+
+bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
+{
+ ASSERT(applier);
+ GraphicsContext* scratch = scratchContext();
+ scratch->save();
+
+ applier->strokeStyle(scratch);
+
+ SkPaint paint;
+ scratch->platformContext()->setupPaintForStroking(&paint, 0, 0);
+ SkPath strokePath;
+ paint.getFillPath(*platformPath(), &strokePath);
+ bool contains = SkPathContainsPoint(&strokePath, point,
+ SkPath::kWinding_FillType);
+
+ scratch->restore();
+ return contains;
+}
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/PatternSkia.cpp b/WebCore/platform/graphics/skia/PatternSkia.cpp
new file mode 100644
index 0000000..be8eb8a
--- /dev/null
+++ b/WebCore/platform/graphics/skia/PatternSkia.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Pattern.h"
+
+#include "Image.h"
+#include "NativeImageSkia.h"
+#include "TransformationMatrix.h"
+
+#include "SkShader.h"
+#include "SkCanvas.h"
+
+namespace WebCore {
+
+PlatformPatternPtr Pattern::createPlatformPattern(const TransformationMatrix& patternTransform) const
+{
+ // Note: patternTransform is ignored since it seems to be applied elsewhere
+ // (when the pattern is used?). Applying it to the pattern (i.e.
+ // shader->setLocalMatrix) results in a double transformation. This can be
+ // seen, for instance, as an extra offset in:
+ // LayoutTests/fast/canvas/patternfill-repeat.html
+ // and expanded scale and skew in:
+ // LayoutTests/svg/W3C-SVG-1.1/pservers-grad-06-b.svg
+
+ SkBitmap* bm = m_tileImage->nativeImageForCurrentFrame();
+ if (m_repeatX && m_repeatY)
+ return SkShader::CreateBitmapShader(*bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
+
+ // Skia does not have a "draw the tile only once" option. Clamp_TileMode
+ // repeats the last line of the image after drawing one tile. To avoid
+ // filling the space with arbitrary pixels, this workaround forces the
+ // image to have a line of transparent pixels on the "repeated" edge(s),
+ // thus causing extra space to be transparent filled.
+ SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
+ SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
+ int expandW = m_repeatX ? 0 : 1;
+ int expandH = m_repeatY ? 0 : 1;
+
+ // Create a transparent bitmap 1 pixel wider and/or taller than the
+ // original, then copy the orignal into it.
+ // FIXME: Is there a better way to pad (not scale) an image in skia?
+ SkBitmap bm2;
+ bm2.setConfig(bm->config(), bm->width() + expandW, bm->height() + expandH);
+ bm2.allocPixels();
+ bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
+ SkCanvas canvas(bm2);
+ canvas.drawBitmap(*bm, 0, 0);
+ return SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
new file mode 100644
index 0000000..60dbbe0
--- /dev/null
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "GraphicsContext.h"
+#include "NativeImageSkia.h"
+#include "PlatformContextSkia.h"
+#include "SkiaUtils.h"
+
+#include "skia/ext/image_operations.h"
+#include "skia/ext/platform_canvas.h"
+
+#include "SkBitmap.h"
+#include "SkColorPriv.h"
+#include "SkShader.h"
+#include "SkDashPathEffect.h"
+
+#include <wtf/MathExtras.h>
+
+#if defined(__linux__)
+#include "GdkSkia.h"
+#endif
+
+// State -----------------------------------------------------------------------
+
+// Encapsulates the additional painting state information we store for each
+// pushed graphics state.
+struct PlatformContextSkia::State {
+ State();
+ State(const State&);
+ ~State();
+
+ // Common shader state.
+ float m_alpha;
+ SkPorterDuff::Mode m_porterDuffMode;
+ SkShader* m_gradient;
+ SkShader* m_pattern;
+ bool m_useAntialiasing;
+ SkDrawLooper* m_looper;
+
+ // Fill.
+ SkColor m_fillColor;
+
+ // Stroke.
+ WebCore::StrokeStyle m_strokeStyle;
+ SkColor m_strokeColor;
+ float m_strokeThickness;
+ int m_dashRatio; // Ratio of the length of a dash to its width.
+ float m_miterLimit;
+ SkPaint::Cap m_lineCap;
+ SkPaint::Join m_lineJoin;
+ SkDashPathEffect* m_dash;
+
+ // Text. (See cTextFill & friends in GraphicsContext.h.)
+ int m_textDrawingMode;
+
+ // Helper function for applying the state's alpha value to the given input
+ // color to produce a new output color.
+ SkColor applyAlpha(SkColor) const;
+
+private:
+ // Not supported.
+ void operator=(const State&);
+};
+
+// Note: Keep theses default values in sync with GraphicsContextState.
+PlatformContextSkia::State::State()
+ : m_alpha(1)
+ , m_porterDuffMode(SkPorterDuff::kSrcOver_Mode)
+ , m_gradient(0)
+ , m_pattern(0)
+ , m_useAntialiasing(true)
+ , m_looper(0)
+ , m_fillColor(0xFF000000)
+ , m_strokeStyle(WebCore::SolidStroke)
+ , m_strokeColor(WebCore::Color::black)
+ , m_strokeThickness(0)
+ , m_dashRatio(3)
+ , m_miterLimit(4)
+ , m_lineCap(SkPaint::kDefault_Cap)
+ , m_lineJoin(SkPaint::kDefault_Join)
+ , m_dash(0)
+ , m_textDrawingMode(WebCore::cTextFill)
+{
+}
+
+PlatformContextSkia::State::State(const State& other)
+{
+ memcpy(this, &other, sizeof(State));
+
+ m_looper->safeRef();
+ m_dash->safeRef();
+ m_gradient->safeRef();
+ m_pattern->safeRef();
+}
+
+PlatformContextSkia::State::~State()
+{
+ m_looper->safeUnref();
+ m_dash->safeUnref();
+ m_gradient->safeUnref();
+ m_pattern->safeUnref();
+}
+
+SkColor PlatformContextSkia::State::applyAlpha(SkColor c) const
+{
+ int s = roundf(m_alpha * 256);
+ if (s >= 256)
+ return c;
+ if (s < 0)
+ return 0;
+
+ int a = SkAlphaMul(SkColorGetA(c), s);
+ return (c & 0x00FFFFFF) | (a << 24);
+}
+
+// PlatformContextSkia ---------------------------------------------------------
+
+// Danger: canvas can be NULL.
+PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas)
+ : m_canvas(canvas)
+ , m_stateStack(sizeof(State))
+{
+ m_stateStack.append(State());
+ m_state = &m_stateStack.last();
+#if defined(OS_LINUX)
+ m_gdkskia = m_canvas ? gdk_skia_new(m_canvas) : 0;
+#endif
+}
+
+PlatformContextSkia::~PlatformContextSkia()
+{
+#if defined(OS_LINUX)
+ if (m_gdkskia) {
+ g_object_unref(m_gdkskia);
+ m_gdkskia = 0;
+ }
+#endif
+}
+
+void PlatformContextSkia::setCanvas(skia::PlatformCanvas* canvas)
+{
+ m_canvas = canvas;
+}
+
+void PlatformContextSkia::save()
+{
+ m_stateStack.append(*m_state);
+ m_state = &m_stateStack.last();
+
+ // Save our native canvas.
+ canvas()->save();
+}
+
+void PlatformContextSkia::restore()
+{
+ m_stateStack.removeLast();
+ m_state = &m_stateStack.last();
+
+ // Restore our native canvas.
+ canvas()->restore();
+}
+
+void PlatformContextSkia::drawRect(SkRect rect)
+{
+ SkPaint paint;
+ int fillcolorNotTransparent = m_state->m_fillColor & 0xFF000000;
+ if (fillcolorNotTransparent) {
+ setupPaintForFilling(&paint);
+ canvas()->drawRect(rect, paint);
+ }
+
+ if (m_state->m_strokeStyle != WebCore::NoStroke &&
+ (m_state->m_strokeColor & 0xFF000000)) {
+ if (fillcolorNotTransparent) {
+ // This call is expensive so don't call it unnecessarily.
+ paint.reset();
+ }
+ setupPaintForStroking(&paint, &rect, 0);
+ canvas()->drawRect(rect, paint);
+ }
+}
+
+void PlatformContextSkia::setupPaintCommon(SkPaint* paint) const
+{
+#ifdef SK_DEBUGx
+ {
+ SkPaint defaultPaint;
+ SkASSERT(*paint == defaultPaint);
+ }
+#endif
+
+ paint->setAntiAlias(m_state->m_useAntialiasing);
+ paint->setPorterDuffXfermode(m_state->m_porterDuffMode);
+ paint->setLooper(m_state->m_looper);
+
+ if (m_state->m_gradient)
+ paint->setShader(m_state->m_gradient);
+ else if (m_state->m_pattern)
+ paint->setShader(m_state->m_pattern);
+}
+
+void PlatformContextSkia::setupPaintForFilling(SkPaint* paint) const
+{
+ setupPaintCommon(paint);
+ paint->setColor(m_state->applyAlpha(m_state->m_fillColor));
+}
+
+float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, int length) const
+{
+ setupPaintCommon(paint);
+ float width = m_state->m_strokeThickness;
+
+ // This allows dashing and dotting to work properly for hairline strokes.
+ if (width == 0)
+ width = 1;
+
+ paint->setColor(m_state->applyAlpha(m_state->m_strokeColor));
+ paint->setStyle(SkPaint::kStroke_Style);
+ paint->setStrokeWidth(SkFloatToScalar(width));
+ paint->setStrokeCap(m_state->m_lineCap);
+ paint->setStrokeJoin(m_state->m_lineJoin);
+ paint->setStrokeMiter(SkFloatToScalar(m_state->m_miterLimit));
+
+ if (rect != 0 && (static_cast<int>(roundf(width)) & 1))
+ rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
+
+ if (m_state->m_dash)
+ paint->setPathEffect(m_state->m_dash);
+ else {
+ switch (m_state->m_strokeStyle) {
+ case WebCore::NoStroke:
+ case WebCore::SolidStroke:
+ break;
+ case WebCore::DashedStroke:
+ width = m_state->m_dashRatio * width;
+ // Fall through.
+ case WebCore::DottedStroke:
+ SkScalar dashLength;
+ if (length) {
+ // Determine about how many dashes or dots we should have.
+ int numDashes = length / roundf(width);
+ if (!(numDashes & 1))
+ numDashes++; // Make it odd so we end on a dash/dot.
+ // Use the number of dashes to determine the length of a
+ // dash/dot, which will be approximately width
+ dashLength = SkScalarDiv(SkIntToScalar(length), SkIntToScalar(numDashes));
+ } else
+ dashLength = SkFloatToScalar(width);
+ SkScalar intervals[2] = { dashLength, dashLength };
+ paint->setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();
+ }
+ }
+
+ return width;
+}
+
+void PlatformContextSkia::setDrawLooper(SkDrawLooper* dl)
+{
+ SkRefCnt_SafeAssign(m_state->m_looper, dl);
+}
+
+void PlatformContextSkia::setMiterLimit(float ml)
+{
+ m_state->m_miterLimit = ml;
+}
+
+void PlatformContextSkia::setAlpha(float alpha)
+{
+ m_state->m_alpha = alpha;
+}
+
+void PlatformContextSkia::setLineCap(SkPaint::Cap lc)
+{
+ m_state->m_lineCap = lc;
+}
+
+void PlatformContextSkia::setLineJoin(SkPaint::Join lj)
+{
+ m_state->m_lineJoin = lj;
+}
+
+void PlatformContextSkia::setPorterDuffMode(SkPorterDuff::Mode pdm)
+{
+ m_state->m_porterDuffMode = pdm;
+}
+
+void PlatformContextSkia::setFillColor(SkColor color)
+{
+ m_state->m_fillColor = color;
+}
+
+SkDrawLooper* PlatformContextSkia::getDrawLooper() const
+{
+ return m_state->m_looper;
+}
+
+WebCore::StrokeStyle PlatformContextSkia::getStrokeStyle() const
+{
+ return m_state->m_strokeStyle;
+}
+
+void PlatformContextSkia::setStrokeStyle(WebCore::StrokeStyle strokeStyle)
+{
+ m_state->m_strokeStyle = strokeStyle;
+}
+
+void PlatformContextSkia::setStrokeColor(SkColor strokeColor)
+{
+ m_state->m_strokeColor = strokeColor;
+}
+
+float PlatformContextSkia::getStrokeThickness() const
+{
+ return m_state->m_strokeThickness;
+}
+
+void PlatformContextSkia::setStrokeThickness(float thickness)
+{
+ m_state->m_strokeThickness = thickness;
+}
+
+int PlatformContextSkia::getTextDrawingMode() const
+{
+ return m_state->m_textDrawingMode;
+}
+
+void PlatformContextSkia::setTextDrawingMode(int mode)
+{
+ // cTextClip is never used, so we assert that it isn't set:
+ // https://bugs.webkit.org/show_bug.cgi?id=21898
+ ASSERT((mode & WebCore::cTextClip) == 0);
+ m_state->m_textDrawingMode = mode;
+}
+
+void PlatformContextSkia::setUseAntialiasing(bool enable)
+{
+ m_state->m_useAntialiasing = enable;
+}
+
+SkColor PlatformContextSkia::fillColor() const
+{
+ return m_state->m_fillColor;
+}
+
+void PlatformContextSkia::beginPath()
+{
+ m_path.reset();
+}
+
+void PlatformContextSkia::addPath(const SkPath& path)
+{
+ m_path.addPath(path);
+}
+
+void PlatformContextSkia::setFillRule(SkPath::FillType fr)
+{
+ m_path.setFillType(fr);
+}
+
+void PlatformContextSkia::setGradient(SkShader* gradient)
+{
+ if (gradient != m_state->m_gradient) {
+ m_state->m_gradient->safeUnref();
+ m_state->m_gradient = gradient;
+ }
+}
+
+void PlatformContextSkia::setPattern(SkShader* pattern)
+{
+ if (pattern != m_state->m_pattern) {
+ m_state->m_pattern->safeUnref();
+ m_state->m_pattern = pattern;
+ }
+}
+
+void PlatformContextSkia::setDashPathEffect(SkDashPathEffect* dash)
+{
+ if (dash != m_state->m_dash) {
+ m_state->m_dash->safeUnref();
+ m_state->m_dash = dash;
+ }
+}
+
+void PlatformContextSkia::paintSkPaint(const SkRect& rect,
+ const SkPaint& paint)
+{
+ m_canvas->drawRect(rect, paint);
+}
+
+const SkBitmap* PlatformContextSkia::bitmap() const
+{
+ return &m_canvas->getDevice()->accessBitmap(false);
+}
+
+bool PlatformContextSkia::isPrinting()
+{
+ return m_canvas->getTopPlatformDevice().IsVectorial();
+}
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h
new file mode 100644
index 0000000..78e9a19
--- /dev/null
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PlatformContextSkia_h
+#define PlatformContextSkia_h
+
+#include "GraphicsContext.h"
+#include "Noncopyable.h"
+
+#include "SkDashPathEffect.h"
+#include "SkDrawLooper.h"
+#include "SkDeque.h"
+#include "skia/ext/platform_canvas.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+
+#include <wtf/Vector.h>
+
+typedef struct _GdkDrawable GdkSkia;
+
+// This class holds the platform-specific state for GraphicsContext. We put
+// most of our Skia wrappers on this class. In theory, a lot of this stuff could
+// be moved to GraphicsContext directly, except that some code external to this
+// would like to poke at our graphics layer as well (like the Image and Font
+// stuff, which needs some amount of our wrappers and state around SkCanvas).
+//
+// So in general, this class uses just Skia types except when there's no easy
+// conversion. GraphicsContext is responsible for converting the WebKit types to
+// Skia types and setting up the eventual call to the Skia functions.
+//
+// This class then keeps track of all the current Skia state. WebKit expects
+// that the graphics state that is pushed and popped by save() and restore()
+// includes things like colors and pen styles. Skia does this differently, where
+// push and pop only includes transforms and bitmaps, and the application is
+// responsible for managing the painting state which is store in separate
+// SkPaint objects. This class provides the adaptor that allows the painting
+// state to be pushed and popped along with the bitmap.
+class PlatformContextSkia : Noncopyable {
+public:
+ // For printing, there shouldn't be any canvas. canvas can be NULL. If you
+ // supply a NULL canvas, you can also call setCanvas later.
+ PlatformContextSkia(skia::PlatformCanvas*);
+ ~PlatformContextSkia();
+
+ // Sets the canvas associated with this context. Use when supplying NULL
+ // to the constructor.
+ void setCanvas(skia::PlatformCanvas*);
+
+ void save();
+ void restore();
+
+ // Sets up the common flags on a paint for antialiasing, effects, etc.
+ // This is implicitly called by setupPaintFill and setupPaintStroke, but
+ // you may wish to call it directly sometimes if you don't want that other
+ // behavior.
+ void setupPaintCommon(SkPaint*) const;
+
+ // Sets up the paint for the current fill style.
+ void setupPaintForFilling(SkPaint*) const;
+
+ // Sets up the paint for stroking. Returns an int representing the width of
+ // the pen, or 1 if the pen's width is 0 if a non-zero length is provided,
+ // the number of dashes/dots on a dashed/dotted line will be adjusted to
+ // start and end that length with a dash/dot.
+ float setupPaintForStroking(SkPaint*, SkRect*, int length) const;
+
+ // State setting functions.
+ void setDrawLooper(SkDrawLooper*); // Note: takes an additional ref.
+ void setMiterLimit(float);
+ void setAlpha(float);
+ void setLineCap(SkPaint::Cap);
+ void setLineJoin(SkPaint::Join);
+ void setFillRule(SkPath::FillType);
+ void setPorterDuffMode(SkPorterDuff::Mode);
+ void setFillColor(SkColor);
+ void setStrokeStyle(WebCore::StrokeStyle);
+ void setStrokeColor(SkColor);
+ void setStrokeThickness(float thickness);
+ void setTextDrawingMode(int mode);
+ void setUseAntialiasing(bool enable);
+ void setGradient(SkShader*);
+ void setPattern(SkShader*);
+ void setDashPathEffect(SkDashPathEffect*);
+
+ SkDrawLooper* getDrawLooper() const;
+ WebCore::StrokeStyle getStrokeStyle() const;
+ float getStrokeThickness() const;
+ int getTextDrawingMode() const;
+
+ void beginPath();
+ void addPath(const SkPath&);
+ const SkPath* currentPath() const { return &m_path; }
+
+ SkColor fillColor() const;
+
+ skia::PlatformCanvas* canvas() { return m_canvas; }
+
+ // FIXME: This should be pushed down to GraphicsContext.
+ void drawRect(SkRect rect);
+
+ // FIXME: I'm still unsure how I will serialize this call.
+ void paintSkPaint(const SkRect&, const SkPaint&);
+
+ const SkBitmap* bitmap() const;
+
+ // Returns the canvas used for painting, NOT guaranteed to be non-NULL.
+ //
+ // Warning: This function is deprecated so the users are reminded that they
+ // should use this layer of indirection instead of using the canvas
+ // directly. This is to help with the eventual serialization.
+ skia::PlatformCanvas* canvas() const;
+
+ // Returns if the context is a printing context instead of a display
+ // context. Bitmap shouldn't be resampled when printing to keep the best
+ // possible quality.
+ bool isPrinting();
+
+#if defined(__linux__)
+ // FIXME: should be camelCase.
+ GdkSkia* gdk_skia() const { return m_gdkskia; }
+#endif
+
+private:
+ // Defines drawing style.
+ struct State;
+
+ // NULL indicates painting is disabled. Never delete this object.
+ skia::PlatformCanvas* m_canvas;
+
+ // States stack. Enables local drawing state change with save()/restore()
+ // calls.
+ WTF::Vector<State> m_stateStack;
+ // Pointer to the current drawing state. This is a cached value of
+ // mStateStack.back().
+ State* m_state;
+
+ // Current path.
+ SkPath m_path;
+
+#if defined(__linux__)
+ // A pointer to a GDK Drawable wrapping of this Skia canvas
+ GdkSkia* m_gdkskia;
+#endif
+};
+
+#endif // PlatformContextSkia_h
diff --git a/WebCore/platform/graphics/skia/PlatformGraphics.h b/WebCore/platform/graphics/skia/PlatformGraphics.h
new file mode 100644
index 0000000..4ae8835
--- /dev/null
+++ b/WebCore/platform/graphics/skia/PlatformGraphics.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PlatformGraphics_h
+#define PlatformGraphics_h
+
+typedef class SkShader* PlatformGradient;
+typedef class SkShader* PlatformPattern;
+
+#endif // PlatformGraphics_h
diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp
new file mode 100644
index 0000000..6e79a7e
--- /dev/null
+++ b/WebCore/platform/graphics/skia/SkiaFontWin.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SkiaFontWin.h"
+
+#include "SkCanvas.h"
+#include "SkPaint.h"
+
+#include <wtf/ListHashSet.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+struct CachedOutlineKey {
+ CachedOutlineKey() : font(0), glyph(0), path(0) {}
+ CachedOutlineKey(HFONT f, WORD g) : font(f), glyph(g), path(0) {}
+
+ HFONT font;
+ WORD glyph;
+
+ // The lifetime of this pointer is managed externally to this class. Be sure
+ // to call DeleteOutline to remove items.
+ SkPath* path;
+};
+
+const bool operator==(const CachedOutlineKey& a, const CachedOutlineKey& b)
+{
+ return a.font == b.font && a.glyph == b.glyph;
+}
+
+struct CachedOutlineKeyHash {
+ static unsigned hash(const CachedOutlineKey& key)
+ {
+ unsigned keyBytes;
+ memcpy(&keyBytes, &key.font, sizeof(unsigned));
+ return keyBytes + key.glyph;
+ }
+
+ static unsigned equal(const CachedOutlineKey& a, const CachedOutlineKey& b)
+ {
+ return a.font == b.font && a.glyph == b.glyph;
+ }
+
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+typedef ListHashSet<CachedOutlineKey, CachedOutlineKeyHash> OutlineCache;
+
+// FIXME: Convert from static constructor to accessor function. WebCore tries to
+// avoid global constructors to save on start-up time.
+static OutlineCache outlineCache;
+
+// The global number of glyph outlines we'll cache.
+static const int outlineCacheSize = 256;
+
+static SkScalar FIXEDToSkScalar(FIXED fixed)
+{
+ SkFixed skFixed;
+ memcpy(&skFixed, &fixed, sizeof(SkFixed));
+ return SkFixedToScalar(skFixed);
+}
+
+// Removes the given key from the cached outlines, also deleting the path.
+static void deleteOutline(OutlineCache::iterator deleteMe)
+{
+ delete deleteMe->path;
+ outlineCache.remove(deleteMe);
+}
+
+static void addPolyCurveToPath(const TTPOLYCURVE* polyCurve, SkPath* path)
+{
+ switch (polyCurve->wType) {
+ case TT_PRIM_LINE:
+ for (WORD i = 0; i < polyCurve->cpfx; i++) {
+ path->lineTo(FIXEDToSkScalar(polyCurve->apfx[i].x), -FIXEDToSkScalar(polyCurve->apfx[i].y));
+ }
+ break;
+
+ case TT_PRIM_QSPLINE:
+ // FIXME: doesn't this duplicate points if we do the loop > once?
+ for (WORD i = 0; i < polyCurve->cpfx - 1; i++) {
+ SkScalar bx = FIXEDToSkScalar(polyCurve->apfx[i].x);
+ SkScalar by = FIXEDToSkScalar(polyCurve->apfx[i].y);
+
+ SkScalar cx = FIXEDToSkScalar(polyCurve->apfx[i + 1].x);
+ SkScalar cy = FIXEDToSkScalar(polyCurve->apfx[i + 1].y);
+ if (i < polyCurve->cpfx - 2) {
+ // We're not the last point, compute C.
+ cx = SkScalarAve(bx, cx);
+ cy = SkScalarAve(by, cy);
+ }
+
+ // Need to flip the y coordinates since the font's coordinate system is
+ // flipped from ours vertically.
+ path->quadTo(bx, -by, cx, -cy);
+ }
+ break;
+
+ case TT_PRIM_CSPLINE:
+ // FIXME
+ break;
+ }
+}
+
+// The size of the glyph path buffer.
+static const int glyphPathBufferSize = 4096;
+
+// Fills the given SkPath with the outline for the given glyph index. The font
+// currently selected into the given DC is used. Returns true on success.
+static bool getPathForGlyph(HDC dc, WORD glyph, SkPath* path)
+{
+ char buffer[glyphPathBufferSize];
+ GLYPHMETRICS gm;
+ MAT2 mat = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; // Each one is (fract,value).
+
+ DWORD totalSize = GetGlyphOutlineW(dc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE,
+ &gm, glyphPathBufferSize, buffer, &mat);
+ if (totalSize == GDI_ERROR)
+ return false;
+
+ const char* curGlyph = buffer;
+ const char* endGlyph = &buffer[totalSize];
+ while (curGlyph < endGlyph) {
+ const TTPOLYGONHEADER* polyHeader =
+ reinterpret_cast<const TTPOLYGONHEADER*>(curGlyph);
+ path->moveTo(FIXEDToSkScalar(polyHeader->pfxStart.x),
+ -FIXEDToSkScalar(polyHeader->pfxStart.y));
+
+ const char* curPoly = curGlyph + sizeof(TTPOLYGONHEADER);
+ const char* endPoly = curGlyph + polyHeader->cb;
+ while (curPoly < endPoly) {
+ const TTPOLYCURVE* polyCurve =
+ reinterpret_cast<const TTPOLYCURVE*>(curPoly);
+ addPolyCurveToPath(polyCurve, path);
+ curPoly += sizeof(WORD) * 2 + sizeof(POINTFX) * polyCurve->cpfx;
+ }
+ curGlyph += polyHeader->cb;
+ }
+
+ path->close();
+ return true;
+}
+
+// Returns a SkPath corresponding to the give glyph in the given font. The font
+// should be selected into the given DC. The returned path is owned by the
+// hashtable. Returns 0 on error.
+const SkPath* SkiaWinOutlineCache::lookupOrCreatePathForGlyph(HDC hdc, HFONT font, WORD glyph)
+{
+ CachedOutlineKey key(font, glyph);
+ OutlineCache::iterator found = outlineCache.find(key);
+ if (found != outlineCache.end()) {
+ // Keep in MRU order by removing & reinserting the value.
+ key = *found;
+ outlineCache.remove(found);
+ outlineCache.add(key);
+ return key.path;
+ }
+
+ key.path = new SkPath;
+ if (!getPathForGlyph(hdc, glyph, key.path))
+ return 0;
+
+ if (outlineCache.size() > outlineCacheSize)
+ // The cache is too big, find the oldest value (first in the list).
+ deleteOutline(outlineCache.begin());
+
+ outlineCache.add(key);
+ return key.path;
+}
+
+
+void SkiaWinOutlineCache::removePathsForFont(HFONT hfont)
+{
+ // ListHashSet isn't the greatest structure for deleting stuff out of, but
+ // removing entries will be relatively rare (we don't remove fonts much, nor
+ // do we draw out own glyphs using these routines much either).
+ //
+ // We keep a list of all glyphs we're removing which we do in a separate
+ // pass.
+ Vector<CachedOutlineKey> outlinesToDelete;
+ for (OutlineCache::iterator i = outlineCache.begin();
+ i != outlineCache.end(); ++i)
+ outlinesToDelete.append(*i);
+
+ for (Vector<CachedOutlineKey>::iterator i = outlinesToDelete.begin();
+ i != outlinesToDelete.end(); ++i)
+ deleteOutline(outlineCache.find(*i));
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.h b/WebCore/platform/graphics/skia/SkiaFontWin.h
new file mode 100644
index 0000000..2adab39
--- /dev/null
+++ b/WebCore/platform/graphics/skia/SkiaFontWin.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SkiaWinOutlineCache_h
+#define SkiaWinOutlineCache_h
+
+#include <windows.h>
+
+class SkPath;
+
+namespace WebCore {
+
+// FIXME: Rename file to SkiaWinOutlineCache
+class SkiaWinOutlineCache {
+public:
+ static const SkPath* lookupOrCreatePathForGlyph(HDC, HFONT, WORD);
+ // Removes any cached glyphs from the outline cache corresponding to the
+ // given font handle.
+ static void removePathsForFont(HFONT);
+
+private:
+ SkiaWinOutlineCache();
+};
+
+} // namespace WebCore
+
+#endif // SkiaWinOutlineCache_h
diff --git a/WebCore/platform/graphics/skia/SkiaUtils.cpp b/WebCore/platform/graphics/skia/SkiaUtils.cpp
new file mode 100644
index 0000000..6d9ffe2
--- /dev/null
+++ b/WebCore/platform/graphics/skia/SkiaUtils.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2006,2007,2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "SkiaUtils.h"
+
+#include "ImageBuffer.h"
+#include "SharedBuffer.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkMatrix.h"
+#include "SkRegion.h"
+
+namespace WebCore {
+
+static const struct CompositOpToPorterDuffMode {
+ uint8_t mCompositOp;
+ uint8_t mPorterDuffMode;
+} gMapCompositOpsToPorterDuffModes[] = {
+ { CompositeClear, SkPorterDuff::kClear_Mode },
+ { CompositeCopy, SkPorterDuff::kSrcOver_Mode }, // TODO
+ { CompositeSourceOver, SkPorterDuff::kSrcOver_Mode },
+ { CompositeSourceIn, SkPorterDuff::kSrcIn_Mode },
+ { CompositeSourceOut, SkPorterDuff::kSrcOut_Mode },
+ { CompositeSourceAtop, SkPorterDuff::kSrcATop_Mode },
+ { CompositeDestinationOver, SkPorterDuff::kDstOver_Mode },
+ { CompositeDestinationIn, SkPorterDuff::kDstIn_Mode },
+ { CompositeDestinationOut, SkPorterDuff::kDstOut_Mode },
+ { CompositeDestinationAtop, SkPorterDuff::kDstATop_Mode },
+ { CompositeXOR, SkPorterDuff::kXor_Mode },
+ { CompositePlusDarker, SkPorterDuff::kDarken_Mode },
+ { CompositeHighlight, SkPorterDuff::kSrcOver_Mode }, // TODO
+ { CompositePlusLighter, SkPorterDuff::kLighten_Mode }
+};
+
+SkPorterDuff::Mode WebCoreCompositeToSkiaComposite(CompositeOperator op)
+{
+ const CompositOpToPorterDuffMode* table = gMapCompositOpsToPorterDuffModes;
+
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(gMapCompositOpsToPorterDuffModes); i++) {
+ if (table[i].mCompositOp == op)
+ return (SkPorterDuff::Mode)table[i].mPorterDuffMode;
+ }
+
+ SkDEBUGF(("GraphicsContext::setCompositeOperation uknown CompositeOperator %d\n", op));
+ return SkPorterDuff::kSrcOver_Mode; // fall-back
+}
+
+static U8CPU InvScaleByte(U8CPU component, uint32_t scale)
+{
+ SkASSERT(component == (uint8_t)component);
+ return (component * scale + 0x8000) >> 16;
+}
+
+SkColor SkPMColorToColor(SkPMColor pm)
+{
+ if (0 == pm)
+ return 0;
+
+ unsigned a = SkGetPackedA32(pm);
+ uint32_t scale = (255 << 16) / a;
+
+ return SkColorSetARGB(a,
+ InvScaleByte(SkGetPackedR32(pm), scale),
+ InvScaleByte(SkGetPackedG32(pm), scale),
+ InvScaleByte(SkGetPackedB32(pm), scale));
+}
+
+Color SkPMColorToWebCoreColor(SkPMColor pm)
+{
+ return SkPMColorToColor(pm);
+}
+
+void IntersectRectAndRegion(const SkRegion& region, const SkRect& srcRect, SkRect* destRect) {
+ // The cliperator requires an int rect, so we round out.
+ SkIRect srcRectRounded;
+ srcRect.roundOut(&srcRectRounded);
+
+ // The Cliperator will iterate over a bunch of rects where our transformed
+ // rect and the clipping region (which may be non-square) overlap.
+ SkRegion::Cliperator cliperator(region, srcRectRounded);
+ if (cliperator.done()) {
+ destRect->setEmpty();
+ return;
+ }
+
+ // Get the union of all visible rects in the clip that overlap our bitmap.
+ SkIRect currentVisibleRect = cliperator.rect();
+ cliperator.next();
+ while (!cliperator.done()) {
+ currentVisibleRect.join(cliperator.rect());
+ cliperator.next();
+ }
+
+ destRect->set(currentVisibleRect);
+}
+
+void ClipRectToCanvas(const SkCanvas& canvas, const SkRect& srcRect, SkRect* destRect) {
+ // Translate into the canvas' coordinate space. This is where the clipping
+ // region applies.
+ SkRect transformedSrc;
+ canvas.getTotalMatrix().mapRect(&transformedSrc, srcRect);
+
+ // Do the intersection.
+ SkRect transformedDest;
+ IntersectRectAndRegion(canvas.getTotalClip(), transformedSrc, &transformedDest);
+
+ // Now transform it back into world space.
+ SkMatrix inverseTransform;
+ canvas.getTotalMatrix().invert(&inverseTransform);
+ inverseTransform.mapRect(destRect, transformedDest);
+}
+
+bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath::FillType ft)
+{
+ SkRegion rgn;
+ SkRegion clip;
+
+ SkPath::FillType originalFillType = originalPath->getFillType();
+
+ const SkPath* path = originalPath;
+ SkPath scaledPath;
+ int scale = 1;
+
+ SkRect bounds;
+ originalPath->computeBounds(&bounds, SkPath::kFast_BoundsType);
+
+ // We can immediately return false if the point is outside the bounding rect
+ if (!bounds.contains(SkFloatToScalar(point.x()), SkFloatToScalar(point.y())))
+ return false;
+
+ originalPath->setFillType(ft);
+
+ // Skia has trouble with coordinates close to the max signed 16-bit values
+ // If we have those, we need to scale.
+ //
+ // TODO: remove this code once Skia is patched to work properly with large
+ // values
+ const SkScalar kMaxCoordinate = SkIntToScalar(1<<15);
+ SkScalar biggestCoord = std::max(std::max(std::max(bounds.fRight, bounds.fBottom), -bounds.fLeft), -bounds.fTop);
+
+ if (biggestCoord > kMaxCoordinate) {
+ scale = SkScalarCeil(SkScalarDiv(biggestCoord, kMaxCoordinate));
+
+ SkMatrix m;
+ m.setScale(SkScalarInvert(SkIntToScalar(scale)), SkScalarInvert(SkIntToScalar(scale)));
+ originalPath->transform(m, &scaledPath);
+ path = &scaledPath;
+ }
+
+ int x = static_cast<int>(floorf(point.x() / scale));
+ int y = static_cast<int>(floorf(point.y() / scale));
+ clip.setRect(x, y, x + 1, y + 1);
+
+ bool contains = rgn.setPath(*path, clip);
+
+ originalPath->setFillType(originalFillType);
+ return contains;
+}
+
+GraphicsContext* scratchContext()
+{
+ static ImageBuffer* scratch = 0;
+ if (!scratch)
+ scratch = ImageBuffer::create(IntSize(1, 1), false).release();
+ // We don't bother checking for failure creating the ImageBuffer, since our
+ // ImageBuffer initializer won't fail.
+ return scratch->context();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/SkiaUtils.h b/WebCore/platform/graphics/skia/SkiaUtils.h
new file mode 100644
index 0000000..0e68574
--- /dev/null
+++ b/WebCore/platform/graphics/skia/SkiaUtils.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2006,2007,2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// All of the functions in this file should move to new homes and this file should be deleted.
+
+#ifndef SkiaUtils_h
+#define SkiaUtils_h
+
+#include <wtf/MathExtras.h>
+#include "GraphicsContext.h"
+#include "SkPath.h"
+#include "SkPorterDuff.h"
+
+class SkCanvas;
+class SkRegion;
+
+namespace WebCore {
+
+SkPorterDuff::Mode WebCoreCompositeToSkiaComposite(CompositeOperator);
+
+// move this guy into SkColor.h
+SkColor SkPMColorToColor(SkPMColor);
+
+// This should be an operator on Color
+Color SkPMColorToWebCoreColor(SkPMColor);
+
+// Skia has problems when passed infinite, etc floats, filter them to 0.
+inline SkScalar WebCoreFloatToSkScalar(float f)
+{
+ return SkFloatToScalar(isfinite(f) ? f : 0);
+}
+
+inline SkScalar WebCoreDoubleToSkScalar(double d)
+{
+ return SkDoubleToScalar(isfinite(d) ? d : 0);
+}
+
+// Computes the smallest rectangle that, which when drawn to the given canvas,
+// will cover the same area as the source rectangle. It will clip to the canvas'
+// clip, doing the necessary coordinate transforms.
+//
+// srcRect and destRect can be the same.
+void ClipRectToCanvas(const SkCanvas&, const SkRect& srcRect, SkRect* destRect);
+
+// Determine if a given WebKit point is contained in a path
+bool SkPathContainsPoint(SkPath*, const FloatPoint&, SkPath::FillType);
+
+// Returns a statically allocated 1x1 GraphicsContext intended for temporary
+// operations. Please save() the state and restore() it when you're done with
+// the context.
+GraphicsContext* scratchContext();
+
+} // namespace WebCore
+
+#endif // SkiaUtils_h
diff --git a/WebCore/platform/graphics/skia/TransformationMatrixSkia.cpp b/WebCore/platform/graphics/skia/TransformationMatrixSkia.cpp
new file mode 100644
index 0000000..1e2a194
--- /dev/null
+++ b/WebCore/platform/graphics/skia/TransformationMatrixSkia.cpp
@@ -0,0 +1,222 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "config.h"
+#include "TransformationMatrix.h"
+
+#include "FloatRect.h"
+#include "IntRect.h"
+
+#include "SkiaUtils.h"
+
+namespace WebCore {
+
+TransformationMatrix::TransformationMatrix()
+{
+ m_transform.reset();
+}
+
+TransformationMatrix::TransformationMatrix(double a, double b, double c, double d, double e, double f)
+{
+ setMatrix(a, b, c, d, e, f);
+}
+
+TransformationMatrix::TransformationMatrix(const SkMatrix& matrix)
+ : m_transform(matrix)
+{
+}
+
+void TransformationMatrix::setMatrix(double a, double b, double c, double d, double e, double f)
+{
+ m_transform.reset();
+
+ m_transform.setScaleX(WebCoreDoubleToSkScalar(a));
+ m_transform.setSkewX(WebCoreDoubleToSkScalar(c));
+ m_transform.setTranslateX(WebCoreDoubleToSkScalar(e));
+
+ m_transform.setScaleY(WebCoreDoubleToSkScalar(d));
+ m_transform.setSkewY(WebCoreDoubleToSkScalar(b));
+ m_transform.setTranslateY(WebCoreDoubleToSkScalar(f));
+}
+
+void TransformationMatrix::map(double x, double y, double* x2, double* y2) const
+{
+ SkPoint src, dst;
+ src.set(WebCoreDoubleToSkScalar(x), WebCoreDoubleToSkScalar(y));
+ m_transform.mapPoints(&dst, &src, 1);
+
+ *x2 = SkScalarToDouble(dst.fX);
+ *y2 = SkScalarToDouble(dst.fY);
+}
+
+IntRect TransformationMatrix::mapRect(const IntRect& src) const
+{
+ SkRect dst;
+ m_transform.mapRect(&dst, src);
+ return enclosingIntRect(dst);
+}
+
+FloatRect TransformationMatrix::mapRect(const FloatRect& src) const
+{
+ SkRect dst;
+ m_transform.mapRect(&dst, src);
+ return dst;
+}
+
+bool TransformationMatrix::isIdentity() const
+{
+ return m_transform.isIdentity();
+}
+
+void TransformationMatrix::reset()
+{
+ m_transform.reset();
+}
+
+TransformationMatrix &TransformationMatrix::scale(double sx, double sy)
+{
+ m_transform.preScale(WebCoreDoubleToSkScalar(sx), WebCoreDoubleToSkScalar(sy), 0, 0);
+ return *this;
+}
+
+TransformationMatrix &TransformationMatrix::rotate(double d)
+{
+ m_transform.preRotate(WebCoreDoubleToSkScalar(d), 0, 0);
+ return *this;
+}
+
+TransformationMatrix &TransformationMatrix::translate(double tx, double ty)
+{
+ m_transform.preTranslate(WebCoreDoubleToSkScalar(tx), WebCoreDoubleToSkScalar(ty));
+ return *this;
+}
+
+TransformationMatrix &TransformationMatrix::shear(double sx, double sy)
+{
+ m_transform.preSkew(WebCoreDoubleToSkScalar(sx), WebCoreDoubleToSkScalar(sy), 0, 0);
+ return *this;
+}
+
+double TransformationMatrix::det() const
+{
+ return SkScalarToDouble(m_transform.getScaleX()) * SkScalarToDouble(m_transform.getScaleY()) -
+ SkScalarToDouble(m_transform.getSkewY()) * SkScalarToDouble(m_transform.getSkewX());
+}
+
+TransformationMatrix TransformationMatrix::inverse() const
+{
+ TransformationMatrix inverse;
+ m_transform.invert(&inverse.m_transform);
+ return inverse;
+}
+
+TransformationMatrix::operator SkMatrix() const
+{
+ return m_transform;
+}
+
+bool TransformationMatrix::operator==(const TransformationMatrix& m2) const
+{
+ return m_transform == m2.m_transform;
+}
+
+TransformationMatrix &TransformationMatrix::operator*=(const TransformationMatrix& m2)
+{
+ m_transform.setConcat(m2.m_transform, m_transform);
+ return *this;
+}
+
+TransformationMatrix TransformationMatrix::operator*(const TransformationMatrix& m2)
+{
+ TransformationMatrix cat;
+ cat.m_transform.setConcat(m2.m_transform, m_transform);
+ return cat;
+}
+
+double TransformationMatrix::a() const
+{
+ return SkScalarToDouble(m_transform.getScaleX());
+}
+
+void TransformationMatrix::setA(double a)
+{
+ m_transform.setScaleX(WebCoreDoubleToSkScalar(a));
+}
+
+double TransformationMatrix::b() const
+{
+ return SkScalarToDouble(m_transform.getSkewY());
+}
+
+void TransformationMatrix::setB(double b)
+{
+ m_transform.setSkewY(WebCoreDoubleToSkScalar(b));
+}
+
+double TransformationMatrix::c() const
+{
+ return SkScalarToDouble(m_transform.getSkewX());
+}
+
+void TransformationMatrix::setC(double c)
+{
+ m_transform.setSkewX(WebCoreDoubleToSkScalar(c));
+}
+
+double TransformationMatrix::d() const
+{
+ return SkScalarToDouble(m_transform.getScaleY());
+}
+
+void TransformationMatrix::setD(double d)
+{
+ m_transform.setScaleY(WebCoreDoubleToSkScalar(d));
+}
+
+double TransformationMatrix::e() const
+{
+ return SkScalarToDouble(m_transform.getTranslateX());
+}
+
+void TransformationMatrix::setE(double e)
+{
+ m_transform.setTranslateX(WebCoreDoubleToSkScalar(e));
+}
+
+double TransformationMatrix::f() const
+{
+ return SkScalarToDouble(m_transform.getTranslateY());
+}
+
+void TransformationMatrix::setF(double f)
+{
+ m_transform.setTranslateY(WebCoreDoubleToSkScalar(f));
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/transforms/IdentityTransformOperation.h b/WebCore/platform/graphics/transforms/IdentityTransformOperation.h
new file mode 100644
index 0000000..347737c
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/IdentityTransformOperation.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 IdentityTransformOperation_h
+#define IdentityTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class IdentityTransformOperation : public TransformOperation {
+public:
+ static PassRefPtr<IdentityTransformOperation> create()
+ {
+ return adoptRef(new IdentityTransformOperation());
+ }
+
+private:
+ virtual bool isIdentity() const { return true; }
+ virtual OperationType getOperationType() const { return IDENTITY; }
+ virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == IDENTITY; }
+
+ virtual bool operator==(const TransformOperation& o) const
+ {
+ return isSameType(o);
+ }
+
+ virtual bool apply(TransformationMatrix&, const IntSize&) const
+ {
+ return false;
+ }
+
+ virtual PassRefPtr<TransformOperation> blend(const TransformOperation*, double, bool = false)
+ {
+ return this;
+ }
+
+ IdentityTransformOperation()
+ {
+ }
+
+};
+
+} // namespace WebCore
+
+#endif // IdentityTransformOperation_h
diff --git a/WebCore/platform/graphics/transforms/MatrixTransformOperation.cpp b/WebCore/platform/graphics/transforms/MatrixTransformOperation.cpp
new file mode 100644
index 0000000..153d96d
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/MatrixTransformOperation.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "MatrixTransformOperation.h"
+
+#include <algorithm>
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> MatrixTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ // convert the TransformOperations into matrices
+ IntSize size;
+ TransformationMatrix fromT;
+ TransformationMatrix toT(m_a, m_b, m_c, m_d, m_e, m_f);
+ if (from) {
+ const MatrixTransformOperation* m = static_cast<const MatrixTransformOperation*>(from);
+ fromT.setMatrix(m->m_a, m->m_b, m->m_c, m->m_d, m->m_e, m->m_f);
+ }
+
+ if (blendToIdentity)
+ std::swap(fromT, toT);
+
+ toT.blend(fromT, progress);
+ return MatrixTransformOperation::create(toT.a(), toT.b(), toT.c(), toT.d(), toT.e(), toT.f());
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/transforms/MatrixTransformOperation.h b/WebCore/platform/graphics/transforms/MatrixTransformOperation.h
new file mode 100644
index 0000000..d272229
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/MatrixTransformOperation.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 MatrixTransformOperation_h
+#define MatrixTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class MatrixTransformOperation : public TransformOperation {
+public:
+ static PassRefPtr<MatrixTransformOperation> create(double a, double b, double c, double d, double e, double f)
+ {
+ return adoptRef(new MatrixTransformOperation(a, b, c, d, e, f));
+ }
+
+private:
+ virtual bool isIdentity() const { return m_a == 1 && m_b == 0 && m_c == 0 && m_d == 1 && m_e == 0 && m_f == 0; }
+ virtual OperationType getOperationType() const { return MATRIX; }
+ virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == MATRIX; }
+
+ virtual bool operator==(const TransformOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+
+ const MatrixTransformOperation* m = static_cast<const MatrixTransformOperation*>(&o);
+ return m_a == m->m_a && m_b == m->m_b && m_c == m->m_c && m_d == m->m_d && m_e == m->m_e && m_f == m->m_f;
+ }
+
+ virtual bool apply(TransformationMatrix& transform, const IntSize&) const
+ {
+ TransformationMatrix matrix(m_a, m_b, m_c, m_d, m_e, m_f);
+ transform = matrix * transform;
+ return false;
+ }
+
+ virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+
+ MatrixTransformOperation(double a, double b, double c, double d, double e, double f)
+ : m_a(a)
+ , m_b(b)
+ , m_c(c)
+ , m_d(d)
+ , m_e(e)
+ , m_f(f)
+ {
+ }
+
+ double m_a;
+ double m_b;
+ double m_c;
+ double m_d;
+ double m_e;
+ double m_f;
+};
+
+} // namespace WebCore
+
+#endif // MatrixTransformOperation_h
diff --git a/WebCore/platform/graphics/transforms/RotateTransformOperation.cpp b/WebCore/platform/graphics/transforms/RotateTransformOperation.cpp
new file mode 100644
index 0000000..4887cee
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/RotateTransformOperation.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RotateTransformOperation.h"
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ if (blendToIdentity)
+ return RotateTransformOperation::create(m_angle - m_angle * progress, m_type);
+
+ const RotateTransformOperation* fromOp = static_cast<const RotateTransformOperation*>(from);
+ double fromAngle = fromOp ? fromOp->m_angle : 0;
+ return RotateTransformOperation::create(fromAngle + (m_angle - fromAngle) * progress, m_type);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/transforms/RotateTransformOperation.h b/WebCore/platform/graphics/transforms/RotateTransformOperation.h
new file mode 100644
index 0000000..adc6c4c
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/RotateTransformOperation.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 RotateTransformOperation_h
+#define RotateTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class RotateTransformOperation : public TransformOperation {
+public:
+ static PassRefPtr<RotateTransformOperation> create(double angle, OperationType type)
+ {
+ return adoptRef(new RotateTransformOperation(angle, type));
+ }
+
+ virtual bool isIdentity() const { return m_angle == 0; }
+ virtual OperationType getOperationType() const { return m_type; }
+ virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
+
+ virtual bool operator==(const TransformOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const RotateTransformOperation* r = static_cast<const RotateTransformOperation*>(&o);
+ return m_angle == r->m_angle;
+ }
+
+ virtual bool apply(TransformationMatrix& transform, const IntSize& /*borderBoxSize*/) const
+ {
+ transform.rotate(m_angle);
+ return false;
+ }
+
+ virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+
+ double angle() const { return m_angle; }
+
+private:
+ RotateTransformOperation(double angle, OperationType type)
+ : m_angle(angle)
+ , m_type(type)
+ {
+ }
+
+ double m_angle;
+ OperationType m_type;
+};
+
+} // namespace WebCore
+
+#endif // RotateTransformOperation_h
diff --git a/WebCore/platform/graphics/transforms/ScaleTransformOperation.cpp b/WebCore/platform/graphics/transforms/ScaleTransformOperation.cpp
new file mode 100644
index 0000000..49a8fd8
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/ScaleTransformOperation.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ScaleTransformOperation.h"
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> ScaleTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ if (blendToIdentity)
+ return ScaleTransformOperation::create(m_x + (1. - m_x) * progress, m_y + (1. - m_y) * progress, m_type);
+
+ const ScaleTransformOperation* fromOp = static_cast<const ScaleTransformOperation*>(from);
+ double fromX = fromOp ? fromOp->m_x : 1.;
+ double fromY = fromOp ? fromOp->m_y : 1.;
+ return ScaleTransformOperation::create(fromX + (m_x - fromX) * progress, fromY + (m_y - fromY) * progress, m_type);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/transforms/ScaleTransformOperation.h b/WebCore/platform/graphics/transforms/ScaleTransformOperation.h
new file mode 100644
index 0000000..289f8a1
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/ScaleTransformOperation.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 ScaleTransformOperation_h
+#define ScaleTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class ScaleTransformOperation : public TransformOperation {
+public:
+ static PassRefPtr<ScaleTransformOperation> create(double sx, double sy, OperationType type)
+ {
+ return adoptRef(new ScaleTransformOperation(sx, sy, type));
+ }
+
+private:
+ virtual bool isIdentity() const { return m_x == 1 && m_y == 1; }
+ virtual OperationType getOperationType() const { return m_type; }
+ virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
+
+ virtual bool operator==(const TransformOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const ScaleTransformOperation* s = static_cast<const ScaleTransformOperation*>(&o);
+ return m_x == s->m_x && m_y == s->m_y;
+ }
+
+ virtual bool apply(TransformationMatrix& transform, const IntSize&) const
+ {
+ transform.scale(m_x, m_y);
+ return false;
+ }
+
+ virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+
+ ScaleTransformOperation(double sx, double sy, OperationType type)
+ : m_x(sx)
+ , m_y(sy)
+ , m_type(type)
+ {
+ }
+
+ double m_x;
+ double m_y;
+ OperationType m_type;
+};
+
+} // namespace WebCore
+
+#endif // ScaleTransformOperation_h
diff --git a/WebCore/platform/graphics/transforms/SkewTransformOperation.cpp b/WebCore/platform/graphics/transforms/SkewTransformOperation.cpp
new file mode 100644
index 0000000..2a430e9
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/SkewTransformOperation.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "SkewTransformOperation.h"
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> SkewTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ if (blendToIdentity)
+ return SkewTransformOperation::create(m_angleX - m_angleX * progress, m_angleY - m_angleY * progress, m_type);
+
+ const SkewTransformOperation* fromOp = static_cast<const SkewTransformOperation*>(from);
+ double fromAngleX = fromOp ? fromOp->m_angleX : 0;
+ double fromAngleY = fromOp ? fromOp->m_angleY : 0;
+ return SkewTransformOperation::create(fromAngleX + (m_angleX - fromAngleX) * progress, fromAngleY + (m_angleY - fromAngleY) * progress, m_type);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/transforms/SkewTransformOperation.h b/WebCore/platform/graphics/transforms/SkewTransformOperation.h
new file mode 100644
index 0000000..6343710
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/SkewTransformOperation.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 SkewTransformOperation_h
+#define SkewTransformOperation_h
+
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class SkewTransformOperation : public TransformOperation {
+public:
+ static PassRefPtr<SkewTransformOperation> create(double angleX, double angleY, OperationType type)
+ {
+ return adoptRef(new SkewTransformOperation(angleX, angleY, type));
+ }
+
+private:
+ virtual bool isIdentity() const { return m_angleX == 0 && m_angleY == 0; }
+ virtual OperationType getOperationType() const { return m_type; }
+ virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
+
+ virtual bool operator==(const TransformOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const SkewTransformOperation* s = static_cast<const SkewTransformOperation*>(&o);
+ return m_angleX == s->m_angleX && m_angleY == s->m_angleY;
+ }
+
+ virtual bool apply(TransformationMatrix& transform, const IntSize&) const
+ {
+ transform.skew(m_angleX, m_angleY);
+ return false;
+ }
+
+ virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+
+ SkewTransformOperation(double angleX, double angleY, OperationType type)
+ : m_angleX(angleX)
+ , m_angleY(angleY)
+ , m_type(type)
+ {
+ }
+
+ double m_angleX;
+ double m_angleY;
+ OperationType m_type;
+};
+
+} // namespace WebCore
+
+#endif // SkewTransformOperation_h
diff --git a/WebCore/platform/graphics/transforms/TransformOperation.h b/WebCore/platform/graphics/transforms/TransformOperation.h
new file mode 100644
index 0000000..65a0def
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/TransformOperation.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 TransformOperation_h
+#define TransformOperation_h
+
+#include "TransformationMatrix.h"
+#include "IntSize.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+// CSS Transforms (may become part of CSS3)
+
+class TransformOperation : public RefCounted<TransformOperation> {
+public:
+ enum OperationType {
+ SCALE_X, SCALE_Y, SCALE,
+ TRANSLATE_X, TRANSLATE_Y, TRANSLATE,
+ ROTATE,
+ SKEW_X, SKEW_Y, SKEW,
+ MATRIX, IDENTITY, NONE
+ };
+
+ virtual ~TransformOperation() { }
+
+ virtual bool operator==(const TransformOperation&) const = 0;
+ bool operator!=(const TransformOperation& o) const { return !(*this == o); }
+
+ virtual bool isIdentity() const = 0;
+
+ virtual bool apply(TransformationMatrix&, const IntSize& borderBoxSize) const = 0;
+
+ virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) = 0;
+
+ virtual OperationType getOperationType() const = 0;
+ virtual bool isSameType(const TransformOperation&) const { return false; }
+};
+
+} // namespace WebCore
+
+#endif // TransformOperation_h
diff --git a/WebCore/platform/graphics/transforms/TransformOperations.cpp b/WebCore/platform/graphics/transforms/TransformOperations.cpp
new file mode 100644
index 0000000..3d71480
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/TransformOperations.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "TransformOperations.h"
+
+#include "IdentityTransformOperation.h"
+
+namespace WebCore {
+
+TransformOperations::TransformOperations(bool makeIdentity)
+{
+ if (makeIdentity)
+ m_operations.append(IdentityTransformOperation::create());
+}
+
+bool TransformOperations::operator==(const TransformOperations& o) const
+{
+ if (m_operations.size() != o.m_operations.size())
+ return false;
+
+ unsigned s = m_operations.size();
+ for (unsigned i = 0; i < s; i++) {
+ if (*m_operations[i] != *o.m_operations[i])
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/transforms/TransformOperations.h b/WebCore/platform/graphics/transforms/TransformOperations.h
new file mode 100644
index 0000000..f929417
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/TransformOperations.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 TransformOperations_h
+#define TransformOperations_h
+
+#include "TransformOperation.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class TransformOperations {
+public:
+ TransformOperations(bool makeIdentity = false);
+
+ bool operator==(const TransformOperations& o) const;
+ bool operator!=(const TransformOperations& o) const
+ {
+ return !(*this == o);
+ }
+
+ void apply(const IntSize& sz, TransformationMatrix& t) const
+ {
+ for (unsigned i = 0; i < m_operations.size(); ++i)
+ m_operations[i]->apply(t, sz);
+ }
+
+ Vector<RefPtr<TransformOperation> >& operations() { return m_operations; }
+ const Vector<RefPtr<TransformOperation> >& operations() const { return m_operations; }
+
+private:
+ Vector<RefPtr<TransformOperation> > m_operations;
+};
+
+} // namespace WebCore
+
+#endif // TransformOperations_h
diff --git a/WebCore/platform/graphics/AffineTransform.cpp b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
index fdeba44..b48d572 100644
--- a/WebCore/platform/graphics/AffineTransform.cpp
+++ b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
@@ -24,18 +24,19 @@
*/
#include "config.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatRect.h"
+#include "FloatQuad.h"
#include "IntRect.h"
#include <wtf/MathExtras.h>
namespace WebCore {
-static void affineTransformDecompose(const AffineTransform& matrix, double sr[9])
+static void affineTransformDecompose(const TransformationMatrix& matrix, double sr[9])
{
- AffineTransform m(matrix);
+ TransformationMatrix m(matrix);
// Compute scaling factors
double sx = sqrt(m.a() * m.a() + m.b() * m.b());
@@ -73,7 +74,7 @@ static void affineTransformDecompose(const AffineTransform& matrix, double sr[9]
sr[7] = m.e(); sr[8] = m.f();
}
-static void affineTransformCompose(AffineTransform& m, const double sr[9])
+static void affineTransformCompose(TransformationMatrix& m, const double sr[9])
{
m.setA(sr[3]);
m.setB(sr[4]);
@@ -85,74 +86,74 @@ static void affineTransformCompose(AffineTransform& m, const double sr[9])
m.scale(sr[0], sr[1]);
}
-bool AffineTransform::isInvertible() const
+bool TransformationMatrix::isInvertible() const
{
return det() != 0.0;
}
-AffineTransform& AffineTransform::multiply(const AffineTransform& other)
+TransformationMatrix& TransformationMatrix::multiply(const TransformationMatrix& other)
{
return (*this) *= other;
}
-AffineTransform& AffineTransform::scale(double s)
+TransformationMatrix& TransformationMatrix::scale(double s)
{
return scale(s, s);
}
-AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
+TransformationMatrix& TransformationMatrix::scaleNonUniform(double sx, double sy)
{
return scale(sx, sy);
}
-AffineTransform& AffineTransform::rotateFromVector(double x, double y)
+TransformationMatrix& TransformationMatrix::rotateFromVector(double x, double y)
{
return rotate(rad2deg(atan2(y, x)));
}
-AffineTransform& AffineTransform::flipX()
+TransformationMatrix& TransformationMatrix::flipX()
{
return scale(-1.0f, 1.0f);
}
-AffineTransform& AffineTransform::flipY()
+TransformationMatrix& TransformationMatrix::flipY()
{
return scale(1.0f, -1.0f);
}
-AffineTransform& AffineTransform::skew(double angleX, double angleY)
+TransformationMatrix& TransformationMatrix::skew(double angleX, double angleY)
{
return shear(tan(deg2rad(angleX)), tan(deg2rad(angleY)));
}
-AffineTransform& AffineTransform::skewX(double angle)
+TransformationMatrix& TransformationMatrix::skewX(double angle)
{
return shear(tan(deg2rad(angle)), 0.0f);
}
-AffineTransform& AffineTransform::skewY(double angle)
+TransformationMatrix& TransformationMatrix::skewY(double angle)
{
return shear(0.0f, tan(deg2rad(angle)));
}
-AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest)
+TransformationMatrix makeMapBetweenRects(const FloatRect& source, const FloatRect& dest)
{
- AffineTransform transform;
+ TransformationMatrix transform;
transform.translate(dest.x() - source.x(), dest.y() - source.y());
transform.scale(dest.width() / source.width(), dest.height() / source.height());
return transform;
}
-IntPoint AffineTransform::mapPoint(const IntPoint& point) const
+IntPoint TransformationMatrix::mapPoint(const IntPoint& point) const
{
double x2, y2;
map(point.x(), point.y(), &x2, &y2);
-
+
// Round the point.
return IntPoint(lround(x2), lround(y2));
}
-FloatPoint AffineTransform::mapPoint(const FloatPoint& point) const
+FloatPoint TransformationMatrix::mapPoint(const FloatPoint& point) const
{
double x2, y2;
map(point.x(), point.y(), &x2, &y2);
@@ -160,7 +161,17 @@ FloatPoint AffineTransform::mapPoint(const FloatPoint& point) const
return FloatPoint(static_cast<float>(x2), static_cast<float>(y2));
}
-void AffineTransform::blend(const AffineTransform& from, double progress)
+FloatQuad TransformationMatrix::mapQuad(const FloatQuad& quad) const
+{
+ // FIXME: avoid 4 seperate library calls. Point mapping really needs
+ // to be platform-independent code.
+ return FloatQuad(mapPoint(quad.p1()),
+ mapPoint(quad.p2()),
+ mapPoint(quad.p3()),
+ mapPoint(quad.p4()));
+}
+
+void TransformationMatrix::blend(const TransformationMatrix& from, double progress)
{
double srA[9], srB[9];
diff --git a/WebCore/platform/graphics/AffineTransform.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h
index 37c6033..db121d1 100644
--- a/WebCore/platform/graphics/AffineTransform.h
+++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h
@@ -20,31 +20,28 @@
* 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 AffineTransform_h
-#define AffineTransform_h
+#ifndef TransformationMatrix_h
+#define TransformationMatrix_h
#if PLATFORM(CG)
#include <CoreGraphics/CGAffineTransform.h>
-typedef CGAffineTransform PlatformAffineTransform;
+typedef CGAffineTransform PlatformTransformationMatrix;
#elif PLATFORM(QT)
#include <QMatrix>
-typedef QMatrix PlatformAffineTransform;
+typedef QMatrix PlatformTransformationMatrix;
#elif PLATFORM(CAIRO)
#include <cairo.h>
-typedef cairo_matrix_t PlatformAffineTransform;
-#elif PLATFORM(SGL)
+typedef cairo_matrix_t PlatformTransformationMatrix;
+#elif PLATFORM(SKIA) || PLATFORM(SGL)
#include "SkMatrix.h"
-typedef SkMatrix PlatformAffineTransform;
-#elif PLATFORM(SKIA)
-#include "SkMatrix.h"
-typedef SkMatrix PlatformAffineTransform;
+typedef SkMatrix PlatformTransformationMatrix;
#elif PLATFORM(WX) && USE(WXGC)
#include <wx/defs.h>
#include <wx/graphics.h>
-typedef wxGraphicsMatrix PlatformAffineTransform;
+typedef wxGraphicsMatrix PlatformTransformationMatrix;
#endif
namespace WebCore {
@@ -53,13 +50,14 @@ class IntPoint;
class IntRect;
class FloatPoint;
class FloatRect;
+class FloatQuad;
-class AffineTransform {
+class TransformationMatrix {
public:
- AffineTransform();
- AffineTransform(double a, double b, double c, double d, double e, double f);
+ TransformationMatrix();
+ TransformationMatrix(double a, double b, double c, double d, double e, double f);
#if !PLATFORM(WX) || USE(WXGC)
- AffineTransform(const PlatformAffineTransform&);
+ TransformationMatrix(const PlatformTransformationMatrix&);
#endif
void setMatrix(double a, double b, double c, double d, double e, double f);
@@ -76,6 +74,8 @@ public:
FloatRect mapRect(const FloatRect&) const;
+ FloatQuad mapQuad(const FloatQuad&) const;
+
bool isIdentity() const;
double a() const;
@@ -98,43 +98,43 @@ public:
void reset();
- AffineTransform& multiply(const AffineTransform&);
- AffineTransform& scale(double);
- AffineTransform& scale(double sx, double sy);
- AffineTransform& scaleNonUniform(double sx, double sy);
- AffineTransform& rotate(double d);
- AffineTransform& rotateFromVector(double x, double y);
- AffineTransform& translate(double tx, double ty);
- AffineTransform& shear(double sx, double sy);
- AffineTransform& flipX();
- AffineTransform& flipY();
- AffineTransform& skew(double angleX, double angleY);
- AffineTransform& skewX(double angle);
- AffineTransform& skewY(double angle);
-
+ TransformationMatrix& multiply(const TransformationMatrix&);
+ TransformationMatrix& scale(double);
+ TransformationMatrix& scale(double sx, double sy);
+ TransformationMatrix& scaleNonUniform(double sx, double sy);
+ TransformationMatrix& rotate(double d);
+ TransformationMatrix& rotateFromVector(double x, double y);
+ TransformationMatrix& translate(double tx, double ty);
+ TransformationMatrix& shear(double sx, double sy);
+ TransformationMatrix& flipX();
+ TransformationMatrix& flipY();
+ TransformationMatrix& skew(double angleX, double angleY);
+ TransformationMatrix& skewX(double angle);
+ TransformationMatrix& skewY(double angle);
+
double det() const;
bool isInvertible() const;
- AffineTransform inverse() const;
+ TransformationMatrix inverse() const;
- void blend(const AffineTransform& from, double progress);
+ void blend(const TransformationMatrix& from, double progress);
#if !PLATFORM(WX) || USE(WXGC)
- operator PlatformAffineTransform() const;
+ operator PlatformTransformationMatrix() const;
#endif
- bool operator==(const AffineTransform&) const;
- bool operator!=(const AffineTransform& other) const { return !(*this == other); }
- AffineTransform& operator*=(const AffineTransform&);
- AffineTransform operator*(const AffineTransform&);
-
+ bool operator==(const TransformationMatrix&) const;
+ bool operator!=(const TransformationMatrix& other) const { return !(*this == other); }
+ TransformationMatrix& operator*=(const TransformationMatrix&);
+ TransformationMatrix operator*(const TransformationMatrix&);
+
private:
#if !PLATFORM(WX) || USE(WXGC)
- PlatformAffineTransform m_transform;
+ PlatformTransformationMatrix m_transform;
#endif
};
-AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest);
+TransformationMatrix makeMapBetweenRects(const FloatRect& source, const FloatRect& dest);
} // namespace WebCore
-#endif // AffineTransform_h
+#endif // TransformationMatrix_h
diff --git a/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp b/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp
new file mode 100644
index 0000000..47471c4
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "TranslateTransformOperation.h"
+
+namespace WebCore {
+
+PassRefPtr<TransformOperation> TranslateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ if (blendToIdentity)
+ return TranslateTransformOperation::create(Length(m_x.type()).blend(m_x, progress), Length(m_y.type()).blend(m_y, progress), m_type);
+
+ const TranslateTransformOperation* fromOp = static_cast<const TranslateTransformOperation*>(from);
+ Length fromX = fromOp ? fromOp->m_x : Length(m_x.type());
+ Length fromY = fromOp ? fromOp->m_y : Length(m_y.type());
+ return TranslateTransformOperation::create(m_x.blend(fromX, progress), m_y.blend(fromY, progress), m_type);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/transforms/TranslateTransformOperation.h b/WebCore/platform/graphics/transforms/TranslateTransformOperation.h
new file mode 100644
index 0000000..61ccbcc
--- /dev/null
+++ b/WebCore/platform/graphics/transforms/TranslateTransformOperation.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@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
+ * 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 TranslateTransformOperation_h
+#define TranslateTransformOperation_h
+
+#include "Length.h"
+#include "TransformOperation.h"
+
+namespace WebCore {
+
+class TranslateTransformOperation : public TransformOperation {
+public:
+ static PassRefPtr<TranslateTransformOperation> create(const Length& tx, const Length& ty, OperationType type)
+ {
+ return adoptRef(new TranslateTransformOperation(tx, ty, type));
+ }
+
+ virtual bool isIdentity() const { return m_x.calcFloatValue(1) == 0 && m_y.calcFloatValue(1) == 0; }
+ virtual OperationType getOperationType() const { return m_type; }
+ virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
+
+ virtual bool operator==(const TransformOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const TranslateTransformOperation* t = static_cast<const TranslateTransformOperation*>(&o);
+ return m_x == t->m_x && m_y == t->m_y;
+ }
+
+ virtual bool apply(TransformationMatrix& transform, const IntSize& borderBoxSize) const
+ {
+ transform.translate(m_x.calcFloatValue(borderBoxSize.width()), m_y.calcFloatValue(borderBoxSize.height()));
+ return m_x.type() == Percent || m_y.type() == Percent;
+ }
+
+ virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
+
+private:
+ TranslateTransformOperation(const Length& tx, const Length& ty, OperationType type)
+ : m_x(tx)
+ , m_y(ty)
+ , m_type(type)
+ {
+ }
+
+ Length m_x;
+ Length m_y;
+ OperationType m_type;
+};
+
+} // namespace WebCore
+
+#endif // TranslateTransformOperation_h
diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp
index 1766cd9..9ca95f3 100644
--- a/WebCore/platform/graphics/win/FontCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,7 +26,7 @@
#include "config.h"
#include "Font.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatConversion.h"
#include "GlyphBuffer.h"
#include "GraphicsContext.h"
@@ -227,7 +227,7 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
XFORM xform;
GetWorldTransform(hdc, &xform);
- AffineTransform hdcTransform(xform.eM11, xform.eM21, xform.eM12, xform.eM22, xform.eDx, xform.eDy);
+ TransformationMatrix hdcTransform(xform.eM11, xform.eM21, xform.eM12, xform.eM22, xform.eDx, xform.eDy);
CGAffineTransform initialGlyphTransform = hdcTransform.isInvertible() ? hdcTransform.inverse() : CGAffineTransformIdentity;
if (font->platformData().syntheticOblique())
initialGlyphTransform = CGAffineTransformConcat(initialGlyphTransform, CGAffineTransformMake(1, 0, tanf(syntheticObliqueAngle * piFloat / 180.0f), 1, 0, 0));
@@ -294,14 +294,18 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
int from, int numGlyphs, const FloatPoint& point) const
{
- if (font->m_font.useGDI()) {
- drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
- return;
- }
-
CGContextRef cgContext = graphicsContext->platformContext();
+ bool shouldUseFontSmoothing = WebCoreShouldUseFontSmoothing();
+
+ if (font->platformData().useGDI()) {
+ static bool canUsePlatformNativeGlyphs = wkCanUsePlatformNativeGlyphs();
+ if (!canUsePlatformNativeGlyphs || !shouldUseFontSmoothing || (graphicsContext->textDrawingMode() & cTextStroke)) {
+ drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+ return;
+ }
+ }
- uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext, WebCoreShouldUseFontSmoothing());
+ uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext, shouldUseFontSmoothing);
const FontPlatformData& platformData = font->platformData();
@@ -322,7 +326,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
FloatSize translation = glyphBuffer.offsetAt(from);
CGContextSetFontSize(cgContext, platformData.size());
- wkSetCGContextFontRenderingStyle(cgContext, font->isSystemFont(), false);
+ wkSetCGContextFontRenderingStyle(cgContext, font->isSystemFont(), false, font->platformData().useGDI());
IntSize shadowSize;
int shadowBlur;
diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp
index 49b3d76..9acc5a0 100644
--- a/WebCore/platform/graphics/win/FontCacheWin.cpp
+++ b/WebCore/platform/graphics/win/FontCacheWin.cpp
@@ -134,7 +134,7 @@ static const Vector<DWORD, 4>& getCJKCodePageMasks()
static bool initialized;
if (!initialized) {
initialized = true;
- IMLangFontLink2* langFontLink = FontCache::getFontLinkInterface();
+ IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface();
if (!langFontLink)
return codePageMasks;
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
index 26fceba..ba8afe7 100644
--- a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,6 +27,7 @@
#include "SharedBuffer.h"
#include "SoftLinking.h"
#include <ApplicationServices/ApplicationServices.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <wtf/RetainPtr.h>
// From t2embapi.h, which is missing from the Microsoft Platform SDK.
@@ -64,7 +65,10 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
ASSERT(m_fontReference);
ASSERT(T2embedLibrary());
- LOGFONT logFont;
+ static bool canUsePlatformNativeGlyphs = wkCanUsePlatformNativeGlyphs();
+ LOGFONT _logFont;
+
+ LOGFONT& logFont = canUsePlatformNativeGlyphs ? *static_cast<LOGFONT*>(malloc(sizeof(LOGFONT))) : _logFont;
if (m_name.isNull())
TTGetNewFontName(&m_fontReference, logFont.lfFaceName, LF_FACESIZE, 0, 0);
else
@@ -86,6 +90,8 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
logFont.lfWeight = bold ? 700 : 400;
HFONT hfont = CreateFontIndirect(&logFont);
+ if (canUsePlatformNativeGlyphs)
+ wkSetFontPlatformInfo(m_cgFont, &logFont, free);
return FontPlatformData(hfont, m_cgFont, size, bold, italic, renderingMode == AlternateRenderingMode);
}
diff --git a/WebCore/platform/graphics/win/FontPlatformData.h b/WebCore/platform/graphics/win/FontPlatformData.h
index d61afa8..09a8b55 100644
--- a/WebCore/platform/graphics/win/FontPlatformData.h
+++ b/WebCore/platform/graphics/win/FontPlatformData.h
@@ -45,6 +45,7 @@ public:
FontPlatformData()
#if PLATFORM(CAIRO)
: m_fontFace(0)
+ , m_scaledFont(0)
,
#else
:
diff --git a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
index bbfdb9f..c7e59ab 100644
--- a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
@@ -2,7 +2,7 @@
* This file is part of the internal font implementation. It should not be included by anyone other than
* FontMac.cpp, FontWin.cpp and Font.cpp.
*
- * Copyright (C) 2006, 2007, 2008 Apple Inc.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,6 +27,7 @@
#include "PlatformString.h"
#include "StringHash.h"
#include <ApplicationServices/ApplicationServices.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <wtf/HashMap.h>
#include <wtf/RetainPtr.h>
#include <wtf/Vector.h>
@@ -119,6 +120,11 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR*
ASSERT(m_cgFont);
}
}
+ if (m_useGDI && wkCanUsePlatformNativeGlyphs()) {
+ LOGFONT* logfont = static_cast<LOGFONT*>(malloc(sizeof(LOGFONT)));
+ GetObject(font, sizeof(*logfont), logfont);
+ wkSetFontPlatformInfo(m_cgFont.get(), logfont, free);
+ }
}
FontPlatformData::FontPlatformData(HFONT hfont, CGFontRef font, float size, bool bold, bool oblique, bool useGDI)
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index 5a4279a..dccbe6c 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "GraphicsContext.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "NotImplemented.h"
#include "Path.h"
@@ -173,6 +173,16 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo
m_data->restore();
}
+void GraphicsContext::setShouldIncludeChildWindows(bool include)
+{
+ m_data->m_shouldIncludeChildWindows = include;
+}
+
+bool GraphicsContext::shouldIncludeChildWindows() const
+{
+ return m_data->m_shouldIncludeChildWindows;
+}
+
GraphicsContext::WindowsBitmap::WindowsBitmap(HDC hdc, IntSize size)
: m_hdc(0)
, m_size(size)
@@ -222,14 +232,16 @@ GraphicsContext::WindowsBitmap* GraphicsContext::createWindowsBitmap(IntSize siz
void GraphicsContext::drawWindowsBitmap(WindowsBitmap* image, const IntPoint& point)
{
RetainPtr<CGColorSpaceRef> deviceRGB(AdoptCF, CGColorSpaceCreateDeviceRGB());
- RetainPtr<CFDataRef> imageData(AdoptCF, CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, image->buffer(), image->bufferLength(), kCFAllocatorNull));
+ // FIXME: Creating CFData is non-optimal, but needed to avoid crashing when printing. Ideally we should
+ // make a custom CGDataProvider that controls the WindowsBitmap lifetime. see <rdar://6394455>
+ RetainPtr<CFDataRef> imageData(AdoptCF, CFDataCreate(kCFAllocatorDefault, image->buffer(), image->bufferLength()));
RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(imageData.get()));
RetainPtr<CGImageRef> cgImage(AdoptCF, CGImageCreate(image->size().width(), image->size().height(), 8, 32, image->bytesPerRow(), deviceRGB.get(),
kCGBitmapByteOrder32Little | kCGImageAlphaFirst, dataProvider.get(), 0, true, kCGRenderingIntentDefault));
CGContextDrawImage(m_data->m_cgContext, CGRectMake(point.x(), point.y(), image->size().width(), image->size().height()), cgImage.get());
}
-void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform)
+void GraphicsContextPlatformPrivate::concatCTM(const TransformationMatrix& transform)
{
if (!m_hdc)
return;
diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
index 3dcf6ba..892d24a 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "GraphicsContext.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "NotImplemented.h"
#include "Path.h"
@@ -102,7 +102,7 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo
cairo_surface_mark_dirty(surface);
}
-void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform)
+void GraphicsContextPlatformPrivate::concatCTM(const TransformationMatrix& transform)
{
cairo_surface_t* surface = cairo_get_target(cr);
HDC hdc = cairo_win32_surface_get_dc(surface);
diff --git a/WebCore/platform/graphics/win/GraphicsContextWin.cpp b/WebCore/platform/graphics/win/GraphicsContextWin.cpp
index dbf9fad..b3ebcb0 100644
--- a/WebCore/platform/graphics/win/GraphicsContextWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextWin.cpp
@@ -32,7 +32,7 @@
#include "GraphicsContextPlatformPrivateCairo.h"
#endif
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "NotImplemented.h"
#include "Path.h"
#include <wtf/MathExtras.h>
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index cef4217..1b09e1f 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 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
@@ -239,8 +239,9 @@ IntSize MediaPlayerPrivate::naturalSize() const
bool MediaPlayerPrivate::hasVideo() const
{
- // This is not used at the moment
- return true;
+ if (!m_qtMovie)
+ return false;
+ return m_qtMovie->hasVideo();
}
void MediaPlayerPrivate::setVolume(float volume)
diff --git a/WebCore/platform/graphics/win/QTMovieWin.cpp b/WebCore/platform/graphics/win/QTMovieWin.cpp
index 8eee41b..32aecd3 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.cpp
+++ b/WebCore/platform/graphics/win/QTMovieWin.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Computer, 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
@@ -710,6 +710,14 @@ void QTMovieWin::disableUnsupportedTracks(unsigned& enabledTrackCount)
}
}
+
+bool QTMovieWin::hasVideo() const
+{
+ if (!m_private->m_movie)
+ return false;
+ return (GetMovieIndTrackType(m_private->m_movie, 1, VisualMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly));
+}
+
pascal OSErr movieDrawingCompleteProc(Movie movie, long data)
{
UppParam param;
diff --git a/WebCore/platform/graphics/win/QTMovieWin.h b/WebCore/platform/graphics/win/QTMovieWin.h
index e31780a..2186974 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.h
+++ b/WebCore/platform/graphics/win/QTMovieWin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Computer, 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
@@ -86,6 +86,8 @@ public:
void disableUnsupportedTracks(unsigned& enabledTrackCount);
+ bool hasVideo() const;
+
static unsigned countSupportedTypes();
static void getSupportedType(unsigned index, const UChar*& str, unsigned& len);
diff --git a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
index 0e9f9fb..9d5c3b9 100644
--- a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
+++ b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
@@ -91,6 +91,7 @@ void SimpleFontData::platformCommonDestroy()
{
// We don't hash this on Win32, so it's effectively owned by us.
delete m_smallCapsFontData;
+ m_smallCapsFontData = 0;
ScriptFreeCache(&m_scriptCache);
delete m_scriptFontProperties;
@@ -124,7 +125,7 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
// FIXME: Microsoft documentation seems to imply that characters can be output using a given font and DC
// merely by testing code page intersection. This seems suspect though. Can't a font only partially
// cover a given code page?
- IMLangFontLink2* langFontLink = FontCache::getFontLinkInterface();
+ IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface();
if (!langFontLink)
return false;
@@ -176,6 +177,7 @@ void SimpleFontData::determinePitch()
float SimpleFontData::widthForGDIGlyph(Glyph glyph) const
{
HDC hdc = GetDC(0);
+ SetGraphicsMode(hdc, GM_ADVANCED);
HGDIOBJ oldFont = SelectObject(hdc, m_font.hfont());
int width;
GetCharWidthI(hdc, glyph, 1, 0, &width);
diff --git a/WebCore/platform/graphics/wx/FontPlatformData.h b/WebCore/platform/graphics/wx/FontPlatformData.h
index e3a3cce..d2394dc 100644
--- a/WebCore/platform/graphics/wx/FontPlatformData.h
+++ b/WebCore/platform/graphics/wx/FontPlatformData.h
@@ -81,7 +81,7 @@ public:
bool operator==(const FontPlatformData& other) const
{
if (m_fontState == VALID)
- return other.m_fontState == VALID && m_font.Ok() && other.m_font.Ok() && m_font.IsSameAs(other.m_font);
+ return other.m_fontState == VALID && m_font.IsOk() && other.m_font.IsOk() && m_font.IsSameAs(other.m_font);
else
return m_fontState == other.m_fontState;
}
@@ -89,7 +89,7 @@ public:
bool isHashTableDeletedValue() const { return m_fontState == DELETED; }
unsigned computeHash() const {
- ASSERT(m_font.Ok());
+ ASSERT(m_font.IsOk());
// make a hash that is unique for this font, but not globally unique - that is,
// a font whose properties are equal should generate the same hash
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 435e7ce..59e388e 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "GraphicsContext.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatRect.h"
#include "Font.h"
#include "IntRect.h"
@@ -284,7 +284,7 @@ void GraphicsContext::clip(const FloatRect& r)
wxPoint pos(0, 0);
if (windc) {
-#ifndef __WXGTK__
+#if !defined(__WXGTK__) || wxCHECK_VERSION(2,9,0)
wxWindow* window = windc->GetWindow();
#else
wxWindow* window = windc->m_owner;
@@ -349,10 +349,10 @@ void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
notImplemented();
}
-AffineTransform GraphicsContext::getCTM() const
+TransformationMatrix GraphicsContext::getCTM() const
{
notImplemented();
- return AffineTransform();
+ return TransformationMatrix();
}
void GraphicsContext::translate(float tx, float ty)
@@ -414,7 +414,13 @@ void GraphicsContext::setURLForRect(const KURL&, const IntRect&)
void GraphicsContext::setCompositeOperation(CompositeOperator op)
{
if (m_data->context)
+ {
+#if wxCHECK_VERSION(2,9,0)
+ m_data->context->SetLogicalFunction(static_cast<wxRasterOperationMode>(getWxCompositingOperation(op, false)));
+#else
m_data->context->SetLogicalFunction(getWxCompositingOperation(op, false));
+#endif
+ }
}
void GraphicsContext::beginPath()
@@ -455,7 +461,7 @@ void GraphicsContext::setPlatformFillColor(const Color& color)
m_data->context->SetBrush(wxBrush(color));
}
-void GraphicsContext::concatCTM(const AffineTransform& transform)
+void GraphicsContext::concatCTM(const TransformationMatrix& transform)
{
if (paintingDisabled())
return;
@@ -464,7 +470,7 @@ void GraphicsContext::concatCTM(const AffineTransform& transform)
return;
}
-void GraphicsContext::setUseAntialiasing(bool enable)
+void GraphicsContext::setPlatformShouldAntialias(bool enable)
{
if (paintingDisabled())
return;
diff --git a/WebCore/platform/graphics/wx/ImageSourceWx.cpp b/WebCore/platform/graphics/wx/ImageSourceWx.cpp
index 3ce4f2a..d523354 100644
--- a/WebCore/platform/graphics/wx/ImageSourceWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageSourceWx.cpp
@@ -30,6 +30,7 @@
#include "GIFImageDecoder.h"
#include "ICOImageDecoder.h"
#include "JPEGImageDecoder.h"
+#include "NotImplemented.h"
#include "PNGImageDecoder.h"
#include "SharedBuffer.h"
#include "XBMImageDecoder.h"
@@ -92,7 +93,7 @@ ImageSource::ImageSource()
ImageSource::~ImageSource()
{
- delete m_decoder;
+ clear(true);
}
bool ImageSource::initialized() const
@@ -141,6 +142,12 @@ int ImageSource::repetitionCount()
return m_decoder->repetitionCount();
}
+String ImageSource::filenameExtension() const
+{
+ notImplemented();
+ return String();
+}
+
size_t ImageSource::frameCount() const
{
return m_decoder ? m_decoder->frameCount() : 0;
@@ -152,10 +159,18 @@ bool ImageSource::frameIsCompleteAtIndex(size_t index)
return (m_decoder && m_decoder->frameBufferAtIndex(index) != 0);
}
-void ImageSource::clear()
+void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
{
- delete m_decoder;
+ if (!destroyAll) {
+ if (m_decoder)
+ m_decoder->clearFrameBufferCache(clearBeforeFrame);
+ return;
+ }
+
+ delete m_decoder;
m_decoder = 0;
+ if (data)
+ setData(data, allDataReceived);
}
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
@@ -205,8 +220,9 @@ NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
}
}
-
+#if !wxCHECK_VERSION(2,9,0)
bmp->UseAlpha();
+#endif
ASSERT(bmp->IsOk());
return bmp;
}
diff --git a/WebCore/platform/graphics/wx/ImageWx.cpp b/WebCore/platform/graphics/wx/ImageWx.cpp
index a05a31f..e52e9ff 100644
--- a/WebCore/platform/graphics/wx/ImageWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageWx.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "Image.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "BitmapImage.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
@@ -52,15 +52,17 @@ namespace WebCore {
// this is in GraphicsContextWx.cpp
int getWxCompositingOperation(CompositeOperator op, bool hasAlpha);
-void FrameData::clear()
+bool FrameData::clear(bool clearMetadata)
{
+ if (clearMetadata)
+ m_haveMetadata = false;
+
if (m_frame) {
delete m_frame;
m_frame = 0;
- // NOTE: We purposefully don't reset metadata here, so that even if we
- // throw away previously-decoded data, animation loops can still access
- // properties like frame durations without re-decoding.
+ return true;
}
+ return false;
}
// ================================================
@@ -95,6 +97,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
#if USE(WXGC)
wxGCDC* context = (wxGCDC*)ctxt->platformContext();
+ wxGraphicsContext* gc = context->GetGraphicsContext();
#else
wxWindowDC* context = ctxt->platformContext();
#endif
@@ -114,7 +117,29 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
// Set the compositing operation.
ctxt->setCompositeOperation(op);
+
+#if USE(WXGC)
+ float scaleX = src.width() / dst.width();
+ float scaleY = src.height() / dst.height();
+ FloatRect adjustedDestRect = dst;
+ FloatSize selfSize = currentFrameSize();
+
+ if (src.size() != selfSize) {
+ 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());
+ gc->DrawBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height());
+ gc->PopState();
+#else
IntRect srcIntRect(src);
IntRect dstIntRect(dst);
bool rescaling = false;
@@ -124,7 +149,8 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
wxImage img = bitmap->ConvertToImage();
img.Rescale(dstIntRect.width(), dstIntRect.height());
bitmap = new wxBitmap(img);
- }
+ }
+
wxMemoryDC mydc;
ASSERT(bitmap->GetRefData());
mydc.SelectObject(*bitmap);
@@ -143,10 +169,12 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
delete bitmap;
bitmap = NULL;
}
+#endif
+
ctxt->restore();
}
-void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& dstRect)
+void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& dstRect)
{
if (!m_source.initialized())
return;
@@ -169,23 +197,33 @@ void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, c
#if USE(WXGC)
wxGraphicsContext* gc = context->GetGraphicsContext();
gc->ConcatTransform(patternTransform);
-#endif
-
+#else
wxMemoryDC mydc;
mydc.SelectObject(*bitmap);
+#endif
- while ( currentW < dstRect.width() ) {
- while ( currentH < dstRect.height() ) {
+ wxPoint origin(context->GetDeviceOrigin());
+ wxSize clientSize(context->GetSize());
+
+ 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());
+#else
context->Blit((wxCoord)dstRect.x() + currentW, (wxCoord)dstRect.y() + currentH,
(wxCoord)srcRect.width(), (wxCoord)srcRect.height(), &mydc,
(wxCoord)srcRect.x(), (wxCoord)srcRect.y(), wxCOPY, true);
+#endif
currentH += srcRect.height();
}
currentW += srcRect.width();
currentH = 0;
}
ctxt->restore();
+
+#if !USE(WXGC)
mydc.SelectObject(wxNullBitmap);
+#endif
// NB: delete is causing crashes during page load, but not during the deletion
// itself. It occurs later on when a valid bitmap created in frameAtIndex
diff --git a/WebCore/platform/graphics/wx/PathWx.cpp b/WebCore/platform/graphics/wx/PathWx.cpp
index 5ff9914..60c71d5 100644
--- a/WebCore/platform/graphics/wx/PathWx.cpp
+++ b/WebCore/platform/graphics/wx/PathWx.cpp
@@ -26,10 +26,11 @@
#include "config.h"
#include "Path.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatPoint.h"
#include "FloatRect.h"
#include "NotImplemented.h"
+#include "StrokeStyleApplier.h"
#include <stdio.h>
@@ -64,7 +65,7 @@ Path::Path()
}
Path::~Path()
-{
+{
}
Path::Path(const Path& path)
@@ -73,7 +74,16 @@ Path::Path(const Path& path)
}
bool Path::contains(const FloatPoint& point, const WindRule rule) const
-{
+{
+#if USE(WXGC)
+ if (m_path) {
+#if wxCHECK_VERSION(2,9,0)
+ return m_path->Contains(point.x(), point.y(), static_cast<wxPolygonFillMode>(getWxWindRuleForWindRule(rule)));
+#else
+ return m_path->Contains(point.x(), point.y(), getWxWindRuleForWindRule(rule));
+#endif
+ }
+#endif
return false;
}
@@ -93,6 +103,12 @@ FloatRect Path::boundingRect() const
return FloatRect();
}
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+{
+ notImplemented();
+ return FloatRect();
+}
+
Path& Path::operator=(const Path&)
{
notImplemented();
@@ -121,60 +137,93 @@ void Path::moveTo(const FloatPoint& point)
#endif
}
-void Path::addLineTo(const FloatPoint&)
-{
- notImplemented();
+void Path::addLineTo(const FloatPoint& point)
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->AddLineToPoint(point.x(), point.y());
+#endif
}
-void Path::addQuadCurveTo(const FloatPoint&, const FloatPoint&)
-{
- notImplemented();
+void Path::addQuadCurveTo(const FloatPoint& control, const FloatPoint& end)
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->AddQuadCurveToPoint(control.x(), control.y(), end.x(), end.y());
+#endif
}
-void Path::addBezierCurveTo(const FloatPoint&, const FloatPoint&, const FloatPoint&)
-{
- notImplemented();
+void Path::addBezierCurveTo(const FloatPoint& control1, const FloatPoint& control2, const FloatPoint& end)
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->AddCurveToPoint(control1.x(), control1.y(), control2.x(), control2.y(), end.x(), end.y());
+#endif
}
-void Path::addArcTo(const FloatPoint&, const FloatPoint&, float)
-{
- notImplemented();
+void Path::addArcTo(const FloatPoint& point1, const FloatPoint& point2, float radius)
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->AddArcToPoint(point1.x(), point1.y(), point2.x(), point2.y(), radius);
+#endif
}
void Path::closeSubpath()
-{
- notImplemented();
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->CloseSubpath();
+#endif
}
-void Path::addArc(const FloatPoint&, float, float, float, bool)
-{
- notImplemented();
+void Path::addArc(const FloatPoint& point, float radius, float startAngle, float endAngle, bool clockwise)
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->AddArc(point.x(), point.y(), radius, startAngle, endAngle, clockwise);
+#endif
}
-void Path::addRect(const FloatRect&)
-{
- notImplemented();
+void Path::addRect(const FloatRect& rect)
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->AddRectangle(rect.x(), rect.y(), rect.width(), rect.height());
+#endif
}
-void Path::addEllipse(const FloatRect&)
-{
- notImplemented();
+void Path::addEllipse(const FloatRect& rect)
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->AddEllipse(rect.x(), rect.y(), rect.width(), rect.height());
+#endif
}
-void Path::transform(const AffineTransform&)
-{
- notImplemented();
+void Path::transform(const TransformationMatrix& transform)
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->Transform(transform);
+#endif
}
void Path::apply(void* info, PathApplierFunction function) const
-{
+{
notImplemented();
}
bool Path::isEmpty() const
{
- notImplemented();
- return false;
+#if USE(WXGC)
+ if (m_path) {
+ wxDouble width, height;
+ m_path->GetBox(NULL, NULL, &width, &height);
+ return (width == 0 && height == 0);
+ }
+#endif
+ return true;
}
}
diff --git a/WebCore/platform/graphics/wx/AffineTransformWx.cpp b/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp
index 12485ae..e6a02b8 100644
--- a/WebCore/platform/graphics/wx/AffineTransformWx.cpp
+++ b/WebCore/platform/graphics/wx/TransformationMatrixWx.cpp
@@ -20,11 +20,11 @@
* 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.
*/
#include "config.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatRect.h"
#include "IntRect.h"
@@ -37,105 +37,125 @@
namespace WebCore {
#if USE(WXGC)
-AffineTransform::AffineTransform(const PlatformAffineTransform& matrix)
+TransformationMatrix::TransformationMatrix(const PlatformTransformationMatrix& matrix)
{
m_transform = matrix;
}
#endif
-AffineTransform::AffineTransform(double a, double b, double c, double d, double e, double f)
+TransformationMatrix::TransformationMatrix(double a, double b, double c, double d, double e, double f)
{
#if USE(WXGC)
- wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
+ wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
m_transform = renderer->CreateMatrix();
#endif
setMatrix(a, b, c, d, e, f);
}
-AffineTransform::AffineTransform()
-{
+TransformationMatrix::TransformationMatrix()
+{
// NB: If we ever support using Cairo backend on Win/Mac, this will need to be
// changed somehow (though I'm not sure how as we don't have a reference to the
// graphics context here.
#if USE(WXGC)
- wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
+ wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
m_transform = renderer->CreateMatrix();
#endif
}
-AffineTransform AffineTransform::inverse() const
+TransformationMatrix TransformationMatrix::inverse() const
{
notImplemented();
return *this;
}
-void AffineTransform::setMatrix(double a, double b, double c, double d, double e, double f)
+void TransformationMatrix::setMatrix(double a, double b, double c, double d, double e, double f)
{
#if USE(WXGC)
m_transform.Set(a, b, c, d, e, f);
#endif
}
-void AffineTransform::map(double x, double y, double *x2, double *y2) const
-{
+void TransformationMatrix::map(double x, double y, double *x2, double *y2) const
+{
notImplemented();
}
-IntRect AffineTransform::mapRect(const IntRect &rect) const
+IntRect TransformationMatrix::mapRect(const IntRect &rect) const
{
- notImplemented();
+#if USE(WXGC)
+ double x, y, width, height;
+ x = rect.x();
+ y = rect.y();
+ width = rect.width();
+ height = rect.height();
+
+ m_transform.TransformPoint(&x, &y);
+ m_transform.TransformDistance(&width, &height);
+ return IntRect(x, y, width, height);
+#endif
return IntRect();
}
-FloatRect AffineTransform::mapRect(const FloatRect &rect) const
+FloatRect TransformationMatrix::mapRect(const FloatRect &rect) const
{
- notImplemented();
+#if USE(WXGC)
+ double x, y, width, height;
+ x = rect.x();
+ y = rect.y();
+ width = rect.width();
+ height = rect.height();
+
+ m_transform.TransformPoint(&x, &y);
+ m_transform.TransformDistance(&width, &height);
+ return FloatRect(x, y, width, height);
+#endif
return FloatRect();
}
-AffineTransform& AffineTransform::scale(double sx, double sy)
+TransformationMatrix& TransformationMatrix::scale(double sx, double sy)
{
#if USE(WXGC)
- m_transform.Scale((wxDouble)sx, (wxDouble)sy);
+ m_transform.Scale((wxDouble)sx, (wxDouble)sy);
#endif
- return *this;
+ return *this;
}
-void AffineTransform::reset()
+void TransformationMatrix::reset()
{
notImplemented();
}
-AffineTransform& AffineTransform::rotate(double d)
-{
+TransformationMatrix& TransformationMatrix::rotate(double d)
+{
#if USE(WXGC)
- m_transform.Rotate((wxDouble)d);
+ m_transform.Rotate((wxDouble)d);
#endif
- return *this;
+ return *this;
}
-AffineTransform& AffineTransform::translate(double tx, double ty)
-{
+TransformationMatrix& TransformationMatrix::translate(double tx, double ty)
+{
#if USE(WXGC)
- m_transform.Translate((wxDouble)tx, (wxDouble)ty);
+ m_transform.Translate((wxDouble)tx, (wxDouble)ty);
#endif
- return *this;
+ return *this;
}
-AffineTransform& AffineTransform::shear(double sx, double sy)
-{
- notImplemented();
- return *this;
+TransformationMatrix& TransformationMatrix::shear(double sx, double sy)
+{
+ notImplemented();
+ return *this;
}
-AffineTransform& AffineTransform::operator*=(const AffineTransform& other)
-{
+TransformationMatrix& TransformationMatrix::operator*=(const TransformationMatrix& other)
+{
notImplemented();
- return *this;
+ return *this;
}
-bool AffineTransform::operator== (const AffineTransform &other) const
+bool TransformationMatrix::operator== (const TransformationMatrix &other) const
{
#if USE(WXGC)
return m_transform.IsEqual((wxGraphicsMatrix)other);
@@ -145,26 +165,26 @@ bool AffineTransform::operator== (const AffineTransform &other) const
#endif
}
-AffineTransform AffineTransform::operator* (const AffineTransform &other)
+TransformationMatrix TransformationMatrix::operator* (const TransformationMatrix &other)
{
notImplemented();
return *this; //m_transform * other.m_transform;
}
-double AffineTransform::det() const
-{
- notImplemented();
+double TransformationMatrix::det() const
+{
+ notImplemented();
return 0;
}
#if USE(WXGC)
-AffineTransform::operator wxGraphicsMatrix() const
+TransformationMatrix::operator wxGraphicsMatrix() const
{
return m_transform;
}
#endif
-double AffineTransform::a() const
+double TransformationMatrix::a() const
{
double a = 0;
#if USE(WXGC)
@@ -173,12 +193,12 @@ double AffineTransform::a() const
return a;
}
-void AffineTransform::setA(double a)
+void TransformationMatrix::setA(double a)
{
setMatrix(a, b(), c(), d(), e(), f());
}
-double AffineTransform::b() const
+double TransformationMatrix::b() const
{
double b = 0;
#if USE(WXGC)
@@ -187,12 +207,12 @@ double AffineTransform::b() const
return b;
}
-void AffineTransform::setB(double b)
+void TransformationMatrix::setB(double b)
{
setMatrix(a(), b, c(), d(), e(), f());
}
-double AffineTransform::c() const
+double TransformationMatrix::c() const
{
double c = 0;
#if USE(WXGC)
@@ -201,12 +221,12 @@ double AffineTransform::c() const
return c;
}
-void AffineTransform::setC(double c)
+void TransformationMatrix::setC(double c)
{
setMatrix(a(), b(), c, d(), e(), f());
}
-double AffineTransform::d() const
+double TransformationMatrix::d() const
{
double d = 0;
#if USE(WXGC)
@@ -215,12 +235,12 @@ double AffineTransform::d() const
return d;
}
-void AffineTransform::setD(double d)
+void TransformationMatrix::setD(double d)
{
setMatrix(a(), b(), c(), d, e(), f());
}
-double AffineTransform::e() const
+double TransformationMatrix::e() const
{
double e = 0;
#if USE(WXGC)
@@ -229,12 +249,12 @@ double AffineTransform::e() const
return e;
}
-void AffineTransform::setE(double e)
+void TransformationMatrix::setE(double e)
{
setMatrix(a(), b(), c(), d(), e, f());
}
-double AffineTransform::f() const
+double TransformationMatrix::f() const
{
double f = 0;
#if USE(WXGC)
@@ -243,7 +263,7 @@ double AffineTransform::f() const
return f;
}
-void AffineTransform::setF(double f)
+void TransformationMatrix::setF(double f)
{
setMatrix(a(), b(), c(), d(), e(), f);
}
diff --git a/WebCore/platform/gtk/FileSystemGtk.cpp b/WebCore/platform/gtk/FileSystemGtk.cpp
index 965cea9..4f0ae01 100644
--- a/WebCore/platform/gtk/FileSystemGtk.cpp
+++ b/WebCore/platform/gtk/FileSystemGtk.cpp
@@ -29,7 +29,6 @@
#include <glib.h>
#include <glib/gstdio.h>
-#include <glib/gutils.h>
#include <unistd.h>
diff --git a/WebCore/platform/gtk/GeolocationServiceGtk.cpp b/WebCore/platform/gtk/GeolocationServiceGtk.cpp
new file mode 100644
index 0000000..0c80dd6
--- /dev/null
+++ b/WebCore/platform/gtk/GeolocationServiceGtk.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 Holger Hans Peter Freyther
+ *
+ * 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 "GeolocationServiceGtk.h"
+
+namespace WebCore {
+
+GeolocationService* GeolocationService::create(GeolocationServiceClient* client)
+{
+ return new GeolocationServiceGtk(client);
+}
+
+GeolocationServiceGtk::GeolocationServiceGtk(GeolocationServiceClient* client)
+ : GeolocationService(client)
+{}
+
+bool GeolocationServiceGtk::startUpdating(PositionOptions*)
+{
+ return false;
+}
+
+void GeolocationServiceGtk::stopUpdating()
+{
+}
+
+void GeolocationServiceGtk::suspend()
+{
+}
+
+void GeolocationServiceGtk::resume()
+{
+}
+
+Geoposition* GeolocationServiceGtk::lastPosition() const
+{
+ return 0;
+}
+
+PositionError* GeolocationServiceGtk::lastError() const
+{
+ return 0;
+}
+
+}
diff --git a/WebCore/platform/gtk/GeolocationServiceGtk.h b/WebCore/platform/gtk/GeolocationServiceGtk.h
new file mode 100644
index 0000000..02aff2d
--- /dev/null
+++ b/WebCore/platform/gtk/GeolocationServiceGtk.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2008 Holger Hans Peter Freyther
+ *
+ * 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 GeolocationServiceGtk_h
+#define GeolocationServiceGtk_h
+
+#include "GeolocationService.h"
+
+namespace WebCore {
+ class GeolocationServiceGtk : public GeolocationService {
+ public:
+ GeolocationServiceGtk(GeolocationServiceClient*);
+
+ virtual bool startUpdating(PositionOptions*);
+ virtual void stopUpdating();
+
+ virtual void suspend();
+ virtual void resume();
+
+ Geoposition* lastPosition() const;
+ PositionError* lastError() const;
+ };
+}
+
+#endif
diff --git a/WebCore/platform/gtk/KeyEventGtk.cpp b/WebCore/platform/gtk/KeyEventGtk.cpp
index 153ef19..e0742f4 100644
--- a/WebCore/platform/gtk/KeyEventGtk.cpp
+++ b/WebCore/platform/gtk/KeyEventGtk.cpp
@@ -36,7 +36,9 @@
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
-#include <gtk/gtkversion.h>
+
+// GTK_CHECK_VERSION is defined in gtk/gtkversion.h
+#include <gtk/gtk.h>
namespace WebCore {
@@ -464,6 +466,32 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode)
// VK_NONAME (FC) Reserved for future use
// VK_PA1 (FD) PA1 key
// VK_OEM_CLEAR (FE) Clear key
+ case GDK_F1:
+ case GDK_F2:
+ case GDK_F3:
+ case GDK_F4:
+ case GDK_F5:
+ case GDK_F6:
+ case GDK_F7:
+ case GDK_F8:
+ case GDK_F9:
+ case GDK_F10:
+ case GDK_F11:
+ case GDK_F12:
+ case GDK_F13:
+ case GDK_F14:
+ case GDK_F15:
+ case GDK_F16:
+ case GDK_F17:
+ case GDK_F18:
+ case GDK_F19:
+ case GDK_F20:
+ case GDK_F21:
+ case GDK_F22:
+ case GDK_F23:
+ case GDK_F24:
+ return VK_F1 + (keycode - GDK_F1);
+
default:
return 0;
}
diff --git a/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp b/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
index 20fe0cb..8afb60f 100644
--- a/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
+++ b/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp
@@ -39,6 +39,7 @@ static const ExtensionMap extensionMap [] = {
{ "bmp", "image/bmp" },
{ "css", "text/css" },
{ "gif", "image/gif" },
+ { "htm", "text/html" },
{ "html", "text/html" },
{ "ico", "image/x-icon" },
{ "jpeg", "image/jpeg" },
@@ -54,6 +55,8 @@ static const ExtensionMap extensionMap [] = {
{ "xml", "text/xml" },
{ "xsl", "text/xsl" },
{ "xhtml", "application/xhtml+xml" },
+ { "wml", "text/vnd.wap.wml" },
+ { "wmlc", "application/vnd.wap.wmlc" },
{ 0, 0 }
};
diff --git a/WebCore/platform/gtk/MouseEventGtk.cpp b/WebCore/platform/gtk/MouseEventGtk.cpp
index f441f00..2400ebf 100644
--- a/WebCore/platform/gtk/MouseEventGtk.cpp
+++ b/WebCore/platform/gtk/MouseEventGtk.cpp
@@ -27,11 +27,12 @@
#include "config.h"
#include "PlatformMouseEvent.h"
-#include "SystemTime.h"
#include "Assertions.h"
#include <gdk/gdk.h>
-#include <gtk/gtkversion.h>
+
+// GTK_CHECK_VERSION is defined in gtk/gtkversion.h
+#include <gtk/gtk.h>
namespace WebCore {
diff --git a/WebCore/platform/gtk/PlatformScreenGtk.cpp b/WebCore/platform/gtk/PlatformScreenGtk.cpp
index 9788253..3512be1 100644
--- a/WebCore/platform/gtk/PlatformScreenGtk.cpp
+++ b/WebCore/platform/gtk/PlatformScreenGtk.cpp
@@ -47,10 +47,20 @@ namespace WebCore {
int screenDepth(Widget* widget)
{
GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformWindow());
+
if (!container)
return 24;
- GdkVisual* visual = gdk_drawable_get_visual(GDK_DRAWABLE(GTK_WIDGET(widget->root()->hostWindow()->platformWindow())->window));
+ if (!GTK_WIDGET_REALIZED(container)) {
+ GtkWidget* toplevel = gtk_widget_get_toplevel(container);
+ if (GTK_WIDGET_TOPLEVEL(toplevel))
+ container = toplevel;
+ else
+ return 24;
+ }
+
+
+ GdkVisual* visual = gdk_drawable_get_visual(GDK_DRAWABLE(container->window));
return visual->depth;
}
@@ -75,8 +85,8 @@ bool screenIsMonochrome(Widget* widget)
FloatRect screenRect(Widget* widget)
{
- GtkWidget* container = GTK_WIDGET(widget->root()->hostWindow()->platformWindow());
- if (!container)
+ GtkWidget* container = gtk_widget_get_toplevel(GTK_WIDGET(widget->root()->hostWindow()->platformWindow()));
+ if (!GTK_WIDGET_TOPLEVEL(container))
return FloatRect();
GdkScreen* screen = gtk_widget_has_screen(container) ? gtk_widget_get_screen(container) : gdk_screen_get_default();
diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp
index bf8b8d7..ee462e0 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -23,9 +23,10 @@
#include "config.h"
#include "RenderThemeGtk.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "GraphicsContext.h"
#include "NotImplemented.h"
+#include "RenderBox.h"
#include "RenderObject.h"
#include "gtkdrawing.h"
@@ -82,10 +83,16 @@ bool RenderThemeGtk::controlSupportsTints(const RenderObject* o) const
int RenderThemeGtk::baselinePosition(const RenderObject* o) const
{
+ if (!o->isBox())
+ return 0;
+
// FIXME: This strategy is possibly incorrect for the GTK+ port.
if (o->style()->appearance() == CheckboxPart ||
- o->style()->appearance() == RadioPart)
- return o->marginTop() + o->height() - 2;
+ o->style()->appearance() == RadioPart) {
+ const RenderBox* box = toRenderBox(o);
+ return box->marginTop() + box->height() - 2;
+ }
+
return RenderTheme::baselinePosition(o);
}
@@ -161,7 +168,7 @@ static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderOb
break;
}
- AffineTransform ctm = i.context->getCTM();
+ TransformationMatrix ctm = i.context->getCTM();
IntPoint pos = ctm.mapPoint(rect.location());
GdkRectangle gdkRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height());
@@ -409,7 +416,7 @@ Color RenderThemeGtk::inactiveListBoxSelectionForegroundColor() const
return widget->style->text[GTK_STATE_ACTIVE];
}
-double RenderThemeGtk::caretBlinkFrequency() const
+double RenderThemeGtk::caretBlinkInterval() const
{
GtkSettings* settings = gtk_settings_get_default();
diff --git a/WebCore/platform/gtk/RenderThemeGtk.h b/WebCore/platform/gtk/RenderThemeGtk.h
index dda8bc8..76f7a0a 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/WebCore/platform/gtk/RenderThemeGtk.h
@@ -66,7 +66,7 @@ public:
virtual Color inactiveListBoxSelectionBackgroundColor() const;
virtual Color inactiveListBoxSelectionForegroundColor() const;
- virtual double caretBlinkFrequency() const;
+ virtual double caretBlinkInterval() const;
// System fonts.
virtual void systemFont(int propId, FontDescription&) const;
diff --git a/WebCore/platform/gtk/ScrollbarGtk.cpp b/WebCore/platform/gtk/ScrollbarGtk.cpp
index 099895d..df165e3 100644
--- a/WebCore/platform/gtk/ScrollbarGtk.cpp
+++ b/WebCore/platform/gtk/ScrollbarGtk.cpp
@@ -76,7 +76,7 @@ ScrollbarGtk::~ScrollbarGtk()
g_object_unref(G_OBJECT(platformWidget()));
}
-void ScrollbarGtk::frameRectsChanged() const
+void ScrollbarGtk::frameRectsChanged()
{
if (!parent() || !parent()->isScrollViewScrollbar(this))
return;
@@ -114,23 +114,6 @@ void ScrollbarGtk::setFrameRect(const IntRect& rect)
frameRectsChanged();
}
-void ScrollbarGtk::frameRectsChanged()
-{
- if (!parent())
- return;
-
- ASSERT(parent()->isFrameView());
-
- FrameView* frameView = static_cast<FrameView*>(parent());
- IntRect windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
-
- IntSize sz = frameRect().size();
- sz.clampNegativeToZero();
-
- GtkAllocation allocation = { windowRect.x(), windowRect.y(), sz.width(), sz.height() };
- gtk_widget_size_allocate(platformWidget(), &allocation);
-}
-
void ScrollbarGtk::gtkValueChanged(GtkAdjustment*, ScrollbarGtk* that)
{
that->setValue(static_cast<int>(gtk_adjustment_get_value(that->m_adjustment)));
diff --git a/WebCore/platform/gtk/ScrollbarGtk.h b/WebCore/platform/gtk/ScrollbarGtk.h
index 50e9184..11ff079 100644
--- a/WebCore/platform/gtk/ScrollbarGtk.h
+++ b/WebCore/platform/gtk/ScrollbarGtk.h
@@ -48,14 +48,13 @@ public:
virtual void setEnabled(bool);
- virtual void frameRectsChanged() const;
+ virtual void frameRectsChanged();
protected:
ScrollbarGtk(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
virtual void updateThumbPosition();
virtual void updateThumbProportion();
- virtual void frameRectsChanged();
private:
static void gtkValueChanged(GtkAdjustment*, ScrollbarGtk*);
diff --git a/WebCore/platform/gtk/SharedTimerGtk.cpp b/WebCore/platform/gtk/SharedTimerGtk.cpp
index e0a5b60..0a760ed 100644
--- a/WebCore/platform/gtk/SharedTimerGtk.cpp
+++ b/WebCore/platform/gtk/SharedTimerGtk.cpp
@@ -28,8 +28,8 @@
#include "config.h"
#include "SharedTimer.h"
-#include "SystemTime.h"
#include <wtf/Assertions.h>
+#include <wtf/CurrentTime.h>
#include <glib.h>
namespace WebCore {
diff --git a/WebCore/platform/gtk/TemporaryLinkStubs.cpp b/WebCore/platform/gtk/TemporaryLinkStubs.cpp
index 5093794..edabd10 100644
--- a/WebCore/platform/gtk/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/gtk/TemporaryLinkStubs.cpp
@@ -58,8 +58,6 @@ Vector<char> loadResourceIntoArray(const char* resourceName)
void PluginView::invalidateRegion(NPRegion) { notImplemented(); }
-Color WebCore::focusRingColor() { return Color(); }
-
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 fbe31f7..64ec65a 100644
--- a/WebCore/platform/gtk/WheelEventGtk.cpp
+++ b/WebCore/platform/gtk/WheelEventGtk.cpp
@@ -29,7 +29,9 @@
#include "PlatformWheelEvent.h"
#include <gdk/gdk.h>
-#include <gtk/gtkversion.h>
+
+// GTK_CHECK_VERSION is defined in gtk/gtkversion.h
+#include <gtk/gtk.h>
namespace WebCore {
diff --git a/WebCore/platform/gtk/gtk2drawing.c b/WebCore/platform/gtk/gtk2drawing.c
index 83b4cb4..dd46e74 100644
--- a/WebCore/platform/gtk/gtk2drawing.c
+++ b/WebCore/platform/gtk/gtk2drawing.c
@@ -89,7 +89,7 @@ static GtkWidget* gMenuItemWidget;
static GtkWidget* gImageMenuItemWidget;
static GtkWidget* gCheckMenuItemWidget;
static GtkWidget* gTreeViewWidget;
-static GtkWidget* gMiddleTreeViewColumn;
+static GtkTreeViewColumn* gMiddleTreeViewColumn;
static GtkWidget* gTreeHeaderCellWidget;
static GtkWidget* gTreeHeaderSortArrowWidget;
static GtkWidget* gExpanderWidget;
@@ -143,7 +143,7 @@ setup_widget_prototype(GtkWidget* widget)
gtk_container_add(GTK_CONTAINER(protoLayout), widget);
gtk_widget_realize(widget);
- g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
return MOZ_GTK_SUCCESS;
}
@@ -288,7 +288,7 @@ moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data)
g_object_add_weak_pointer(G_OBJECT(widget),
(gpointer) &gComboBoxButtonWidget);
gtk_widget_realize(widget);
- g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
}
@@ -307,7 +307,7 @@ moz_gtk_get_combo_box_button_inner_widgets(GtkWidget *widget,
} else
return;
gtk_widget_realize(widget);
- g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
static gint
@@ -348,7 +348,7 @@ ensure_combo_box_widgets()
&gComboBoxArrowWidget);
gtk_widget_realize(gComboBoxArrowWidget);
g_object_set_data(G_OBJECT(gComboBoxArrowWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
} else {
/* Shouldn't be reached with current internal gtk implementation; we
@@ -398,7 +398,7 @@ moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
} else
return;
gtk_widget_realize(widget);
- g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", TRUE);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
static void
@@ -409,7 +409,8 @@ 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", TRUE);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint",
+ GINT_TO_POINTER(TRUE));
}
}
@@ -461,7 +462,7 @@ ensure_combo_box_entry_widgets()
&gComboBoxEntryArrowWidget);
gtk_widget_realize(gComboBoxEntryArrowWidget);
g_object_set_data(G_OBJECT(gComboBoxEntryArrowWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
} else {
/* Shouldn't be reached with current internal gtk implementation;
@@ -501,7 +502,8 @@ 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", TRUE);
+ g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint",
+ GINT_TO_POINTER(TRUE));
}
return MOZ_GTK_SUCCESS;
}
@@ -590,7 +592,7 @@ ensure_menu_bar_item_widget()
gMenuBarItemWidget);
gtk_widget_realize(gMenuBarItemWidget);
g_object_set_data(G_OBJECT(gMenuBarItemWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
return MOZ_GTK_SUCCESS;
}
@@ -605,7 +607,7 @@ ensure_menu_popup_widget()
gMenuPopupWidget);
gtk_widget_realize(gMenuPopupWidget);
g_object_set_data(G_OBJECT(gMenuPopupWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
return MOZ_GTK_SUCCESS;
}
@@ -620,7 +622,7 @@ ensure_menu_item_widget()
gMenuItemWidget);
gtk_widget_realize(gMenuItemWidget);
g_object_set_data(G_OBJECT(gMenuItemWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
return MOZ_GTK_SUCCESS;
}
@@ -635,7 +637,7 @@ ensure_image_menu_item_widget()
gImageMenuItemWidget);
gtk_widget_realize(gImageMenuItemWidget);
g_object_set_data(G_OBJECT(gImageMenuItemWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
return MOZ_GTK_SUCCESS;
}
@@ -650,7 +652,7 @@ ensure_menu_separator_widget()
gMenuSeparatorWidget);
gtk_widget_realize(gMenuSeparatorWidget);
g_object_set_data(G_OBJECT(gMenuSeparatorWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
return MOZ_GTK_SUCCESS;
}
@@ -665,7 +667,7 @@ ensure_check_menu_item_widget()
gCheckMenuItemWidget);
gtk_widget_realize(gCheckMenuItemWidget);
g_object_set_data(G_OBJECT(gCheckMenuItemWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
return MOZ_GTK_SUCCESS;
}
@@ -720,9 +722,9 @@ ensure_tree_header_cell_widget()
gTreeHeaderCellWidget = GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn)->button;
gTreeHeaderSortArrowWidget = GTK_TREE_VIEW_COLUMN(gMiddleTreeViewColumn)->arrow;
g_object_set_data(G_OBJECT(gTreeHeaderCellWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
g_object_set_data(G_OBJECT(gTreeHeaderSortArrowWidget),
- "transparent-bg-hint", TRUE);
+ "transparent-bg-hint", GINT_TO_POINTER(TRUE));
}
return MOZ_GTK_SUCCESS;
}
@@ -1536,11 +1538,12 @@ 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", 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);
- g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", FALSE);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(FALSE));
}
/* Get the position of the inner window, see _gtk_entry_get_borders */
diff --git a/WebCore/platform/gtk/gtkdrawing.h b/WebCore/platform/gtk/gtkdrawing.h
index 6e44d4a..eb6995a 100644
--- a/WebCore/platform/gtk/gtkdrawing.h
+++ b/WebCore/platform/gtk/gtkdrawing.h
@@ -49,7 +49,7 @@
#define _GTK_DRAWING_H_
#include <gdk/gdk.h>
-#include <gtk/gtkstyle.h>
+#include <gtk/gtk.h>
#ifdef __cplusplus
extern "C" {
diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h
index 3df2e88..e21ddcf 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/ImageDecoder.h
@@ -28,6 +28,7 @@
#include "IntRect.h"
#include "ImageSource.h"
+#include "PlatformString.h"
#include "SharedBuffer.h"
#include <wtf/Vector.h>
@@ -54,6 +55,16 @@ public:
m_disposalMethod(DisposeNotSpecified), m_hasAlpha(false)
{}
+ void clear() {
+ m_bytes.clear();
+ m_rect = IntRect();
+ m_height = 0;
+ m_status = FrameEmpty;
+ m_duration = 0;
+ m_disposalMethod = DisposeNotSpecified;
+ m_hasAlpha = false;
+ }
+
const RGBA32Array& bytes() const { return m_bytes; }
RGBA32Array& bytes() { return m_bytes; }
const IntRect& rect() const { return m_rect; }
@@ -107,6 +118,9 @@ 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; }
@@ -135,6 +149,14 @@ public:
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;
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
index 0f515f0..d850cc7 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
@@ -36,6 +36,8 @@ class BMPImageReader;
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;
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index 22a6f09..843e65a 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -156,9 +156,18 @@ int GIFImageDecoder::repetitionCount() const
// packets sent back by the webserver) not always. Our caller is
// responsible for waiting until image decoding has finished to ask this if
// it needs an authoritative answer. In the meantime, we should default to
- // "loop once", both in the reader and here.
- if (m_reader)
- m_repetitionCount = m_reader->repetitionCount();
+ // "loop once".
+ if (m_reader) {
+ // Added wrinkle: ImageSource::clear() may destroy the reader, making
+ // the result from the reader _less_ authoritative on future calls. To
+ // detect this, the reader returns cLoopCountNotSeen (-2) instead of
+ // cAnimationLoopOnce (-1) when its current incarnation hasn't actually
+ // seen a loop count yet; in this case we return our previously-cached
+ // value.
+ const int repetitionCount = m_reader->repetitionCount();
+ if (repetitionCount != cLoopCountNotSeen)
+ m_repetitionCount = repetitionCount;
+ }
return m_repetitionCount;
}
@@ -174,6 +183,40 @@ RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index)
return &frame;
}
+void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame)
+{
+ // In some cases, like if the decoder was destroyed while animating, we
+ // can be asked to clear more frames than we currently have.
+ if (m_frameBufferCache.isEmpty())
+ return; // Nothing to do.
+ // The "-1" here is tricky. It does not mean that |clearBeforeFrame| is the
+ // last frame we wish to preserve, but rather that we never want to clear
+ // the very last frame in the cache: it's empty (so clearing it is
+ // pointless), it's partial (so we don't want to clear it anyway), or the
+ // cache could be enlarged with a future setData() call and it could be
+ // needed to construct the next frame (see comments below). Callers can
+ // always use ImageSource::clear(true, ...) to completely free the memory in
+ // this case.
+ clearBeforeFrame = std::min(clearBeforeFrame, m_frameBufferCache.size() - 1);
+ const Vector<RGBA32Buffer>::iterator end(m_frameBufferCache.begin() + clearBeforeFrame);
+ for (Vector<RGBA32Buffer>::iterator i(m_frameBufferCache.begin()); i != end; ++i) {
+ if (i->status() == RGBA32Buffer::FrameEmpty)
+ continue; // Nothing to do.
+
+ // The layout of frames is:
+ // [empty frames][complete frames][partial frame][empty frames]
+ // ...where each of these groups may be empty. We should not clear a
+ // partial frame since that's what's being decoded right now, and we
+ // also should not clear the last complete frame, since it may be needed
+ // when constructing the next frame. Note that "i + 1" is safe since
+ // i < end < m_frameBufferCache.end().
+ if ((i->status() == RGBA32Buffer::FramePartial) || ((i + 1)->status() != RGBA32Buffer::FrameComplete))
+ break;
+
+ i->clear();
+ }
+}
+
// Feed data to the GIF reader.
void GIFImageDecoder::decode(GIFQuery query, unsigned haltAtFrame) const
{
@@ -228,6 +271,7 @@ 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) &&
@@ -360,7 +404,12 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod)
{
+ // Initialize the frame if necessary. Some GIFs insert do-nothing frames,
+ // in which case we never reach haveDecodedRow() before getting here.
RGBA32Buffer& buffer = m_frameBufferCache[frameIndex];
+ if (buffer.status() == RGBA32Buffer::FrameEmpty)
+ initFrameBuffer(frameIndex);
+
buffer.ensureHeight(m_size.height());
buffer.setStatus(RGBA32Buffer::FrameComplete);
buffer.setDuration(frameDuration);
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
index b407b8d..02b43a2 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
@@ -39,6 +39,8 @@ public:
GIFImageDecoder();
~GIFImageDecoder();
+ virtual String filenameExtension() const { return "gif"; }
+
// Take the data and store it.
virtual void setData(SharedBuffer* data, bool allDataReceived);
@@ -54,6 +56,8 @@ public:
virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+ virtual void clearFrameBufferCache(size_t clearBeforeFrame);
+
virtual unsigned frameDurationAtIndex(size_t index) { return 0; }
enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery };
diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.h b/WebCore/platform/image-decoders/gif/GIFImageReader.h
index faa08d2..855e6be 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageReader.h
+++ b/WebCore/platform/image-decoders/gif/GIFImageReader.h
@@ -47,6 +47,8 @@
#define MAX_COLORS 256
#define MAX_HOLD_SIZE 256
+const int cLoopCountNotSeen = -2;
+
/* gif2.h
The interface for the GIF87/89a decoder.
*/
@@ -187,7 +189,7 @@ struct GIFImageReader {
screen_bgcolor = version = 0;
screen_width = screen_height = 0;
global_colormap_size = images_decoded = images_count = 0;
- loop_count = -1;
+ loop_count = cLoopCountNotSeen;
count = 0;
}
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
index 6571b99..a4f3dbd 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
@@ -36,6 +36,8 @@ class ICOImageReader;
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;
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
index 57fd9da..b4d7b2a 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -39,6 +39,8 @@ public:
JPEGImageDecoder();
~JPEGImageDecoder();
+ virtual String filenameExtension() const { return "jpg"; }
+
// Take the data and store it.
virtual void setData(SharedBuffer* data, bool allDataReceived);
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
index 926f1f2..8c73785 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
@@ -39,6 +39,8 @@ public:
PNGImageDecoder();
~PNGImageDecoder();
+ virtual String filenameExtension() const { return "png"; }
+
// Take the data and store it.
virtual void setData(SharedBuffer* data, bool allDataReceived);
diff --git a/WebCore/platform/image-decoders/skia/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/skia/BMPImageDecoder.cpp
new file mode 100644
index 0000000..08d5df5
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/BMPImageDecoder.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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 "config.h"
+#include "BMPImageDecoder.h"
+
+namespace WebCore {
+
+// Number of bits in .BMP used to store the file header (doesn't match
+// "sizeof(BMPImageDecoder::BitmapFileHeader)" since we omit some fields and
+// don't pack).
+static const size_t sizeOfFileHeader = 14;
+
+void BMPImageDecoder::decodeImage(SharedBuffer* data)
+{
+ // Read and process file header.
+ if ((m_decodedOffset < sizeOfFileHeader) && !processFileHeader(data))
+ return;
+
+ // Decode BMP.
+ decodeBMP(data);
+}
+
+bool BMPImageDecoder::processFileHeader(SharedBuffer* data)
+{
+ // Read file header.
+ ASSERT(!m_decodedOffset);
+ if (data->size() < sizeOfFileHeader)
+ return false;
+ const uint16_t fileType =
+ (data->data()[0] << 8) | static_cast<uint8_t>(data->data()[1]);
+ m_imgDataOffset = readUint32(data, 10);
+ m_decodedOffset = m_headerOffset = sizeOfFileHeader;
+
+ // See if this is a bitmap filetype we understand.
+ enum {
+ BMAP = 'BM',
+ // The following additional OS/2 2.x header values (see
+ // http://www.fileformat.info/format/os2bmp/egff.htm ) aren't widely
+ // decoded, and are unlikely to be in much use.
+ /*
+ ICON = 'IC',
+ POINTER = 'PT',
+ COLORICON = 'CI',
+ COLORPOINTER = 'CP',
+ BITMAPARRAY = 'BA',
+ */
+ };
+ if (fileType != BMAP)
+ m_failed = true;
+
+ return !m_failed;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/skia/BMPImageDecoder.h b/WebCore/platform/image-decoders/skia/BMPImageDecoder.h
new file mode 100644
index 0000000..065981f
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/BMPImageDecoder.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifndef BMPImageDecoder_h
+#define BMPImageDecoder_h
+
+#include "BMPImageReader.h"
+
+namespace WebCore {
+
+ // This class decodes the BMP image format.
+ class BMPImageDecoder : public BMPImageReader {
+ public:
+ virtual String filenameExtension() const { return "bmp"; }
+
+ // BMPImageReader
+ virtual void decodeImage(SharedBuffer*);
+
+ private:
+ // Processes the file header at the beginning of the data. Returns true if
+ // the file header could be decoded.
+ bool processFileHeader(SharedBuffer*);
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/image-decoders/skia/BMPImageReader.cpp b/WebCore/platform/image-decoders/skia/BMPImageReader.cpp
new file mode 100644
index 0000000..829b107
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/BMPImageReader.cpp
@@ -0,0 +1,835 @@
+/*
+ * 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 "config.h"
+#include "BMPImageReader.h"
+
+namespace WebCore {
+
+BMPImageReader::BMPImageReader()
+ : m_decodedOffset(0)
+ , m_headerOffset(0)
+ , m_imgDataOffset(0)
+ , m_andMaskState(None)
+ , m_isOS21x(false)
+ , m_isOS22x(false)
+ , m_isTopDown(false)
+ , m_needToProcessBitmasks(false)
+ , m_needToProcessColorTable(false)
+ , m_tableSizeInBytes(0)
+ , m_seenNonZeroAlphaPixel(false)
+ , m_seenZeroAlphaPixel(false)
+{
+ m_frameBufferCache.resize(1);
+
+ // Clue-in decodeBMP() that we need to detect the correct info header size.
+ memset(&m_infoHeader, 0, sizeof(m_infoHeader));
+}
+
+void BMPImageReader::setData(SharedBuffer* data, bool allDataReceived)
+{
+ ImageDecoder::setData(data, allDataReceived);
+
+ // NOTE: This function intentionally uses frameBufferAtIndex() instead of
+ // checking m_frameBufferCache.first() directly, so that it will do the
+ // right thing for ICOImageDecoder, which needs to override this accessor
+ // to support ICOs which contain PNGs.
+
+ // Return quickly when we can't do any more work.
+ if (m_failed || data->isEmpty()
+ || (frameBufferAtIndex(0)->status() == RGBA32Buffer::FrameComplete))
+ return;
+
+ // Decode as much as we can. This assumes |data| starts at the beginning
+ // of the image data, rather than containing just the latest chunk.
+ decodeImage(data);
+ if (m_failed) {
+ // Handle failure before getting the framebuffer below.
+ m_colorTable.clear();
+ return;
+ }
+
+ // If we got all the data but couldn't finish decoding, fail.
+ const bool finished =
+ (frameBufferAtIndex(0)->status() == RGBA32Buffer::FrameComplete);
+ if (allDataReceived && !finished)
+ m_failed = true;
+
+ // Release the color table when we no longer need it.
+ if (finished || m_failed)
+ m_colorTable.clear();
+}
+
+RGBA32Buffer* BMPImageReader::frameBufferAtIndex(size_t index)
+{
+ return index ? 0 : &m_frameBufferCache.first();
+}
+
+void BMPImageReader::decodeBMP(SharedBuffer* data)
+{
+ // Calculate size of info header.
+ if (!m_infoHeader.biSize && !getInfoHeaderSize(data))
+ return;
+
+ // Read and process info header.
+ if ((m_decodedOffset < (m_headerOffset + m_infoHeader.biSize))
+ && !processInfoHeader(data))
+ return;
+
+ // Read and process the bitmasks, if needed.
+ if (m_needToProcessBitmasks && !processBitmasks(data))
+ return;
+
+ // Read and process the color table, if needed.
+ if (m_needToProcessColorTable && !processColorTable(data))
+ return;
+
+ // Initialize frame buffer state, if needed.
+ if (m_frameBufferCache.first().status() == RGBA32Buffer::FrameEmpty) {
+ m_frameBufferCache.first().setRect(IntRect(IntPoint(), size()));
+ m_frameBufferCache.first().setStatus(RGBA32Buffer::FramePartial);
+ if (!m_frameBufferCache.first().setSize(m_infoHeader.biWidth,
+ m_infoHeader.biHeight)) {
+ // Unable to allocate.
+ m_failed = true;
+ return;
+ }
+
+ // setSize() calls eraseARGB(), which resets the alpha flag, so we force
+ // it back to false here. We'll set it true below in all cases where
+ // these 0s could actually show through.
+ m_frameBufferCache.first().setHasAlpha(false);
+ if (!m_isTopDown)
+ m_coord.setY(size().height() - 1);
+ }
+
+ // Decode the data.
+ if ((m_andMaskState != Decoding) && !pastEndOfImage(0)) {
+ if ((m_infoHeader.biCompression == RLE4)
+ || (m_infoHeader.biCompression == RLE8)
+ || (m_infoHeader.biCompression == RLE24)) {
+ if (!processRLEData(data))
+ return;
+ } else if (!processNonRLEData(data, false, 0))
+ return;
+ }
+
+ // If the image has an AND mask and there was no alpha data, process the
+ // mask.
+ if ((m_andMaskState == NotYetDecoded)
+ && !m_frameBufferCache.first().hasAlpha()) {
+ // Reset decoding coordinates to start of image.
+ m_coord.setX(0);
+ m_coord.setY(m_isTopDown ? 0 : (size().height() - 1));
+
+ // The AND mask is stored as 1-bit data.
+ m_infoHeader.biBitCount = 1;
+
+ m_andMaskState = Decoding;
+ }
+ if ((m_andMaskState == Decoding) && !processNonRLEData(data, false, 0))
+ return;
+
+ // Done!
+ m_frameBufferCache.first().setStatus(RGBA32Buffer::FrameComplete);
+}
+
+bool BMPImageReader::getInfoHeaderSize(SharedBuffer* data)
+{
+ // Get size of info header.
+ ASSERT(m_decodedOffset == m_headerOffset);
+ if ((m_decodedOffset > data->size())
+ || ((data->size() - m_decodedOffset) < 4))
+ return false;
+ m_infoHeader.biSize = readUint32(data, 0);
+ // Don't increment m_decodedOffset here, it just makes the code in
+ // processInfoHeader() more confusing.
+
+ // Don't allow the header to overflow (which would be harmless here, but
+ // problematic or at least confusing in other places), or to overrun the
+ // image data.
+ if (((m_headerOffset + m_infoHeader.biSize) < m_headerOffset)
+ || (m_imgDataOffset
+ && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize)))) {
+ m_failed = true;
+ return false;
+ }
+
+ // See if this is a header size we understand:
+ // OS/2 1.x: 12
+ if (m_infoHeader.biSize == 12)
+ m_isOS21x = true;
+ // Windows V3: 40
+ else if ((m_infoHeader.biSize == 40) || isWindowsV4Plus())
+ ;
+ // OS/2 2.x: any multiple of 4 between 16 and 64, inclusive, or 42 or 46
+ else if ((m_infoHeader.biSize >= 16) && (m_infoHeader.biSize <= 64)
+ && (((m_infoHeader.biSize & 3) == 0) || (m_infoHeader.biSize == 42)
+ || (m_infoHeader.biSize == 46)))
+ m_isOS22x = true;
+ else
+ m_failed = true;
+
+ return !m_failed;
+}
+
+bool BMPImageReader::processInfoHeader(SharedBuffer* data)
+{
+ // Read info header.
+ ASSERT(m_decodedOffset == m_headerOffset);
+ if ((m_decodedOffset > data->size())
+ || ((data->size() - m_decodedOffset) < m_infoHeader.biSize)
+ || !readInfoHeader(data))
+ return false;
+ m_decodedOffset += m_infoHeader.biSize;
+
+ // Sanity-check header values.
+ if (!isInfoHeaderValid()) {
+ m_failed = true;
+ return false;
+ }
+
+ // Make our size available to the caller.
+ if (!setSize(m_infoHeader.biWidth, m_infoHeader.biHeight)) {
+ m_failed = true;
+ return false;
+ }
+
+ // For paletted images, bitmaps can set biClrUsed to 0 to mean "all
+ // colors", so set it to the maximum number of colors for this bit depth.
+ // Also do this for bitmaps that put too large a value here.
+ if (m_infoHeader.biBitCount < 16) {
+ const uint32_t maxColors =
+ static_cast<uint32_t>(1) << m_infoHeader.biBitCount;
+ if ((m_infoHeader.biClrUsed == 0)
+ || (m_infoHeader.biClrUsed > maxColors))
+ m_infoHeader.biClrUsed = maxColors;
+ }
+
+ // For any bitmaps that set their BitCount to the wrong value, reset the
+ // counts now that we've calculated the number of necessary colors, since
+ // other code relies on this value being correct.
+ if (m_infoHeader.biCompression == RLE8)
+ m_infoHeader.biBitCount = 8;
+ else if (m_infoHeader.biCompression == RLE4)
+ m_infoHeader.biBitCount = 4;
+
+ // Tell caller what still needs to be processed.
+ if (m_infoHeader.biBitCount >= 16)
+ m_needToProcessBitmasks = true;
+ else if (m_infoHeader.biBitCount > 0)
+ m_needToProcessColorTable = true;
+
+ return true;
+}
+
+bool BMPImageReader::readInfoHeader(SharedBuffer* data)
+{
+ // Pre-initialize some fields that not all headers set.
+ m_infoHeader.biCompression = RGB;
+ m_infoHeader.biClrUsed = 0;
+
+ if (m_isOS21x) {
+ m_infoHeader.biWidth = readUint16(data, 4);
+ m_infoHeader.biHeight = readUint16(data, 6);
+ ASSERT(m_andMaskState == None); // ICO is a Windows format, not OS/2!
+ m_infoHeader.biBitCount = readUint16(data, 10);
+ return true;
+ }
+
+ m_infoHeader.biWidth = readUint32(data, 4);
+ m_infoHeader.biHeight = readUint32(data, 8);
+ if (m_andMaskState != None)
+ m_infoHeader.biHeight /= 2;
+ m_infoHeader.biBitCount = readUint16(data, 14);
+
+ // Read compression type, if present.
+ if (m_infoHeader.biSize >= 20) {
+ uint32_t biCompression = readUint32(data, 16);
+
+ // Detect OS/2 2.x-specific compression types.
+ if ((biCompression == 3) && (m_infoHeader.biBitCount == 1)) {
+ m_infoHeader.biCompression = HUFFMAN1D;
+ m_isOS22x = true;
+ } else if ((biCompression == 4) && (m_infoHeader.biBitCount == 24)) {
+ m_infoHeader.biCompression = RLE24;
+ m_isOS22x = true;
+ } else if (biCompression > 5) {
+ // Some type we don't understand.
+ m_failed = true;
+ return false;
+ } else
+ m_infoHeader.biCompression = static_cast<CompressionType>(biCompression);
+ }
+
+ // Read colors used, if present.
+ if (m_infoHeader.biSize >= 36)
+ m_infoHeader.biClrUsed = readUint32(data, 32);
+
+ // Windows V4+ can safely read the four bitmasks from 40-56 bytes in, so do
+ // that here. If the bit depth is less than 16, these values will be
+ // ignored by the image data decoders. If the bit depth is at least 16 but
+ // the compression format isn't BITFIELDS, these values will be ignored and
+ // overwritten* in processBitmasks().
+ // NOTE: We allow alpha here. Microsoft doesn't really document this well,
+ // but some BMPs appear to use it.
+ //
+ // For non-Windows V4+, m_bitMasks[] et. al will be initialized later
+ // during processBitmasks().
+ //
+ // *Except the alpha channel. Bizarrely, some RGB bitmaps expect decoders
+ // to pay attention to the alpha mask here, so there's a special case in
+ // processBitmasks() that doesn't always overwrite that value.
+ if (isWindowsV4Plus()) {
+ m_bitMasks[0] = readUint32(data, 40);
+ m_bitMasks[1] = readUint32(data, 44);
+ m_bitMasks[2] = readUint32(data, 48);
+ m_bitMasks[3] = readUint32(data, 52);
+ }
+
+ // Detect top-down BMPs.
+ if (m_infoHeader.biHeight < 0) {
+ m_isTopDown = true;
+ m_infoHeader.biHeight = -m_infoHeader.biHeight;
+ }
+
+ return true;
+}
+
+bool BMPImageReader::isInfoHeaderValid() const
+{
+ // Non-positive widths/heights are invalid. (We've already flipped the
+ // sign of the height for top-down bitmaps.)
+ if ((m_infoHeader.biWidth <= 0) || (m_infoHeader.biHeight == 0))
+ return false;
+
+ // Only Windows V3+ has top-down bitmaps.
+ if (m_isTopDown && (m_isOS21x || m_isOS22x))
+ return false;
+
+ // Only bit depths of 1, 4, 8, or 24 are universally supported.
+ if ((m_infoHeader.biBitCount != 1) && (m_infoHeader.biBitCount != 4)
+ && (m_infoHeader.biBitCount != 8)
+ && (m_infoHeader.biBitCount != 24)) {
+ // Windows V3+ additionally supports bit depths of 0 (for embedded
+ // JPEG/PNG images), 16, and 32.
+ if (m_isOS21x || m_isOS22x)
+ return false;
+ if ((m_infoHeader.biBitCount != 0)
+ && (m_infoHeader.biBitCount != 16)
+ && (m_infoHeader.biBitCount != 32))
+ return false;
+ }
+
+ // Each compression type is only valid with certain bit depths (except RGB,
+ // which can be used with any bit depth). Also, some formats do not
+ // some compression types.
+ switch (m_infoHeader.biCompression) {
+ case RGB:
+ if (m_infoHeader.biBitCount == 0)
+ return false;
+ break;
+
+ case RLE8:
+ // Supposedly there are undocumented formats like "BitCount = 1,
+ // Compression = RLE4" (which means "4 bit, but with a 2-color table"),
+ // so also allow the paletted RLE compression types to have too low a
+ // bit count; we'll correct this later.
+ if (m_infoHeader.biBitCount == 0 || m_infoHeader.biBitCount > 8)
+ return false;
+ break;
+
+ case RLE4:
+ // See comments in RLE8.
+ if (m_infoHeader.biBitCount == 0 || m_infoHeader.biBitCount > 4)
+ return false;
+ break;
+
+ case BITFIELDS:
+ // Only valid for Windows V3+.
+ if (m_isOS21x || m_isOS22x)
+ return false;
+ if ((m_infoHeader.biBitCount != 16) && (m_infoHeader.biBitCount != 32))
+ return false;
+ break;
+
+ case JPEG:
+ case PNG:
+ // Only valid for Windows V3+.
+ if (m_isOS21x || m_isOS22x)
+ return false;
+ if (m_infoHeader.biBitCount != 0)
+ return false;
+ break;
+
+ case HUFFMAN1D:
+ // Only valid for OS/2 2.x.
+ if (!m_isOS22x)
+ return false;
+ if (m_infoHeader.biBitCount != 1)
+ return false;
+ break;
+
+ case RLE24:
+ // Only valid for OS/2 2.x.
+ if (!m_isOS22x)
+ return false;
+ if (m_infoHeader.biBitCount != 24)
+ return false;
+ break;
+
+ default:
+ // Some type we don't understand. This should have been caught in
+ // readInfoHeader().
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ // Top-down bitmaps cannot be compressed; they must be RGB or BITFIELDS.
+ if (m_isTopDown && (m_infoHeader.biCompression != RGB)
+ && (m_infoHeader.biCompression != BITFIELDS))
+ return false;
+
+ // Reject the following valid bitmap types that we don't currently bother
+ // decoding. Few other people decode these either, they're unlikely to be
+ // in much use.
+ // TODO(pkasting): Consider supporting these someday.
+ // * Bitmaps larger than 2^16 pixels in either dimension (Windows
+ // probably doesn't draw these well anyway, and the decoded data would
+ // take a lot of memory).
+ if ((m_infoHeader.biWidth >= (1 << 16))
+ || (m_infoHeader.biHeight >= (1 << 16)))
+ return false;
+ // * Windows V3+ JPEG-in-BMP and PNG-in-BMP bitmaps (supposedly not found
+ // in the wild, only used to send data to printers?).
+ if ((m_infoHeader.biCompression == JPEG)
+ || (m_infoHeader.biCompression == PNG))
+ return false;
+ // * OS/2 2.x Huffman-encoded monochrome bitmaps (see
+ // http://www.fileformat.info/mirror/egff/ch09_05.htm , re: "G31D"
+ // algorithm).
+ if (m_infoHeader.biCompression == HUFFMAN1D)
+ return false;
+
+ return true;
+}
+
+bool BMPImageReader::processBitmasks(SharedBuffer* data)
+{
+ // Create m_bitMasks[] values.
+ if (m_infoHeader.biCompression != BITFIELDS) {
+ // The format doesn't actually use bitmasks. To simplify the decode
+ // logic later, create bitmasks for the RGB data. For Windows V4+,
+ // this overwrites the masks we read from the header, which are
+ // supposed to be ignored in non-BITFIELDS cases.
+ // 16 bits: MSB <- xRRRRRGG GGGBBBBB -> LSB
+ // 24/32 bits: MSB <- [AAAAAAAA] RRRRRRRR GGGGGGGG BBBBBBBB -> LSB
+ const int numBits = (m_infoHeader.biBitCount == 16) ? 5 : 8;
+ for (int i = 0; i <= 2; ++i) {
+ m_bitMasks[i] =
+ ((static_cast<uint32_t>(1) << (numBits * (3 - i))) - 1) ^
+ ((static_cast<uint32_t>(1) << (numBits * (2 - i))) - 1);
+ }
+
+ // For Windows V4+ 32-bit RGB, don't overwrite the alpha mask from the
+ // header (see note in readInfoHeader()).
+ if (m_infoHeader.biBitCount < 32)
+ m_bitMasks[3] = 0;
+ else if (!isWindowsV4Plus())
+ m_bitMasks[3] = static_cast<uint32_t>(0xff000000);
+ } else if (!isWindowsV4Plus()) {
+ // For Windows V4+ BITFIELDS mode bitmaps, this was already done when
+ // we read the info header.
+
+ // Fail if we don't have enough file space for the bitmasks.
+ static const int SIZEOF_BITMASKS = 12;
+ if (((m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS) < (m_headerOffset + m_infoHeader.biSize))
+ || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS)))) {
+ m_failed = true;
+ return false;
+ }
+
+ // Read bitmasks.
+ if ((data->size() - m_decodedOffset) < SIZEOF_BITMASKS)
+ return false;
+ m_bitMasks[0] = readUint32(data, 0);
+ m_bitMasks[1] = readUint32(data, 4);
+ m_bitMasks[2] = readUint32(data, 8);
+ // No alpha in anything other than Windows V4+.
+ m_bitMasks[3] = 0;
+
+ m_decodedOffset += SIZEOF_BITMASKS;
+ }
+
+ // We've now decoded all the non-image data we care about. Skip anything
+ // else before the actual raster data.
+ if (m_imgDataOffset)
+ m_decodedOffset = m_imgDataOffset;
+ m_needToProcessBitmasks = false;
+
+ // Check masks and set shift values.
+ for (int i = 0; i < 4; ++i) {
+ // Trim the mask to the allowed bit depth. Some Windows V4+ BMPs
+ // specify a bogus alpha channel in bits that don't exist in the pixel
+ // data (for example, bits 25-31 in a 24-bit RGB format).
+ if (m_infoHeader.biBitCount < 32)
+ m_bitMasks[i] &= ((static_cast<uint32_t>(1) << m_infoHeader.biBitCount) - 1);
+
+ // For empty masks (common on the alpha channel, especially after the
+ // trimming above), quickly clear the shifts and continue, to avoid an
+ // infinite loop in the counting code below.
+ uint32_t tempMask = m_bitMasks[i];
+ if (!tempMask) {
+ m_bitShiftsRight[i] = m_bitShiftsLeft[i] = 0;
+ continue;
+ }
+
+ // Make sure bitmask does not overlap any other bitmasks.
+ for (int j = 0; j < i; ++j) {
+ if (tempMask & m_bitMasks[j]) {
+ m_failed = true;
+ return false;
+ }
+ }
+
+ // Count offset into pixel data.
+ for (m_bitShiftsRight[i] = 0; !(tempMask & 1); tempMask >>= 1)
+ ++m_bitShiftsRight[i];
+
+ // Count size of mask.
+ for (m_bitShiftsLeft[i] = 8; tempMask & 1; tempMask >>= 1)
+ --m_bitShiftsLeft[i];
+
+ // Make sure bitmask is contiguous.
+ if (tempMask) {
+ m_failed = true;
+ return false;
+ }
+
+ // Since RGBABuffer tops out at 8 bits per channel, adjust the shift
+ // amounts to use the most significant 8 bits of the channel.
+ if (m_bitShiftsLeft[i] < 0) {
+ m_bitShiftsRight[i] -= m_bitShiftsLeft[i];
+ m_bitShiftsLeft[i] = 0;
+ }
+ }
+
+ return true;
+}
+
+bool BMPImageReader::processColorTable(SharedBuffer* data)
+{
+ m_tableSizeInBytes = m_infoHeader.biClrUsed * (m_isOS21x ? 3 : 4);
+
+ // Fail if we don't have enough file space for the color table.
+ if (((m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes) < (m_headerOffset + m_infoHeader.biSize))
+ || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes)))) {
+ m_failed = true;
+ return false;
+ }
+
+ // Read color table.
+ if ((m_decodedOffset > data->size())
+ || ((data->size() - m_decodedOffset) < m_tableSizeInBytes))
+ return false;
+ m_colorTable.resize(m_infoHeader.biClrUsed);
+ for (size_t i = 0; i < m_infoHeader.biClrUsed; ++i) {
+ m_colorTable[i].rgbBlue = data->data()[m_decodedOffset++];
+ m_colorTable[i].rgbGreen = data->data()[m_decodedOffset++];
+ m_colorTable[i].rgbRed = data->data()[m_decodedOffset++];
+ // Skip padding byte (not present on OS/2 1.x).
+ if (!m_isOS21x)
+ ++m_decodedOffset;
+ }
+
+ // We've now decoded all the non-image data we care about. Skip anything
+ // else before the actual raster data.
+ if (m_imgDataOffset)
+ m_decodedOffset = m_imgDataOffset;
+ m_needToProcessColorTable = false;
+
+ return true;
+}
+
+bool BMPImageReader::processRLEData(SharedBuffer* data)
+{
+ if (m_decodedOffset > data->size())
+ return false;
+
+ // RLE decoding is poorly specified. Two main problems:
+ // (1) Are EOL markers necessary? What happens when we have too many
+ // pixels for one row?
+ // http://www.fileformat.info/format/bmp/egff.htm says extra pixels
+ // should wrap to the next line. Real BMPs I've encountered seem to
+ // instead expect extra pixels to be ignored until the EOL marker is
+ // seen, although this has only happened in a few cases and I suspect
+ // those BMPs may be invalid. So we only change lines on EOL (or Delta
+ // with dy > 0), and fail in most cases when pixels extend past the end
+ // of the line.
+ // (2) When Delta, EOL, or EOF are seen, what happens to the "skipped"
+ // pixels?
+ // http://www.daubnet.com/formats/BMP.html says these should be filled
+ // with color 0. However, the "do nothing" and "don't care" comments
+ // of other references suggest leaving these alone, i.e. letting them
+ // be transparent to the background behind the image. This seems to
+ // match how MSPAINT treats BMPs, so we do that. Note that when we
+ // actually skip pixels for a case like this, we need to note on the
+ // framebuffer that we have alpha.
+
+ // Impossible to decode row-at-a-time, so just do things as a stream of
+ // bytes.
+ while (true) {
+ // Every entry takes at least two bytes; bail if there isn't enough
+ // data.
+ if ((data->size() - m_decodedOffset) < 2)
+ return false;
+
+ // For every entry except EOF, we'd better not have reached the end of
+ // the image.
+ const uint8_t count = data->data()[m_decodedOffset];
+ const uint8_t code = data->data()[m_decodedOffset + 1];
+ if (((count != 0) || (code != 1)) && pastEndOfImage(0)) {
+ m_failed = true;
+ return false;
+ }
+
+ // Decode.
+ if (count == 0) {
+ switch (code) {
+ case 0: // Magic token: EOL
+ // Skip any remaining pixels in this row.
+ if (m_coord.x() < size().width())
+ m_frameBufferCache.first().setHasAlpha(true);
+ moveBufferToNextRow();
+
+ m_decodedOffset += 2;
+ break;
+
+ case 1: // Magic token: EOF
+ // Skip any remaining pixels in the image.
+ if ((m_coord.x() < size().width())
+ || (m_isTopDown ? (m_coord.y() < (size().height() - 1)) : (m_coord.y() > 0)))
+ m_frameBufferCache.first().setHasAlpha(true);
+ return true;
+
+ case 2: { // Magic token: Delta
+ // The next two bytes specify dx and dy. Bail if there isn't
+ // enough data.
+ if ((data->size() - m_decodedOffset) < 4)
+ return false;
+
+ // Fail if this takes us past the end of the desired row or
+ // past the end of the image.
+ const uint8_t dx = data->data()[m_decodedOffset + 2];
+ const uint8_t dy = data->data()[m_decodedOffset + 3];
+ if ((dx != 0) || (dy != 0))
+ m_frameBufferCache.first().setHasAlpha(true);
+ if (((m_coord.x() + dx) > size().width()) ||
+ pastEndOfImage(dy)) {
+ m_failed = true;
+ return false;
+ }
+
+ // Skip intervening pixels.
+ m_coord.move(dx, m_isTopDown ? dy : -dy);
+
+ m_decodedOffset += 4;
+ break;
+ }
+
+ default: // Absolute mode
+ // |code| pixels specified as in BI_RGB, zero-padded at the end
+ // to a multiple of 16 bits.
+ // Because processNonRLEData() expects m_decodedOffset to
+ // point to the beginning of the pixel data, bump it past
+ // the escape bytes and then reset if decoding failed.
+ m_decodedOffset += 2;
+ if (!processNonRLEData(data, true, code)) {
+ m_decodedOffset -= 2;
+ return false;
+ }
+ break;
+ }
+ } else { // Encoded mode
+ // The following color data is repeated for |count| total pixels.
+ // Strangely, some BMPs seem to specify excessively large counts
+ // here; ignore pixels past the end of the row.
+ const int endX = std::min(m_coord.x() + count, size().width());
+
+ if (m_infoHeader.biCompression == RLE24) {
+ // Bail if there isn't enough data.
+ if ((data->size() - m_decodedOffset) < 4)
+ return false;
+
+ // One BGR triple that we copy |count| times.
+ fillRGBA(endX, data->data()[m_decodedOffset + 3],
+ data->data()[m_decodedOffset + 2], code, 0xff);
+ m_decodedOffset += 4;
+ } else {
+ // RLE8 has one color index that gets repeated; RLE4 has two
+ // color indexes in the upper and lower 4 bits of the byte,
+ // which are alternated.
+ size_t colorIndexes[2] = {code, code};
+ if (m_infoHeader.biCompression == RLE4) {
+ colorIndexes[0] = (colorIndexes[0] >> 4) & 0xf;
+ colorIndexes[1] &= 0xf;
+ }
+ if ((colorIndexes[0] >= m_infoHeader.biClrUsed)
+ || (colorIndexes[1] >= m_infoHeader.biClrUsed)) {
+ m_failed = true;
+ return false;
+ }
+ for (int which = 0; m_coord.x() < endX; ) {
+ setI(colorIndexes[which]);
+ which = !which;
+ }
+
+ m_decodedOffset += 2;
+ }
+ }
+ }
+}
+
+bool BMPImageReader::processNonRLEData(SharedBuffer* data, bool inRLE, int numPixels)
+{
+ if (m_decodedOffset > data->size())
+ return false;
+
+ if (!inRLE)
+ numPixels = size().width();
+
+ // Fail if we're being asked to decode more pixels than remain in the row.
+ const int endX = m_coord.x() + numPixels;
+ if (endX > size().width()) {
+ m_failed = true;
+ return false;
+ }
+
+ // Determine how many bytes of data the requested number of pixels
+ // requires.
+ const size_t pixelsPerByte = 8 / m_infoHeader.biBitCount;
+ const size_t bytesPerPixel = m_infoHeader.biBitCount / 8;
+ const size_t unpaddedNumBytes = (m_infoHeader.biBitCount < 16)
+ ? ((numPixels + pixelsPerByte - 1) / pixelsPerByte)
+ : (numPixels * bytesPerPixel);
+ // RLE runs are zero-padded at the end to a multiple of 16 bits. Non-RLE
+ // data is in rows and is zero-padded to a multiple of 32 bits.
+ const size_t alignBits = inRLE ? 1 : 3;
+ const size_t paddedNumBytes = (unpaddedNumBytes + alignBits) & ~alignBits;
+
+ // Decode as many rows as we can. (For RLE, where we only want to decode
+ // one row, we've already checked that this condition is true.)
+ while (!pastEndOfImage(0)) {
+ // Bail if we don't have enough data for the desired number of pixels.
+ if ((data->size() - m_decodedOffset) < paddedNumBytes)
+ return false;
+
+ if (m_infoHeader.biBitCount < 16) {
+ // Paletted data. Pixels are stored little-endian within bytes.
+ // Decode pixels one byte at a time, left to right (so, starting at
+ // the most significant bits in the byte).
+ const uint8_t mask = (1 << m_infoHeader.biBitCount) - 1;
+ for (size_t byte = 0; byte < unpaddedNumBytes; ++byte) {
+ uint8_t pixelData = data->data()[m_decodedOffset + byte];
+ for (size_t pixel = 0; (pixel < pixelsPerByte) && (m_coord.x() < endX); ++pixel) {
+ const size_t colorIndex =
+ (pixelData >> (8 - m_infoHeader.biBitCount)) & mask;
+ if (m_andMaskState == Decoding) {
+ // There's no way to accurately represent an AND + XOR
+ // operation as an RGBA image, so where the AND values
+ // are 1, we simply set the framebuffer pixels to fully
+ // transparent, on the assumption that most ICOs on the
+ // web will not be doing a lot of inverting.
+ if (colorIndex) {
+ setRGBA(0, 0, 0, 0);
+ m_frameBufferCache.first().setHasAlpha(true);
+ } else
+ m_coord.move(1, 0);
+ } else {
+ if (colorIndex >= m_infoHeader.biClrUsed) {
+ m_failed = true;
+ return false;
+ }
+ setI(colorIndex);
+ }
+ pixelData <<= m_infoHeader.biBitCount;
+ }
+ }
+ } else {
+ // RGB data. Decode pixels one at a time, left to right.
+ while (m_coord.x() < endX) {
+ const uint32_t pixel = readCurrentPixel(data, bytesPerPixel);
+
+ // Some BMPs specify an alpha channel but don't actually use it
+ // (it contains all 0s). To avoid displaying these images as
+ // fully-transparent, decode as if images are fully opaque
+ // until we actually see a non-zero alpha value; at that point,
+ // reset any previously-decoded pixels to fully transparent and
+ // continue decoding based on the real alpha channel values.
+ // As an optimization, avoid setting "hasAlpha" to true for
+ // images where all alpha values are 255; opaque images are
+ // faster to draw.
+ int alpha = getAlpha(pixel);
+ if (!m_seenNonZeroAlphaPixel && (alpha == 0)) {
+ m_seenZeroAlphaPixel = true;
+ alpha = 255;
+ } else {
+ m_seenNonZeroAlphaPixel = true;
+ if (m_seenZeroAlphaPixel) {
+ // The eraseARGB() call here also sets "hasAlpha" true.
+ m_frameBufferCache.first().bitmap().eraseARGB(0, 0, 0,
+ 0);
+ m_seenZeroAlphaPixel = false;
+ } else if (alpha != 255)
+ m_frameBufferCache.first().setHasAlpha(true);
+ }
+
+ setRGBA(getComponent(pixel, 0), getComponent(pixel, 1),
+ getComponent(pixel, 2), alpha);
+ }
+ }
+
+ // Success, keep going.
+ m_decodedOffset += paddedNumBytes;
+ if (inRLE)
+ return true;
+ moveBufferToNextRow();
+ }
+
+ // Finished decoding whole image.
+ return true;
+}
+
+void BMPImageReader::moveBufferToNextRow()
+{
+ m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/skia/BMPImageReader.h b/WebCore/platform/image-decoders/skia/BMPImageReader.h
new file mode 100644
index 0000000..0edf7b0
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/BMPImageReader.h
@@ -0,0 +1,327 @@
+/*
+ * 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.
+ */
+
+#ifndef BMPImageReader_h
+#define BMPImageReader_h
+
+#include <stdint.h>
+#include "ImageDecoder.h"
+
+namespace WebCore {
+
+ // This class decodes a BMP image. It is used as a base for the BMP and ICO
+ // decoders, which wrap it in the appropriate code to read file headers, etc.
+ class BMPImageReader : public ImageDecoder {
+ public:
+ BMPImageReader();
+
+ // Does the actual decoding. |data| starts at the beginning of the file,
+ // but may be incomplete.
+ virtual void decodeImage(SharedBuffer* data) = 0;
+
+ // ImageDecoder
+ virtual void setData(SharedBuffer* data, bool allDataReceived);
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+
+ protected:
+ enum AndMaskState {
+ None,
+ NotYetDecoded,
+ Decoding,
+ };
+
+ // Decodes a single BMP, starting with an info header.
+ void decodeBMP(SharedBuffer* data);
+
+ // Read a value from |data[m_decodedOffset + additionalOffset]|, converting
+ // from little to native endianness.
+ inline uint16_t readUint16(SharedBuffer* data, int additionalOffset) const
+ {
+ uint16_t result;
+ memcpy(&result, &data->data()[m_decodedOffset + additionalOffset], 2);
+ #if PLATFORM(BIG_ENDIAN)
+ result = ((result & 0xff) << 8) | ((result & 0xff00) >> 8);
+ #endif
+ return result;
+ }
+
+ inline uint32_t readUint32(SharedBuffer* data, int additionalOffset) const
+ {
+ uint32_t result;
+ memcpy(&result, &data->data()[m_decodedOffset + additionalOffset], 4);
+ #if PLATFORM(BIG_ENDIAN)
+ result = ((result & 0xff) << 24) | ((result & 0xff00) << 8) |
+ ((result & 0xff0000) >> 8) | ((result & 0xff000000) >> 24);
+ #endif
+ return result;
+ }
+
+ // An index into |m_data| representing how much we've already decoded.
+ size_t m_decodedOffset;
+
+ // The file offset at which the BMP info header starts.
+ size_t m_headerOffset;
+
+ // The file offset at which the actual image bits start. When decoding ICO
+ // files, this is set to 0, since it's not stored anywhere in a header; the
+ // reader functions expect the image data to start immediately after the
+ // header and (if necessary) color table.
+ size_t m_imgDataOffset;
+
+ // ICOs store a 1bpp "mask" immediately after the main bitmap image data
+ // (and, confusingly, add its height to the biHeight value in the info
+ // header, thus doubling it). This variable tracks whether we have such a
+ // mask and if we've started decoding it yet.
+ AndMaskState m_andMaskState;
+
+ private:
+ // The various BMP compression types. We don't currently decode all these.
+ enum CompressionType {
+ // Universal types
+ RGB = 0,
+ RLE8 = 1,
+ RLE4 = 2,
+ // Windows V3+ only
+ BITFIELDS = 3,
+ JPEG = 4,
+ PNG = 5,
+ // OS/2 2.x-only
+ HUFFMAN1D, // Stored in file as 3
+ RLE24, // Stored in file as 4
+ };
+
+ // These are based on the Windows BITMAPINFOHEADER and RGBTRIPLE structs,
+ // but with unnecessary entries removed.
+ struct BitmapInfoHeader {
+ uint32_t biSize;
+ int32_t biWidth;
+ int32_t biHeight;
+ uint16_t biBitCount;
+ CompressionType biCompression;
+ uint32_t biClrUsed;
+ };
+ struct RGBTriple {
+ uint8_t rgbBlue;
+ uint8_t rgbGreen;
+ uint8_t rgbRed;
+ };
+
+ // Determines the size of the BMP info header. Returns true if the size is
+ // valid.
+ bool getInfoHeaderSize(SharedBuffer* data);
+
+ // Processes the BMP info header. Returns true if the info header could be
+ // decoded.
+ bool processInfoHeader(SharedBuffer* data);
+
+ // Helper function for processInfoHeader() which does the actual reading of
+ // header values from the byte stream. Returns false on error.
+ bool readInfoHeader(SharedBuffer* data);
+
+ // Returns true if this is a Windows V4+ BMP.
+ inline bool isWindowsV4Plus() const
+ {
+ // Windows V4 info header is 108 bytes. V5 is 124 bytes.
+ return (m_infoHeader.biSize == 108) || (m_infoHeader.biSize == 124);
+ }
+
+ // Returns false if consistency errors are found in the info header.
+ bool isInfoHeaderValid() const;
+
+ // For BI_BITFIELDS images, initializes the m_bitMasks[] and m_bitOffsets[]
+ // arrays. processInfoHeader() will initialize these for other compression
+ // types where needed.
+ bool processBitmasks(SharedBuffer* data);
+
+ // For paletted images, allocates and initializes the m_colorTable[] array.
+ bool processColorTable(SharedBuffer* data);
+
+ // Processes an RLE-encoded image. Returns true if the entire image was
+ // decoded.
+ bool processRLEData(SharedBuffer* data);
+
+ // Processes a set of non-RLE-compressed pixels. Two cases:
+ // * inRLE = true: the data is inside an RLE-encoded bitmap. Tries to
+ // process |numPixels| pixels on the current row; returns true on
+ // success.
+ // * inRLE = false: the data is inside a non-RLE-encoded bitmap.
+ // |numPixels| is ignored. Expects |m_coord| to point at the beginning
+ // of the next row to be decoded. Tries to process as many complete
+ // rows as possible. Returns true if the whole image was decoded.
+ bool processNonRLEData(SharedBuffer* data, bool inRLE, int numPixels);
+
+ // Returns true if the current y-coordinate plus |numRows| would be past
+ // the end of the image. Here "plus" means "toward the end of the image",
+ // so downwards for m_isTopDown images and upwards otherwise.
+ inline bool pastEndOfImage(int numRows)
+ {
+ return m_isTopDown
+ ? ((m_coord.y() + numRows) >= size().height())
+ : ((m_coord.y() - numRows) < 0);
+ }
+
+ // Returns the pixel data for the current X coordinate in a uint32_t.
+ // Assumes m_decodedOffset has been set to the beginning of the current
+ // row.
+ // NOTE: Only as many bytes of the return value as are needed to hold the
+ // pixel data will actually be set.
+ inline uint32_t readCurrentPixel(SharedBuffer* data, int bytesPerPixel) const
+ {
+ const int additionalOffset = m_coord.x() * bytesPerPixel;
+ switch (bytesPerPixel) {
+ case 2:
+ return readUint16(data, additionalOffset);
+
+ case 3: {
+ // It doesn't matter that we never set the most significant byte of
+ // the return value here in little-endian mode, the caller won't
+ // read it.
+ uint32_t pixel;
+ memcpy(&pixel,
+ &data->data()[m_decodedOffset + additionalOffset], 3);
+ #if PLATFORM(BIG_ENDIAN)
+ pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) |
+ ((pixel & 0xff000000) >> 24);
+ #endif
+ return pixel;
+ }
+
+ case 4:
+ return readUint32(data, additionalOffset);
+
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+ }
+
+ // Returns the value of the desired component (0, 1, 2, 3 == R, G, B, A) in
+ // the given pixel data.
+ inline unsigned getComponent(uint32_t pixel, int component) const
+ {
+ return ((pixel & m_bitMasks[component]) >> m_bitShiftsRight[component])
+ << m_bitShiftsLeft[component];
+ }
+
+ inline unsigned getAlpha(uint32_t pixel) const
+ {
+ // For images without alpha, return alpha of 0xff.
+ if (m_bitMasks[3] == 0)
+ return 0xff;
+
+ return getComponent(pixel, 3);
+ }
+
+ // Sets the current pixel to the color given by |colorIndex|. This also
+ // increments the relevant local variables to move the current pixel right
+ // by one.
+ inline void setI(size_t colorIndex)
+ {
+ setRGBA(m_colorTable[colorIndex].rgbRed, m_colorTable[colorIndex].rgbGreen,
+ m_colorTable[colorIndex].rgbBlue, 0xff);
+ }
+
+ // Like setI(), but with the individual component values specified.
+ inline void setRGBA(unsigned red, unsigned green, unsigned blue, unsigned alpha)
+ {
+ RGBA32Buffer::setRGBA(
+ m_frameBufferCache.first().bitmap().getAddr32(m_coord.x(), m_coord.y()),
+ red, green, blue, alpha);
+ m_coord.move(1, 0);
+ }
+
+ // Fills pixels from the current X-coordinate up to, but not including,
+ // |endCoord| with the color given by the individual components. This also
+ // increments the relevant local variables to move the current pixel right
+ // to |endCoord|.
+ inline void fillRGBA(int endCoord, unsigned red, unsigned green, unsigned blue, unsigned alpha)
+ {
+ while (m_coord.x() < endCoord)
+ setRGBA(red, green, blue, alpha);
+ }
+
+ // Resets the relevant local variables to start drawing at the left edge of
+ // the "next" row, where "next" is above or below the current row depending
+ // on the value of |m_isTopDown|.
+ void moveBufferToNextRow();
+
+ // The BMP info header.
+ BitmapInfoHeader m_infoHeader;
+
+ // True if this is an OS/2 1.x (aka Windows 2.x) BMP. The struct layouts
+ // for this type of BMP are slightly different from the later, more common
+ // formats.
+ bool m_isOS21x;
+
+ // True if this is an OS/2 2.x BMP. The meanings of compression types 3
+ // and 4 for this type of BMP differ from Windows V3+ BMPs.
+ //
+ // This will be falsely negative in some cases, but only ones where the way
+ // we misinterpret the data is irrelevant.
+ bool m_isOS22x;
+
+ // True if the BMP is not vertically flipped, that is, the first line of
+ // raster data in the file is the top line of the image.
+ bool m_isTopDown;
+
+ // These flags get set to false as we finish each processing stage.
+ bool m_needToProcessBitmasks;
+ bool m_needToProcessColorTable;
+
+ // Masks/offsets for the color values for non-palette formats. These are
+ // bitwise, with array entries 0, 1, 2, 3 corresponding to R, G, B, A.
+ //
+ // The right/left shift values are meant to be applied after the masks.
+ // We need to right shift to compensate for the bitfields' offsets into the
+ // 32 bits of pixel data, and left shift to scale the color values up for
+ // fields with less than 8 bits of precision. Sadly, we can't just combine
+ // these into one shift value because the net shift amount could go either
+ // direction. (If only "<< -x" were equivalent to ">> x"...)
+ uint32_t m_bitMasks[4];
+ int m_bitShiftsRight[4];
+ int m_bitShiftsLeft[4];
+
+ // The color palette, for paletted formats.
+ size_t m_tableSizeInBytes;
+ Vector<RGBTriple> m_colorTable;
+
+ // The coordinate to which we've decoded the image.
+ IntPoint m_coord;
+
+ // Variables that track whether we've seen pixels with alpha values != 0
+ // and == 0, respectively. See comments in processNonRLEData() on how
+ // these are used.
+ bool m_seenNonZeroAlphaPixel;
+ bool m_seenZeroAlphaPixel;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp
new file mode 100644
index 0000000..38bfa97
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ *
+ * 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 "GIFImageDecoder.h"
+#include "GIFImageReader.h"
+
+namespace WebCore {
+
+class GIFImageDecoderPrivate {
+public:
+ GIFImageDecoderPrivate(GIFImageDecoder* decoder = 0)
+ : m_reader(decoder)
+ , m_readOffset(0)
+ {
+ }
+
+ ~GIFImageDecoderPrivate()
+ {
+ m_reader.close();
+ }
+
+ 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,
+ query,
+ haltFrame);
+ }
+
+ unsigned frameCount() const { return m_reader.images_count; }
+ int repetitionCount() const { return m_reader.loop_count; }
+
+ void setReadOffset(unsigned o) { m_readOffset = o; }
+
+ bool isTransparent() const { return m_reader.frame_reader->is_transparent; }
+
+ 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;
+ } else {
+ map = m_reader.global_colormap;
+ size = m_reader.global_colormap_size;
+ }
+ }
+
+ unsigned frameXOffset() const { return m_reader.frame_reader->x_offset; }
+ unsigned frameYOffset() const { return m_reader.frame_reader->y_offset; }
+ unsigned frameWidth() const { return m_reader.frame_reader->width; }
+ unsigned frameHeight() const { return m_reader.frame_reader->height; }
+
+ int transparentPixel() const { return m_reader.frame_reader->tpixel; }
+
+ unsigned duration() const { return m_reader.frame_reader->delay_time; }
+
+private:
+ GIFImageReader m_reader;
+ unsigned m_readOffset;
+};
+
+GIFImageDecoder::GIFImageDecoder()
+ : m_frameCountValid(true)
+ , m_repetitionCount(cAnimationLoopOnce)
+ , m_reader(0)
+{
+}
+
+GIFImageDecoder::~GIFImageDecoder()
+{
+ delete m_reader;
+}
+
+// Take the data and store it.
+void GIFImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
+{
+ if (m_failed)
+ return;
+
+ // Cache our new data.
+ ImageDecoder::setData(data, allDataReceived);
+
+ // Our frame count is now unknown.
+ m_frameCountValid = false;
+
+ // Create the GIF reader.
+ if (!m_reader && !m_failed)
+ m_reader = new GIFImageDecoderPrivate(this);
+}
+
+// Whether or not the size information has been decoded yet.
+bool GIFImageDecoder::isSizeAvailable() const
+{
+ // If we have pending data to decode, send it to the GIF reader now.
+ if (!ImageDecoder::isSizeAvailable() && m_reader) {
+ if (m_failed)
+ return false;
+
+ // The decoder will go ahead and aggressively consume everything up until the first
+ // size is encountered.
+ decode(GIFSizeQuery, 0);
+ }
+
+ return !m_failed && ImageDecoder::isSizeAvailable();
+}
+
+// The total number of frames for the image. Will scan the image data for the answer
+// (without necessarily decoding all of the individual frames).
+int GIFImageDecoder::frameCount()
+{
+ // If the decoder had an earlier error, we will just return what we had decoded
+ // so far.
+ if (!m_frameCountValid) {
+ // FIXME: Scanning all the data has O(n^2) behavior if the data were to come in really
+ // slowly. Might be interesting to try to clone our existing read session to preserve
+ // 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;
+ // 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());
+ }
+
+ return m_frameBufferCache.size();
+}
+
+// The number of repetitions to perform for an animation loop.
+int GIFImageDecoder::repetitionCount() const
+{
+ // This value can arrive at any point in the image data stream. Most GIFs
+ // in the wild declare it near the beginning of the file, so it usually is
+ // set by the time we've decoded the size, but (depending on the GIF and the
+ // packets sent back by the webserver) not always. Our caller is
+ // responsible for waiting until image decoding has finished to ask this if
+ // it needs an authoritative answer. In the meantime, we should default to
+ // "loop once".
+ if (m_reader) {
+ // Added wrinkle: ImageSource::clear() may destroy the reader, making
+ // the result from the reader _less_ authoritative on future calls. To
+ // detect this, the reader returns cLoopCountNotSeen (-2) instead of
+ // cAnimationLoopOnce (-1) when its current incarnation hasn't actually
+ // seen a loop count yet; in this case we return our previously-cached
+ // value.
+ const int repetitionCount = m_reader->repetitionCount();
+ if (repetitionCount != cLoopCountNotSeen)
+ m_repetitionCount = repetitionCount;
+ }
+ return m_repetitionCount;
+}
+
+RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index)
+{
+ if (index >= static_cast<size_t>(frameCount()))
+ return 0;
+
+ RGBA32Buffer& frame = m_frameBufferCache[index];
+ if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
+ decode(GIFFullQuery, index+1); // Decode this frame.
+ return &frame;
+}
+
+void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame)
+{
+ // In some cases, like if the decoder was destroyed while animating, we
+ // can be asked to clear more frames than we currently have.
+ if (m_frameBufferCache.isEmpty())
+ return; // Nothing to do.
+ // The "-1" here is tricky. It does not mean that |clearBeforeFrame| is the
+ // last frame we wish to preserve, but rather that we never want to clear
+ // the very last frame in the cache: it's empty (so clearing it is
+ // pointless), it's partial (so we don't want to clear it anyway), or the
+ // cache could be enlarged with a future setData() call and it could be
+ // needed to construct the next frame (see comments below). Callers can
+ // always use ImageSource::clear(true, ...) to completely free the memory in
+ // this case.
+ clearBeforeFrame = std::min(clearBeforeFrame, m_frameBufferCache.size() - 1);
+ const Vector<RGBA32Buffer>::iterator end(m_frameBufferCache.begin() + clearBeforeFrame);
+ for (Vector<RGBA32Buffer>::iterator i(m_frameBufferCache.begin()); i != end; ++i) {
+ if (i->status() == RGBA32Buffer::FrameEmpty)
+ continue; // Nothing to do.
+
+ // The layout of frames is:
+ // [empty frames][complete frames][partial frame][empty frames]
+ // ...where each of these groups may be empty. We should not clear a
+ // partial frame since that's what's being decoded right now, and we
+ // also should not clear the last complete frame, since it may be needed
+ // when constructing the next frame. Note that "i + 1" is safe since
+ // i < end < m_frameBufferCache.end().
+ if ((i->status() == RGBA32Buffer::FramePartial) || ((i + 1)->status() != RGBA32Buffer::FrameComplete))
+ break;
+
+ i->clear();
+ }
+}
+
+// Feed data to the GIF reader.
+void GIFImageDecoder::decode(GIFQuery query, unsigned haltAtFrame) const
+{
+ if (m_failed)
+ return;
+
+ m_failed = !m_reader->decode(m_data.get(), query, haltAtFrame);
+
+ if (m_failed) {
+ delete m_reader;
+ m_reader = 0;
+ }
+}
+
+// Callbacks from the GIF reader.
+bool GIFImageDecoder::sizeNowAvailable(unsigned width, unsigned height)
+{
+ return setSize(width, height);
+}
+
+void GIFImageDecoder::decodingHalted(unsigned bytesLeft)
+{
+ m_reader->setReadOffset(m_data->size() - bytesLeft);
+}
+
+bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
+{
+ // Initialize the frame rect in our buffer.
+ IntRect frameRect(m_reader->frameXOffset(), m_reader->frameYOffset(),
+ m_reader->frameWidth(), m_reader->frameHeight());
+
+ // Make sure the frameRect doesn't extend past the bottom-right of the buffer.
+ 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);
+
+ if (frameIndex == 0) {
+ // This is the first frame, so we're not relying on any previous data.
+ if (!prepEmptyFrameBuffer(buffer)) {
+ buffer->setStatus(RGBA32Buffer::FrameComplete);
+ m_failed = true;
+ return false;
+ }
+ } else {
+ // The starting state for this frame depends on the previous frame's
+ // disposal method.
+ //
+ // Frames that use the DisposeOverwritePrevious method are effectively
+ // no-ops in terms of changing the starting state of a frame compared to
+ // the starting state of the previous frame, so skip over them. (If the
+ // 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)) {
+ prevBuffer = &m_frameBufferCache[--frameIndex];
+ prevMethod = prevBuffer->disposalMethod();
+ }
+
+ if ((prevMethod == RGBA32Buffer::DisposeNotSpecified) ||
+ (prevMethod == RGBA32Buffer::DisposeKeep)) {
+ // Preserve the last frame as the starting state for this frame.
+ buffer->copyBitmapData(*prevBuffer);
+ // This next line isn't currently necessary since the alpha state is
+ // currently carried along in the Skia bitmap data, but it's safe,
+ // future-proof, and parallel to the Cairo code.
+ buffer->setHasAlpha(prevBuffer->hasAlpha());
+ } else {
+ // We want to clear the previous frame to transparent, without
+ // affecting pixels in the image outside of the frame.
+ const IntRect& prevRect = prevBuffer->rect();
+ 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);
+ } else {
+ // Copy the whole previous buffer, then clear just its frame.
+ buffer->copyBitmapData(*prevBuffer);
+ // Unnecessary (but safe); see comments on the similar call above.
+ buffer->setHasAlpha(prevBuffer->hasAlpha());
+ SkBitmap& bitmap = buffer->bitmap();
+ for (int y = prevRect.y(); y < prevRect.bottom(); ++y) {
+ for (int x = prevRect.x(); x < prevRect.right(); ++x)
+ buffer->setRGBA(bitmap.getAddr32(x, y), 0, 0, 0, 0);
+ }
+ if ((prevRect.width() > 0) && (prevRect.height() > 0))
+ buffer->setHasAlpha(true);
+ }
+ }
+ }
+
+ // Update our status to be partially complete.
+ buffer->setStatus(RGBA32Buffer::FramePartial);
+
+ // Reset the alpha pixel tracker for this frame.
+ m_currentBufferSawAlpha = false;
+ return true;
+}
+
+bool GIFImageDecoder::prepEmptyFrameBuffer(RGBA32Buffer* buffer) const
+{
+ if (!buffer->setSize(size().width(), size().height()))
+ return false;
+ // This next line isn't currently necessary since Skia's eraseARGB() sets
+ // this for us, but we do it for similar reasons to the setHasAlpha() calls
+ // in initFrameBuffer() above.
+ buffer->setHasAlpha(true);
+ return true;
+}
+
+void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
+ unsigned char* rowBuffer, // Pointer to single scanline temporary buffer
+ unsigned char* rowEnd,
+ unsigned rowNumber, // The row index
+ unsigned repeatCount, // How many times to repeat the row
+ bool writeTransparentPixels)
+{
+ // Initialize the frame if necessary.
+ RGBA32Buffer& buffer = m_frameBufferCache[frameIndex];
+ if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex))
+ return;
+
+ // Do nothing for bogus data.
+ if (rowBuffer == 0 || static_cast<int>(m_reader->frameYOffset() + rowNumber) >= size().height())
+ return;
+
+ unsigned colorMapSize;
+ unsigned char* colorMap;
+ m_reader->getColorMap(colorMap, colorMapSize);
+ if (!colorMap)
+ return;
+
+ // The buffers that we draw are the entire image's width and height, so a final output frame is
+ // width * height RGBA32 values in size.
+ //
+ // A single GIF frame, however, can be smaller than the entire image, i.e., it can represent some sub-rectangle
+ // 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) * size().width() + m_reader->frameXOffset();
+ unsigned* dst = buffer.bitmap().getAddr32(0, 0) + dstPos;
+ 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;
+ unsigned red = colorMap[colorIndex];
+ unsigned green = colorMap[colorIndex + 1];
+ unsigned blue = colorMap[colorIndex + 2];
+ RGBA32Buffer::setRGBA(currDst, red, green, blue, 255);
+ } else {
+ m_currentBufferSawAlpha = true;
+ // We may or may not need to write transparent pixels to the buffer.
+ // If we're compositing against a previous image, it's wrong, and if
+ // we're writing atop a cleared, fully transparent buffer, it's
+ // unnecessary; but if we're decoding an interlaced gif and
+ // displaying it "Haeberli"-style, we must write these for passes
+ // beyond the first, or the initial passes will "show through" the
+ // later ones.
+ if (writeTransparentPixels)
+ RGBA32Buffer::setRGBA(currDst, 0, 0, 0, 0);
+ }
+ currDst++;
+ currentRowByte++;
+ }
+
+ if (repeatCount > 1) {
+ // Copy the row |repeatCount|-1 times.
+ unsigned num = currDst - dst;
+ unsigned data_size = num * sizeof(unsigned);
+ unsigned width = size().width();
+ unsigned* end = buffer.bitmap().getAddr32(0, 0) + 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, data_size);
+ currDst += width;
+ }
+ }
+}
+
+void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod)
+{
+ // Initialize the frame if necessary. Some GIFs insert do-nothing frames,
+ // in which case we never reach haveDecodedRow() before getting here.
+ RGBA32Buffer& buffer = m_frameBufferCache[frameIndex];
+ if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex))
+ return;
+
+ buffer.setStatus(RGBA32Buffer::FrameComplete);
+ buffer.setDuration(frameDuration);
+ buffer.setDisposalMethod(disposalMethod);
+
+ 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), size())))
+ buffer.setHasAlpha(false);
+ 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
+ // alpha, we're safe.
+ //
+ // First skip over prior DisposeOverwritePrevious frames (since they
+ // 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))
+ prevBuffer = &m_frameBufferCache[--frameIndex];
+
+ // Now, if we're at a DisposeNotSpecified or DisposeKeep frame, then
+ // we can say we have no alpha if that frame had no alpha. But
+ // since in initFrameBuffer() we already copied that frame's alpha
+ // state into the current frame's, we need do nothing at all here.
+ //
+ // 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()))
+ buffer.setHasAlpha(false);
+ }
+ }
+}
+
+void GIFImageDecoder::gifComplete()
+{
+ if (m_reader)
+ m_repetitionCount = m_reader->repetitionCount();
+ delete m_reader;
+ m_reader = 0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/skia/GIFImageDecoder.h b/WebCore/platform/image-decoders/skia/GIFImageDecoder.h
new file mode 100644
index 0000000..d234a76
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/GIFImageDecoder.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ *
+ * 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 GIFImageDecoder_h
+#define GIFImageDecoder_h
+
+#include "ImageDecoder.h"
+
+namespace WebCore {
+
+ class GIFImageDecoderPrivate;
+
+ // This class decodes the GIF image format.
+ class GIFImageDecoder : public ImageDecoder {
+ public:
+ GIFImageDecoder();
+ ~GIFImageDecoder();
+
+ virtual String filenameExtension() const { return "gif"; }
+
+ // 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;
+
+ // 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;
+
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+
+ virtual void clearFrameBufferCache(size_t clearBeforeFrame);
+
+ virtual unsigned frameDurationAtIndex(size_t index) { return 0; }
+
+ enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery };
+
+ void decode(GIFQuery, unsigned haltAtFrame) const;
+
+ // Callbacks from the GIF reader.
+ bool 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. Returns true on success. On failure,
+ // this will mark the image as failed.
+ bool initFrameBuffer(unsigned frameIndex);
+
+ // A helper for initFrameBuffer(), this sets the size of the buffer, and
+ // fills it with transparent pixels.
+ bool prepEmptyFrameBuffer(RGBA32Buffer*) const;
+
+ bool m_frameCountValid;
+ bool m_currentBufferSawAlpha;
+ mutable int m_repetitionCount;
+ mutable GIFImageDecoderPrivate* m_reader;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/image-decoders/skia/GIFImageReader.cpp b/WebCore/platform/image-decoders/skia/GIFImageReader.cpp
new file mode 100644
index 0000000..48df514
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/GIFImageReader.cpp
@@ -0,0 +1,951 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Chris Saari <saari@netscape.com>
+ * Apple Computer
+ * Google, Inc.
+ *
+ * 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 ***** */
+
+/*
+The Graphics Interchange Format(c) is the copyright property of CompuServe
+Incorporated. Only CompuServe Incorporated is authorized to define, redefine,
+enhance, alter, modify or change in any way the definition of the format.
+
+CompuServe Incorporated hereby grants a limited, non-exclusive, royalty-free
+license for the use of the Graphics Interchange Format(sm) in computer
+software; computer software utilizing GIF(sm) must acknowledge ownership of the
+Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in
+User and Technical Documentation. Computer software utilizing GIF, which is
+distributed or may be distributed without User or Technical Documentation must
+display to the screen or printer a message acknowledging ownership of the
+Graphics Interchange Format and the Service Mark by CompuServe Incorporated; in
+this case, the acknowledgement may be displayed in an opening screen or leading
+banner, or a closing screen or trailing banner. A message such as the following
+may be used:
+
+ "The Graphics Interchange Format(c) is the Copyright property of
+ CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ CompuServe Incorporated."
+
+For further information, please contact :
+
+ CompuServe Incorporated
+ Graphics Technology Department
+ 5000 Arlington Center Boulevard
+ Columbus, Ohio 43220
+ U. S. A.
+
+CompuServe Incorporated maintains a mailing list with all those individuals and
+organizations who wish to receive copies of this document when it is corrected
+or revised. This service is offered free of charge; please provide us with your
+mailing address.
+*/
+
+#include "config.h"
+#include "GIFImageReader.h"
+
+#include <string.h>
+#include "GIFImageDecoder.h"
+
+using WebCore::GIFImageDecoder;
+
+// Define the Mozilla macro setup so that we can leave the macros alone.
+#define PR_BEGIN_MACRO do {
+#define PR_END_MACRO } while (0)
+
+/*
+ * GETN(n, s) requests at least 'n' bytes available from 'q', at start of state 's'
+ *
+ * Note, the hold will never need to be bigger than 256 bytes to gather up in the hold,
+ * as each GIF block (except colormaps) can never be bigger than 256 bytes.
+ * Colormaps are directly copied in the resp. global_colormap or dynamically allocated local_colormap.
+ * So a fixed buffer in GIFImageReader is good enough.
+ * This buffer is only needed to copy left-over data from one GifWrite call to the next
+ */
+#define GETN(n,s) \
+ PR_BEGIN_MACRO \
+ bytes_to_consume = (n); \
+ state = (s); \
+ PR_END_MACRO
+
+/* Get a 16-bit value stored in little-endian format */
+#define GETINT16(p) ((p)[1]<<8|(p)[0])
+
+//******************************************************************************
+// Send the data to the display front-end.
+void GIFImageReader::output_row()
+{
+ GIFFrameReader* gs = frame_reader;
+
+ int drow_start, drow_end;
+
+ drow_start = drow_end = gs->irow;
+
+ /*
+ * Haeberli-inspired hack for interlaced GIFs: Replicate lines while
+ * displaying to diminish the "venetian-blind" effect as the image is
+ * loaded. Adjust pixel vertical positions to avoid the appearance of the
+ * image crawling up the screen as successive passes are drawn.
+ */
+ if (gs->progressive_display && gs->interlaced && gs->ipass < 4) {
+ unsigned row_dup = 0, row_shift = 0;
+
+ switch (gs->ipass) {
+ case 1:
+ row_dup = 7;
+ row_shift = 3;
+ break;
+ case 2:
+ row_dup = 3;
+ row_shift = 1;
+ break;
+ case 3:
+ row_dup = 1;
+ row_shift = 0;
+ break;
+ default:
+ break;
+ }
+
+ drow_start -= row_shift;
+ drow_end = drow_start + row_dup;
+
+ /* Extend if bottom edge isn't covered because of the shift upward. */
+ if (((gs->height - 1) - drow_end) <= row_shift)
+ drow_end = gs->height - 1;
+
+ /* Clamp first and last rows to upper and lower edge of image. */
+ if (drow_start < 0)
+ drow_start = 0;
+ if ((unsigned)drow_end >= gs->height)
+ drow_end = gs->height - 1;
+ }
+
+ /* Protect against too much image data */
+ if ((unsigned)drow_start >= gs->height)
+ return;
+
+ // CALLBACK: Let the client know we have decoded a row.
+ if (clientptr && frame_reader)
+ clientptr->haveDecodedRow(images_count - 1, frame_reader->rowbuf, frame_reader->rowend,
+ drow_start, drow_end - drow_start + 1,
+ gs->progressive_display && gs->interlaced && gs->ipass > 1);
+
+ gs->rowp = gs->rowbuf;
+
+ if (!gs->interlaced)
+ gs->irow++;
+ else {
+ do {
+ switch (gs->ipass)
+ {
+ case 1:
+ gs->irow += 8;
+ if (gs->irow >= gs->height) {
+ gs->ipass++;
+ gs->irow = 4;
+ }
+ break;
+
+ case 2:
+ gs->irow += 8;
+ if (gs->irow >= gs->height) {
+ gs->ipass++;
+ gs->irow = 2;
+ }
+ break;
+
+ case 3:
+ gs->irow += 4;
+ if (gs->irow >= gs->height) {
+ gs->ipass++;
+ gs->irow = 1;
+ }
+ break;
+
+ case 4:
+ gs->irow += 2;
+ if (gs->irow >= gs->height){
+ gs->ipass++;
+ gs->irow = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } while (gs->irow > (gs->height - 1));
+ }
+}
+
+//******************************************************************************
+/* Perform Lempel-Ziv-Welch decoding */
+int GIFImageReader::do_lzw(const unsigned char *q)
+{
+ GIFFrameReader* gs = frame_reader;
+ if (!gs)
+ return 0;
+
+ int code;
+ int incode;
+ const unsigned char *ch;
+
+ /* Copy all the decoder state variables into locals so the compiler
+ * won't worry about them being aliased. The locals will be homed
+ * back into the GIF decoder structure when we exit.
+ */
+ int avail = gs->avail;
+ int bits = gs->bits;
+ int cnt = count;
+ int codesize = gs->codesize;
+ int codemask = gs->codemask;
+ int oldcode = gs->oldcode;
+ int clear_code = gs->clear_code;
+ unsigned char firstchar = gs->firstchar;
+ int datum = gs->datum;
+
+ if (!gs->prefix) {
+ gs->prefix = new unsigned short[MAX_BITS];
+ memset(gs->prefix, 0, MAX_BITS * sizeof(short));
+ }
+
+ unsigned short *prefix = gs->prefix;
+ unsigned char *stackp = gs->stackp;
+ unsigned char *suffix = gs->suffix;
+ unsigned char *stack = gs->stack;
+ unsigned char *rowp = gs->rowp;
+ unsigned char *rowend = gs->rowend;
+ unsigned rows_remaining = gs->rows_remaining;
+
+ if (rowp == rowend)
+ return 0;
+
+#define OUTPUT_ROW \
+ PR_BEGIN_MACRO \
+ output_row(); \
+ rows_remaining--; \
+ rowp = frame_reader->rowp; \
+ if (!rows_remaining) \
+ goto END; \
+ PR_END_MACRO
+
+ for (ch = q; cnt-- > 0; ch++)
+ {
+ /* Feed the next byte into the decoder's 32-bit input buffer. */
+ datum += ((int) *ch) << bits;
+ bits += 8;
+
+ /* Check for underflow of decoder's 32-bit input buffer. */
+ while (bits >= codesize)
+ {
+ /* Get the leading variable-length symbol from the data stream */
+ code = datum & codemask;
+ datum >>= codesize;
+ bits -= codesize;
+
+ /* Reset the dictionary to its original state, if requested */
+ if (code == clear_code) {
+ codesize = gs->datasize + 1;
+ codemask = (1 << codesize) - 1;
+ avail = clear_code + 2;
+ oldcode = -1;
+ continue;
+ }
+
+ /* Check for explicit end-of-stream code */
+ if (code == (clear_code + 1)) {
+ /* end-of-stream should only appear after all image data */
+ if (rows_remaining != 0)
+ return -1;
+ return 0;
+ }
+
+ if (oldcode == -1) {
+ *rowp++ = suffix[code];
+ if (rowp == rowend)
+ OUTPUT_ROW;
+
+ firstchar = oldcode = code;
+ continue;
+ }
+
+ incode = code;
+ if (code >= avail) {
+ *stackp++ = firstchar;
+ code = oldcode;
+
+ if (stackp == stack + MAX_BITS)
+ return -1;
+ }
+
+ while (code >= clear_code)
+ {
+ if (code >= MAX_BITS || code == prefix[code])
+ return -1;
+
+ // Even though suffix[] only holds characters through suffix[avail - 1],
+ // allowing code >= avail here lets us be more tolerant of malformed
+ // data. As long as code < MAX_BITS, the only risk is a garbled image,
+ // which is no worse than refusing to display it.
+ *stackp++ = suffix[code];
+ code = prefix[code];
+
+ if (stackp == stack + MAX_BITS)
+ return -1;
+ }
+
+ *stackp++ = firstchar = suffix[code];
+
+ /* Define a new codeword in the dictionary. */
+ if (avail < 4096) {
+ prefix[avail] = oldcode;
+ suffix[avail] = firstchar;
+ avail++;
+
+ /* If we've used up all the codewords of a given length
+ * increase the length of codewords by one bit, but don't
+ * exceed the specified maximum codeword size of 12 bits.
+ */
+ if (((avail & codemask) == 0) && (avail < 4096)) {
+ codesize++;
+ codemask += avail;
+ }
+ }
+ oldcode = incode;
+
+ /* Copy the decoded data out to the scanline buffer. */
+ do {
+ *rowp++ = *--stackp;
+ if (rowp == rowend) {
+ OUTPUT_ROW;
+ }
+ } while (stackp > stack);
+ }
+ }
+
+ END:
+
+ /* Home the local copies of the GIF decoder state variables */
+ gs->avail = avail;
+ gs->bits = bits;
+ gs->codesize = codesize;
+ gs->codemask = codemask;
+ count = cnt;
+ gs->oldcode = oldcode;
+ gs->firstchar = firstchar;
+ gs->datum = datum;
+ gs->stackp = stackp;
+ gs->rowp = rowp;
+ gs->rows_remaining = rows_remaining;
+
+ return 0;
+}
+
+
+/******************************************************************************/
+/*
+ * process data arriving from the stream for the gif decoder
+ */
+
+bool GIFImageReader::read(const unsigned char *buf, unsigned len,
+ GIFImageDecoder::GIFQuery query, unsigned haltAtFrame)
+{
+ if (!len) {
+ // No new data has come in since the last call, just ignore this call.
+ return true;
+ }
+
+ const unsigned char *q = buf;
+
+ // Add what we have so far to the block
+ // If previous call to me left something in the hold first complete current block
+ // Or if we are filling the colormaps, first complete the colormap
+ unsigned char* p = 0;
+ if (state == gif_global_colormap)
+ p = global_colormap;
+ else if (state == gif_image_colormap)
+ p = frame_reader ? frame_reader->local_colormap : 0;
+ else if (bytes_in_hold)
+ p = hold;
+ else
+ p = 0;
+
+ if (p || (state == gif_global_colormap) || (state == gif_image_colormap)) {
+ // Add what we have sofar to the block
+ unsigned l = len < bytes_to_consume ? len : bytes_to_consume;
+ if (p)
+ memcpy(p + bytes_in_hold, buf, l);
+
+ if (l < bytes_to_consume) {
+ // Not enough in 'buf' to complete current block, get more
+ bytes_in_hold += l;
+ bytes_to_consume -= l;
+ if (clientptr)
+ clientptr->decodingHalted(0);
+ return true;
+ }
+ // Reset hold buffer count
+ bytes_in_hold = 0;
+ // Point 'q' to complete block in hold (or in colormap)
+ q = p;
+ }
+
+ // Invariant:
+ // 'q' is start of current to be processed block (hold, colormap or buf)
+ // 'bytes_to_consume' is number of bytes to consume from 'buf'
+ // 'buf' points to the bytes to be consumed from the input buffer
+ // 'len' is number of bytes left in input buffer from position 'buf'.
+ // At entrance of the for loop will 'buf' will be moved 'bytes_to_consume'
+ // to point to next buffer, 'len' is adjusted accordingly.
+ // So that next round in for loop, q gets pointed to the next buffer.
+
+ for (;len >= bytes_to_consume; q=buf) {
+ // Eat the current block from the buffer, q keeps pointed at current block
+ buf += bytes_to_consume;
+ len -= bytes_to_consume;
+
+ switch (state)
+ {
+ case gif_lzw:
+ if (do_lzw(q) < 0) {
+ state = gif_error;
+ break;
+ }
+ GETN(1, gif_sub_block);
+ break;
+
+ case gif_lzw_start:
+ {
+ /* Initialize LZW parser/decoder */
+ int datasize = *q;
+ // Since we use a codesize of 1 more than the datasize, we need to ensure
+ // that our datasize is strictly less than the MAX_LZW_BITS value (12).
+ // This sets the largest possible codemask correctly at 4095.
+ if (datasize >= MAX_LZW_BITS) {
+ state = gif_error;
+ break;
+ }
+ int clear_code = 1 << datasize;
+ if (clear_code >= MAX_BITS) {
+ state = gif_error;
+ break;
+ }
+
+ if (frame_reader) {
+ frame_reader->datasize = datasize;
+ frame_reader->clear_code = clear_code;
+ frame_reader->avail = frame_reader->clear_code + 2;
+ frame_reader->oldcode = -1;
+ frame_reader->codesize = frame_reader->datasize + 1;
+ frame_reader->codemask = (1 << frame_reader->codesize) - 1;
+
+ frame_reader->datum = frame_reader->bits = 0;
+
+ /* init the tables */
+ if (!frame_reader->suffix)
+ frame_reader->suffix = new unsigned char[MAX_BITS];
+ // Clearing the whole suffix table lets us be more tolerant of bad data.
+ memset(frame_reader->suffix, 0, MAX_BITS);
+ for (int i = 0; i < frame_reader->clear_code; i++)
+ frame_reader->suffix[i] = i;
+
+ if (!frame_reader->stack)
+ frame_reader->stack = new unsigned char[MAX_BITS];
+ frame_reader->stackp = frame_reader->stack;
+ }
+
+ GETN(1, gif_sub_block);
+ }
+ break;
+
+ /* All GIF files begin with "GIF87a" or "GIF89a" */
+ case gif_type:
+ {
+ if (!strncmp((char*)q, "GIF89a", 6)) {
+ version = 89;
+ } else if (!strncmp((char*)q, "GIF87a", 6)) {
+ version = 87;
+ } else {
+ state = gif_error;
+ break;
+ }
+ GETN(7, gif_global_header);
+ }
+ break;
+
+ case gif_global_header:
+ {
+ /* This is the height and width of the "screen" or
+ * frame into which images are rendered. The
+ * individual images can be smaller than the
+ * screen size and located with an origin anywhere
+ * within the screen.
+ */
+
+ screen_width = GETINT16(q);
+ screen_height = GETINT16(q + 2);
+
+ // CALLBACK: Inform the decoderplugin of our size.
+ if (clientptr) {
+ if (!clientptr->sizeNowAvailable(screen_width, screen_height))
+ return false;
+ }
+
+ screen_bgcolor = q[5];
+ global_colormap_size = 2<<(q[4]&0x07);
+
+ if ((q[4] & 0x80) && global_colormap_size > 0) { /* global map */
+ // Get the global colormap
+ const unsigned size = 3*global_colormap_size;
+
+ // Malloc the color map, but only if we're not just counting frames.
+ if (query != GIFImageDecoder::GIFFrameCountQuery)
+ global_colormap = new unsigned char[size];
+
+ if (len < size) {
+ // Use 'hold' pattern to get the global colormap
+ GETN(size, gif_global_colormap);
+ break;
+ }
+
+ // Copy everything and go directly to gif_image_start.
+ if (global_colormap)
+ memcpy(global_colormap, buf, size);
+ buf += size;
+ len -= size;
+ }
+
+ GETN(1, gif_image_start);
+
+ // q[6] = Pixel Aspect Ratio
+ // Not used
+ // float aspect = (float)((q[6] + 15) / 64.0);
+ }
+ break;
+
+ case gif_global_colormap:
+ // Everything is already copied into global_colormap
+ GETN(1, gif_image_start);
+ break;
+
+ case gif_image_start:
+ {
+ if (*q == ';') { /* terminator */
+ state = gif_done;
+ break;
+ }
+
+ if (*q == '!') { /* extension */
+ GETN(2, gif_extension);
+ break;
+ }
+
+ /* If we get anything other than ',' (image separator), '!'
+ * (extension), or ';' (trailer), there is extraneous data
+ * between blocks. The GIF87a spec tells us to keep reading
+ * until we find an image separator, but GIF89a says such
+ * a file is corrupt. We follow GIF89a and bail out. */
+ if (*q != ',') {
+ if (images_decoded > 0) {
+ /* The file is corrupt, but one or more images have
+ * been decoded correctly. In this case, we proceed
+ * as if the file were correctly terminated and set
+ * the state to gif_done, so the GIF will display.
+ */
+ state = gif_done;
+ } else {
+ /* No images decoded, there is nothing to display. */
+ state = gif_error;
+ }
+ break;
+ } else
+ GETN(9, gif_image_header);
+ }
+ break;
+
+ case gif_extension:
+ {
+ int len = count = q[1];
+ gstate es = gif_skip_block;
+
+ switch (*q)
+ {
+ case 0xf9:
+ es = gif_control_extension;
+ break;
+
+ case 0x01:
+ // ignoring plain text extension
+ break;
+
+ case 0xff:
+ es = gif_application_extension;
+ break;
+
+ case 0xfe:
+ es = gif_consume_comment;
+ break;
+ }
+
+ if (len)
+ GETN(len, es);
+ else
+ GETN(1, gif_image_start);
+ }
+ break;
+
+ case gif_consume_block:
+ if (!*q)
+ GETN(1, gif_image_start);
+ else
+ GETN(*q, gif_skip_block);
+ break;
+
+ case gif_skip_block:
+ GETN(1, gif_consume_block);
+ break;
+
+ case gif_control_extension:
+ {
+ if (query != GIFImageDecoder::GIFFrameCountQuery) {
+ if (!frame_reader)
+ frame_reader = new GIFFrameReader();
+ }
+
+ if (frame_reader) {
+ if (*q & 0x1) {
+ frame_reader->tpixel = q[3];
+ frame_reader->is_transparent = true;
+ } else {
+ frame_reader->is_transparent = false;
+ // ignoring gfx control extension
+ }
+ // NOTE: This relies on the values in the FrameDisposalMethod enum
+ // matching those in the GIF spec!
+ frame_reader->disposal_method = (WebCore::RGBA32Buffer::FrameDisposalMethod)(((*q) >> 2) & 0x7);
+ // Some specs say 3rd bit (value 4), other specs say value 3
+ // Let's choose 3 (the more popular)
+ if (frame_reader->disposal_method == 4)
+ frame_reader->disposal_method = WebCore::RGBA32Buffer::DisposeOverwritePrevious;
+ frame_reader->delay_time = GETINT16(q + 1) * 10;
+ }
+ GETN(1, gif_consume_block);
+ }
+ break;
+
+ case gif_comment_extension:
+ {
+ if (*q)
+ GETN(*q, gif_consume_comment);
+ else
+ GETN(1, gif_image_start);
+ }
+ break;
+
+ case gif_consume_comment:
+ GETN(1, gif_comment_extension);
+ break;
+
+ case gif_application_extension:
+ /* Check for netscape application extension */
+ if (!strncmp((char*)q, "NETSCAPE2.0", 11) ||
+ !strncmp((char*)q, "ANIMEXTS1.0", 11))
+ GETN(1, gif_netscape_extension_block);
+ else
+ GETN(1, gif_consume_block);
+ break;
+
+ /* Netscape-specific GIF extension: animation looping */
+ case gif_netscape_extension_block:
+ if (*q)
+ GETN(*q, gif_consume_netscape_extension);
+ else
+ GETN(1, gif_image_start);
+ break;
+
+ /* Parse netscape-specific application extensions */
+ case gif_consume_netscape_extension:
+ {
+ int netscape_extension = q[0] & 7;
+
+ /* Loop entire animation specified # of times. Only read the
+ loop count during the first iteration. */
+ if (netscape_extension == 1) {
+ loop_count = GETINT16(q + 1);
+
+ GETN(1, gif_netscape_extension_block);
+ }
+ /* Wait for specified # of bytes to enter buffer */
+ else if (netscape_extension == 2) {
+ // Don't do this, this extension doesn't exist (isn't used at all)
+ // and doesn't do anything, as our streaming/buffering takes care of it all...
+ // See: http://semmix.pl/color/exgraf/eeg24.htm
+ GETN(1, gif_netscape_extension_block);
+ } else
+ state = gif_error; // 0,3-7 are yet to be defined netscape
+ // extension codes
+
+ break;
+ }
+
+ case gif_image_header:
+ {
+ unsigned height, width, x_offset, y_offset;
+
+ /* Get image offsets, with respect to the screen origin */
+ x_offset = GETINT16(q);
+ y_offset = GETINT16(q + 2);
+
+ /* Get image width and height. */
+ width = GETINT16(q + 4);
+ height = GETINT16(q + 6);
+
+ /* Work around broken GIF files where the logical screen
+ * size has weird width or height. We assume that GIF87a
+ * files don't contain animations.
+ */
+ if ((images_decoded == 0) &&
+ ((screen_height < height) || (screen_width < width) ||
+ (version == 87)))
+ {
+ screen_height = height;
+ screen_width = width;
+ x_offset = 0;
+ y_offset = 0;
+
+ // CALLBACK: Inform the decoderplugin of our size.
+ if (clientptr)
+ clientptr->sizeNowAvailable(screen_width, screen_height);
+ }
+
+ /* Work around more broken GIF files that have zero image
+ width or height */
+ if (!height || !width) {
+ height = screen_height;
+ width = screen_width;
+ if (!height || !width) {
+ state = gif_error;
+ break;
+ }
+ }
+
+ if (query == GIFImageDecoder::GIFSizeQuery || haltAtFrame == images_decoded) {
+ // The decoder needs to stop. Hand back the number of bytes we consumed from
+ // buffer minus 9 (the amount we consumed to read the header).
+ if (clientptr)
+ clientptr->decodingHalted(len + 9);
+ GETN(9, gif_image_header);
+ return true;
+ }
+
+ images_count = images_decoded + 1;
+
+ if (query == GIFImageDecoder::GIFFullQuery && !frame_reader)
+ frame_reader = new GIFFrameReader();
+
+ if (frame_reader) {
+ frame_reader->x_offset = x_offset;
+ frame_reader->y_offset = y_offset;
+ frame_reader->height = height;
+ frame_reader->width = width;
+
+ /* This case will never be taken if this is the first image */
+ /* being decoded. If any of the later images are larger */
+ /* than the screen size, we need to reallocate buffers. */
+ if (screen_width < width) {
+ /* XXX Deviant! */
+
+ delete []frame_reader->rowbuf;
+ screen_width = width;
+ frame_reader->rowbuf = new unsigned char[screen_width];
+ } else if (!frame_reader->rowbuf) {
+ frame_reader->rowbuf = new unsigned char[screen_width];
+ }
+
+ if (!frame_reader->rowbuf) {
+ state = gif_oom;
+ break;
+ }
+ if (screen_height < height)
+ screen_height = height;
+
+ if (q[8] & 0x40) {
+ frame_reader->interlaced = true;
+ frame_reader->ipass = 1;
+ } else {
+ frame_reader->interlaced = false;
+ frame_reader->ipass = 0;
+ }
+
+ if (images_decoded == 0) {
+ frame_reader->progressive_display = true;
+ } else {
+ /* Overlaying interlaced, transparent GIFs over
+ existing image data using the Haeberli display hack
+ requires saving the underlying image in order to
+ avoid jaggies at the transparency edges. We are
+ unprepared to deal with that, so don't display such
+ images progressively */
+ frame_reader->progressive_display = false;
+ }
+
+ /* Clear state from last image */
+ frame_reader->irow = 0;
+ frame_reader->rows_remaining = frame_reader->height;
+ frame_reader->rowend = frame_reader->rowbuf + frame_reader->width;
+ frame_reader->rowp = frame_reader->rowbuf;
+
+ /* bits per pixel is q[8]&0x07 */
+ }
+
+ if (q[8] & 0x80) /* has a local colormap? */
+ {
+ int num_colors = 2 << (q[8] & 0x7);
+ const unsigned size = 3*num_colors;
+ unsigned char *map = frame_reader ? frame_reader->local_colormap : 0;
+ if (frame_reader && (!map || (num_colors > frame_reader->local_colormap_size))) {
+ delete []map;
+ map = new unsigned char[size];
+ if (!map) {
+ state = gif_oom;
+ break;
+ }
+ }
+
+ /* Switch to the new local palette after it loads */
+ if (frame_reader) {
+ frame_reader->local_colormap = map;
+ frame_reader->local_colormap_size = num_colors;
+ frame_reader->is_local_colormap_defined = true;
+ }
+
+ if (len < size) {
+ // Use 'hold' pattern to get the image colormap
+ GETN(size, gif_image_colormap);
+ break;
+ }
+ // Copy everything and directly go to gif_lzw_start
+ if (frame_reader)
+ memcpy(frame_reader->local_colormap, buf, size);
+ buf += size;
+ len -= size;
+ } else if (frame_reader) {
+ /* Switch back to the global palette */
+ frame_reader->is_local_colormap_defined = false;
+ }
+ GETN(1, gif_lzw_start);
+ }
+ break;
+
+ case gif_image_colormap:
+ // Everything is already copied into local_colormap
+ GETN(1, gif_lzw_start);
+ break;
+
+ case gif_sub_block:
+ {
+ if ((count = *q) != 0)
+ /* Still working on the same image: Process next LZW data block */
+ {
+ /* Make sure there are still rows left. If the GIF data */
+ /* is corrupt, we may not get an explicit terminator. */
+ if (frame_reader && frame_reader->rows_remaining == 0) {
+ /* This is an illegal GIF, but we remain tolerant. */
+ GETN(1, gif_sub_block);
+ }
+ GETN(count, gif_lzw);
+ }
+ else
+ /* See if there are any more images in this sequence. */
+ {
+ images_decoded++;
+
+ // CALLBACK: The frame is now complete.
+ if (clientptr && frame_reader)
+ clientptr->frameComplete(images_decoded - 1, frame_reader->delay_time,
+ frame_reader->disposal_method);
+
+ /* Clear state from this image */
+ if (frame_reader) {
+ frame_reader->is_local_colormap_defined = false;
+ frame_reader->is_transparent = false;
+ }
+
+ GETN(1, gif_image_start);
+ }
+ }
+ break;
+
+ case gif_done:
+ // When the GIF is done, we can stop.
+ if (clientptr)
+ clientptr->gifComplete();
+ return true;
+
+ // Handle out of memory errors
+ case gif_oom:
+ return false;
+
+ // Handle general errors
+ case gif_error:
+ // nsGIFDecoder2::EndGIF(gs->clientptr, gs->loop_count);
+ return false;
+
+ // We shouldn't ever get here.
+ default:
+ break;
+ }
+ }
+
+ // Copy the leftover into gs->hold
+ bytes_in_hold = len;
+ if (len) {
+ // Add what we have sofar to the block
+ unsigned char* p;
+ if (state == gif_global_colormap)
+ p = global_colormap;
+ else if (state == gif_image_colormap)
+ p = frame_reader ? frame_reader->local_colormap : 0;
+ else
+ p = hold;
+ if (p)
+ memcpy(p, buf, len);
+ bytes_to_consume -= len;
+ }
+
+ if (clientptr)
+ clientptr->decodingHalted(0);
+ return true;
+}
diff --git a/WebCore/platform/image-decoders/skia/GIFImageReader.h b/WebCore/platform/image-decoders/skia/GIFImageReader.h
new file mode 100644
index 0000000..aa3d717
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/GIFImageReader.h
@@ -0,0 +1,215 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 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.
+#include "GIFImageDecoder.h"
+
+#define MAX_LZW_BITS 12
+#define MAX_BITS 4097 /* 2^MAX_LZW_BITS+1 */
+#define MAX_COLORS 256
+#define MAX_HOLD_SIZE 256
+
+const int cLoopCountNotSeen = -2;
+
+/* gif2.h
+ The interface for the GIF87/89a decoder.
+*/
+// List of possible parsing states
+typedef enum {
+ gif_type,
+ gif_global_header,
+ gif_global_colormap,
+ gif_image_start,
+ gif_image_header,
+ gif_image_colormap,
+ gif_image_body,
+ gif_lzw_start,
+ gif_lzw,
+ gif_sub_block,
+ gif_extension,
+ gif_control_extension,
+ gif_consume_block,
+ gif_skip_block,
+ gif_done,
+ gif_oom,
+ gif_error,
+ gif_comment_extension,
+ gif_application_extension,
+ gif_netscape_extension_block,
+ gif_consume_netscape_extension,
+ gif_consume_comment
+} gstate;
+
+struct GIFFrameReader {
+ /* LZW decoder state machine */
+ unsigned char *stackp; /* Current stack pointer */
+ int datasize;
+ int codesize;
+ int codemask;
+ int clear_code; /* Codeword used to trigger dictionary reset */
+ int avail; /* Index of next available slot in dictionary */
+ int oldcode;
+ unsigned char firstchar;
+ int bits; /* Number of unread bits in "datum" */
+ int datum; /* 32-bit input buffer */
+
+ /* Output state machine */
+ int ipass; /* Interlace pass; Ranges 1-4 if interlaced. */
+ unsigned int rows_remaining; /* Rows remaining to be output */
+ unsigned int irow; /* Current output row, starting at zero */
+ unsigned char *rowbuf; /* Single scanline temporary buffer */
+ unsigned char *rowend; /* Pointer to end of rowbuf */
+ unsigned char *rowp; /* Current output pointer */
+
+ /* Parameters for image frame currently being decoded */
+ unsigned int x_offset, y_offset; /* With respect to "screen" origin */
+ unsigned int height, width;
+ int tpixel; /* Index of transparent pixel */
+ WebCore::RGBA32Buffer::FrameDisposalMethod disposal_method; /* Restore to background, leave in place, etc.*/
+ unsigned char *local_colormap; /* Per-image colormap */
+ int local_colormap_size; /* Size of local colormap array. */
+
+ bool is_local_colormap_defined : 1;
+ bool progressive_display : 1; /* If TRUE, do Haeberli interlace hack */
+ bool interlaced : 1; /* TRUE, if scanlines arrive interlaced order */
+ bool is_transparent : 1; /* TRUE, if tpixel is valid */
+
+ unsigned delay_time; /* Display time, in milliseconds,
+ for this image in a multi-image GIF */
+
+
+ unsigned short* prefix; /* LZW decoding tables */
+ unsigned char* suffix; /* LZW decoding tables */
+ unsigned char* stack; /* Base of LZW decoder stack */
+
+
+ GIFFrameReader() {
+ stackp = 0;
+ datasize = codesize = codemask = clear_code = avail = oldcode = 0;
+ firstchar = 0;
+ bits = datum = 0;
+ ipass = 0;
+ rows_remaining = irow = 0;
+ rowbuf = rowend = rowp = 0;
+
+ x_offset = y_offset = width = height = 0;
+ tpixel = 0;
+ disposal_method = WebCore::RGBA32Buffer::DisposeNotSpecified;
+
+ local_colormap = 0;
+ local_colormap_size = 0;
+ is_local_colormap_defined = progressive_display = is_transparent = interlaced = false;
+
+ delay_time = 0;
+
+ prefix = 0;
+ suffix = stack = 0;
+ }
+
+ ~GIFFrameReader() {
+ delete []rowbuf;
+ delete []local_colormap;
+ delete []prefix;
+ delete []suffix;
+ delete []stack;
+ }
+};
+
+struct GIFImageReader {
+ WebCore::GIFImageDecoder* clientptr;
+ /* Parsing state machine */
+ gstate state; /* Current decoder master state */
+ unsigned bytes_to_consume; /* Number of bytes to accumulate */
+ unsigned bytes_in_hold; /* bytes accumulated so far*/
+ unsigned char hold[MAX_HOLD_SIZE]; /* Accumulation buffer */
+ unsigned char* global_colormap; /* (3* MAX_COLORS in size) Default colormap if local not supplied, 3 bytes for each color */
+
+ /* Global (multi-image) state */
+ int screen_bgcolor; /* Logical screen background color */
+ 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. */
+
+ // Not really global, but convenient to locate here.
+ int count; /* Remaining # bytes in sub-block */
+
+ GIFFrameReader* frame_reader;
+
+ GIFImageReader(WebCore::GIFImageDecoder* client = 0) {
+ clientptr = client;
+ state = gif_type;
+ bytes_to_consume = 6;
+ bytes_in_hold = 0;
+ frame_reader = 0;
+ global_colormap = 0;
+
+ screen_bgcolor = version = 0;
+ screen_width = screen_height = 0;
+ global_colormap_size = images_decoded = images_count = 0;
+ loop_count = cLoopCountNotSeen;
+ count = 0;
+ }
+
+ ~GIFImageReader() {
+ close();
+ }
+
+ void close() {
+ delete []global_colormap;
+ global_colormap = 0;
+ delete frame_reader;
+ frame_reader = 0;
+ }
+
+ bool read(const unsigned char * buf, unsigned int numbytes,
+ WebCore::GIFImageDecoder::GIFQuery query = WebCore::GIFImageDecoder::GIFFullQuery, unsigned haltAtFrame = -1);
+
+private:
+ void output_row();
+ int do_lzw(const unsigned char *q);
+};
+
+#endif
diff --git a/WebCore/platform/image-decoders/skia/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/skia/ICOImageDecoder.cpp
new file mode 100644
index 0000000..c340896
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/ICOImageDecoder.cpp
@@ -0,0 +1,230 @@
+/*
+ * 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 "config.h"
+#include "ICOImageDecoder.h"
+
+namespace WebCore {
+
+// Number of bits in .ICO/.CUR used to store the directory and its entries,
+// respectively (doesn't match sizeof values for member structs since we omit
+// some fields).
+static const size_t sizeOfDirectory = 6;
+static const size_t sizeOfDirEntry = 16;
+
+void ICOImageDecoder::decodeImage(SharedBuffer* data)
+{
+ // Read and process directory.
+ if ((m_decodedOffset < sizeOfDirectory) && !processDirectory(data))
+ return;
+
+ // Read and process directory entries.
+ if ((m_decodedOffset < (sizeOfDirectory + (m_directory.idCount * sizeOfDirEntry)))
+ && !processDirectoryEntries(data))
+ return;
+
+ // Check if this entry is a PNG; we need 4 bytes to check the magic number.
+ if (m_imageType == Unknown) {
+ if (data->size() < (m_dirEntry.dwImageOffset + 4))
+ return;
+ m_imageType =
+ strncmp(&data->data()[m_dirEntry.dwImageOffset], "\x89PNG", 4) ?
+ BMP : PNG;
+ }
+
+ // Decode selected entry.
+ if (m_imageType == PNG)
+ decodePNG(data);
+ else {
+ // Note that we don't try to limit the bytes we give to the decoder to
+ // just the size specified in the icon directory. If the size given in
+ // the directory is insufficient to decode the whole image, the image is
+ // corrupt anyway, so whatever we do may be wrong. The easiest choice
+ // (which we do here) is to simply aggressively consume bytes until we
+ // run out of bytes, finish decoding, or hit a sequence that makes the
+ // decoder fail.
+ decodeBMP(data);
+ }
+}
+
+RGBA32Buffer* ICOImageDecoder::frameBufferAtIndex(size_t index)
+{
+ return (m_imageType == PNG) ? m_pngDecoder.frameBufferAtIndex(0) :
+ BMPImageReader::frameBufferAtIndex(0);
+}
+
+bool ICOImageDecoder::isSizeAvailable() const
+{
+ return (m_imageType == PNG) ? m_pngDecoder.isSizeAvailable() :
+ BMPImageReader::isSizeAvailable();
+}
+
+IntSize ICOImageDecoder::size() const
+{
+ return (m_imageType == PNG) ? m_pngDecoder.size() : BMPImageReader::size();
+}
+
+bool ICOImageDecoder::processDirectory(SharedBuffer* data)
+{
+ // Read directory.
+ ASSERT(!m_decodedOffset);
+ if (data->size() < sizeOfDirectory)
+ return false;
+ const uint16_t fileType = readUint16(data, 2);
+ m_directory.idCount = readUint16(data, 4);
+ m_decodedOffset = sizeOfDirectory;
+
+ // See if this is an icon filetype we understand, and make sure we have at
+ // least one entry in the directory.
+ enum {
+ ICON = 1,
+ CURSOR = 2,
+ };
+ if (((fileType != ICON) && (fileType != CURSOR)) ||
+ (m_directory.idCount == 0))
+ m_failed = true;
+
+ return !m_failed;
+}
+
+bool ICOImageDecoder::processDirectoryEntries(SharedBuffer* data)
+{
+ // Read directory entries.
+ ASSERT(m_decodedOffset == sizeOfDirectory);
+ if ((m_decodedOffset > data->size()) || (data->size() - m_decodedOffset) <
+ (m_directory.idCount * sizeOfDirEntry))
+ return false;
+ for (int i = 0; i < m_directory.idCount; ++i) {
+ const IconDirectoryEntry dirEntry = readDirectoryEntry(data);
+ if ((i == 0) || isBetterEntry(dirEntry))
+ m_dirEntry = dirEntry;
+ }
+
+ // Make sure the specified image offset is past the end of the directory
+ // entries, and that the offset isn't so large that it overflows when we add
+ // 4 bytes to it (which we do in decodeImage() while ensuring it's safe to
+ // examine the first 4 bytes of the image data).
+ if ((m_dirEntry.dwImageOffset < m_decodedOffset) ||
+ ((m_dirEntry.dwImageOffset + 4) < m_dirEntry.dwImageOffset)) {
+ m_failed = true;
+ return false;
+ }
+
+ // Ready to decode the image at the specified offset.
+ m_decodedOffset = m_headerOffset = m_dirEntry.dwImageOffset;
+ return true;
+}
+
+ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry(
+ SharedBuffer* data)
+{
+ // Read icon data.
+ IconDirectoryEntry entry;
+ entry.bWidth = static_cast<uint8_t>(data->data()[m_decodedOffset]);
+ if (entry.bWidth == 0)
+ entry.bWidth = 256;
+ entry.bHeight = static_cast<uint8_t>(data->data()[m_decodedOffset + 1]);
+ if (entry.bHeight == 0)
+ entry.bHeight = 256;
+ entry.wBitCount = readUint16(data, 6);
+ entry.dwImageOffset = readUint32(data, 12);
+
+ // Some icons don't have a bit depth, only a color count. Convert the
+ // color count to the minimum necessary bit depth. It doesn't matter if
+ // this isn't quite what the bitmap info header says later, as we only use
+ // this value to determine which icon entry is best.
+ if (!entry.wBitCount) {
+ uint8_t colorCount = data->data()[m_decodedOffset + 2];
+ if (colorCount) {
+ for (--colorCount; colorCount; colorCount >>= 1)
+ ++entry.wBitCount;
+ }
+ }
+
+ m_decodedOffset += sizeOfDirEntry;
+ return entry;
+}
+
+bool ICOImageDecoder::isBetterEntry(const IconDirectoryEntry& entry) const
+{
+ const IntSize entrySize(entry.bWidth, entry.bHeight);
+ const IntSize dirEntrySize(m_dirEntry.bWidth, m_dirEntry.bHeight);
+ const int entryArea = entry.bWidth * entry.bHeight;
+ const int dirEntryArea = m_dirEntry.bWidth * m_dirEntry.bHeight;
+
+ if ((entrySize != dirEntrySize) && !m_preferredIconSize.isEmpty()) {
+ // An icon of exactly the preferred size is best.
+ if (entrySize == m_preferredIconSize)
+ return true;
+ if (dirEntrySize == m_preferredIconSize)
+ return false;
+
+ // The icon closest to the preferred area without being smaller is
+ // better.
+ if (entryArea != dirEntryArea) {
+ return (entryArea < dirEntryArea)
+ && (entryArea >= (m_preferredIconSize.width() * m_preferredIconSize.height()));
+ }
+ }
+
+ // Larger icons are better.
+ if (entryArea != dirEntryArea)
+ return (entryArea > dirEntryArea);
+
+ // Higher bit-depth icons are better.
+ return (entry.wBitCount > m_dirEntry.wBitCount);
+}
+
+void ICOImageDecoder::decodePNG(SharedBuffer* data)
+{
+ // Copy out PNG data to a separate vector and instantiate PNG decoder.
+ // It would be nice to save this copy, if I could figure out how to just
+ // offset the perceived start of |data| by |m_dirEntry.dwImageOffset| when
+ // passing it to setData()...
+ RefPtr<SharedBuffer> pngData(
+ SharedBuffer::create(&data->data()[m_dirEntry.dwImageOffset],
+ data->size() - m_dirEntry.dwImageOffset));
+ m_pngDecoder.setData(pngData.get(), true);
+
+ // Decode PNG as a side effect of asking for the frame. Strangely, it's
+ // seemingly unsafe to call decode() or isSizeAvailable() before calling
+ // this, as this is the only function that enlarges the framebuffer to
+ // nonzero size, and before this happens any decoded image data is silently
+ // thrown away and never decoded again (!).
+ m_pngDecoder.frameBufferAtIndex(0);
+ m_failed = m_pngDecoder.failed();
+
+ // Sanity-check that the size is what we expected.
+ if (isSizeAvailable() && ((size().width() != m_dirEntry.bWidth) ||
+ (size().height() != m_dirEntry.bHeight)))
+ m_failed = true;
+}
+
+}
diff --git a/WebCore/platform/image-decoders/skia/ICOImageDecoder.h b/WebCore/platform/image-decoders/skia/ICOImageDecoder.h
new file mode 100644
index 0000000..f0e1acc
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/ICOImageDecoder.h
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#ifndef ICOImageDecoder_h
+#define ICOImageDecoder_h
+
+#include "BMPImageReader.h"
+#include "PNGImageDecoder.h"
+
+namespace WebCore {
+
+ // This class decodes the ICO and CUR image formats.
+ class ICOImageDecoder : public BMPImageReader {
+ public:
+ // See comments on |m_preferredIconSize| below.
+ ICOImageDecoder(const IntSize& preferredIconSize)
+ : m_preferredIconSize(preferredIconSize)
+ , m_imageType(Unknown)
+ {
+ m_andMaskState = NotYetDecoded;
+ }
+
+ virtual String filenameExtension() const { return "ico"; }
+
+ // BMPImageReader
+ virtual void decodeImage(SharedBuffer* data);
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+
+ // ImageDecoder
+ virtual bool isSizeAvailable() const;
+ virtual IntSize size() const;
+
+ private:
+ enum ImageType {
+ Unknown,
+ BMP,
+ PNG,
+ };
+
+ // These are based on the Windows ICONDIR and ICONDIRENTRY structs, but
+ // with unnecessary entries removed.
+ struct IconDirectory {
+ uint16_t idCount;
+ };
+ struct IconDirectoryEntry {
+ uint16_t bWidth; // 16 bits so we can represent 256 as 256, not 0
+ uint16_t bHeight; // "
+ uint16_t wBitCount;
+ uint32_t dwImageOffset;
+ };
+
+ // Processes the ICONDIR at the beginning of the data. Returns true if the
+ // directory could be decoded.
+ bool processDirectory(SharedBuffer*);
+
+ // Processes the ICONDIRENTRY records after the directory. Keeps the
+ // "best" entry as the one we'll decode. Returns true if the entries could
+ // be decoded.
+ bool processDirectoryEntries(SharedBuffer*);
+
+ // Reads and returns a directory entry from the current offset into |data|.
+ IconDirectoryEntry readDirectoryEntry(SharedBuffer*);
+
+ // Returns true if |entry| is a preferable icon entry to m_dirEntry.
+ // Larger sizes, or greater bitdepths at the same size, are preferable.
+ bool isBetterEntry(const IconDirectoryEntry&) const;
+
+ // Called when the image to be decoded is a PNG rather than a BMP.
+ // Instantiates a PNGImageDecoder, decodes the image, and copies the
+ // results locally.
+ void decodePNG(SharedBuffer*);
+
+ // The entry size we should prefer. If this is empty, we choose the
+ // largest available size. If no entries of the desired size are
+ // available, we pick the next larger size.
+ IntSize m_preferredIconSize;
+
+ // The headers for the ICO.
+ IconDirectory m_directory;
+ IconDirectoryEntry m_dirEntry;
+
+ // The PNG decoder, if we need to use one.
+ PNGImageDecoder m_pngDecoder;
+
+ // What kind of image data is stored at the entry we're decoding.
+ ImageType m_imageType;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/image-decoders/skia/ImageDecoder.h b/WebCore/platform/image-decoders/skia/ImageDecoder.h
new file mode 100644
index 0000000..9988a3e
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/ImageDecoder.h
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ *
+ * 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 ImageDecoder_h
+#define ImageDecoder_h
+
+#include "IntRect.h"
+#include "ImageSource.h"
+#include "NativeImageSkia.h"
+#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>
+
+#include "SkBitmap.h"
+
+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.
+ 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_status(FrameEmpty)
+ , 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);
+ }
+
+ ~RGBA32Buffer()
+ {
+ }
+
+ // Initialize with another buffer. This function doesn't create a new copy
+ // of the image data, it only increases the refcount of the existing bitmap.
+ //
+ // Normal callers should not generally be using this function. If you want
+ // to create a copy on which you can modify the image data independently,
+ // use copyBitmapData() instead.
+ RGBA32Buffer& operator=(const RGBA32Buffer& other)
+ {
+ if (this == &other)
+ return *this;
+
+ m_bitmapRef = other.m_bitmapRef;
+ setRect(other.rect());
+ setStatus(other.status());
+ setDuration(other.duration());
+ setDisposalMethod(other.disposalMethod());
+ setHasAlpha(other.hasAlpha());
+ return *this;
+ }
+
+ void clear()
+ {
+ m_bitmapRef = RefCountedNativeImageSkia::create();
+ m_rect = IntRect();
+ m_status = FrameEmpty;
+ m_duration = 0;
+ m_disposalMethod = DisposeNotSpecified;
+ }
+
+ // This function creates a new copy of the image data in |other|, so the
+ // two images can be modified independently.
+ void copyBitmapData(const RGBA32Buffer& other)
+ {
+ 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());
+ }
+ }
+
+ NativeImageSkia& bitmap() { return m_bitmapRef->bitmap(); }
+ const NativeImageSkia& bitmap() const { return m_bitmapRef->bitmap(); }
+
+ // Must be called before any pixels are written. Will return true on
+ // success, false if the memory allocation fails.
+ bool setSize(int width, int height)
+ {
+ // 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())
+ return false; // Allocation failure, maybe the bitmap was too big.
+
+ // Clear the image.
+ bmp.eraseARGB(0, 0, 0, 0);
+
+ return true;
+ }
+
+ int width() const { return bitmap().width(); }
+ int height() const { return 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(); }
+
+ 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_status = s;
+ }
+ void setDuration(unsigned duration) { m_duration = duration; }
+ void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
+ void setHasAlpha(bool alpha) { bitmap().setIsOpaque(!alpha); }
+
+ static void setRGBA(uint32_t* dest, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+ {
+ // We store this data pre-multiplied.
+ if (a == 0)
+ *dest = 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);
+ }
+ *dest = (a << 24 | r << 16 | g << 8 | b);
+ }
+ }
+
+ 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);
+ }
+
+ private:
+ RefPtr<RefCountedNativeImageSkia> m_bitmapRef;
+ IntRect m_rect; // The rect of the original specified frame within the overall buffer.
+ // This will always just be the entire buffer except for GIF frames
+ // whose original rect was smaller than the overall image size.
+ FrameStatus m_status; // Whether or not this frame is completely finished decoding.
+ unsigned m_duration; // The animation delay.
+ FrameDisposalMethod m_disposalMethod; // What to do with this frame's data when initializing the next frame.
+ };
+
+ // 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_failed(false), m_sizeAvailable(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. This default
+ // implementation just returns true if the size has been set and we have not
+ // seen a failure. Decoders may want to override this to lazily decode
+ // enough of the image to get the size.
+ virtual bool isSizeAvailable() const
+ {
+ return !m_failed && m_sizeAvailable;
+ }
+
+ // Requests the size.
+ virtual IntSize size() const
+ {
+ // Requesting the size of an invalid bitmap is meaningless.
+ ASSERT(!m_failed);
+ 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:
+ // Called by the image decoders to set their decoded size, this also check
+ // the size for validity. It will return true if the size was set, or false
+ // if there is an error. On error, the m_failed flag will be set and the
+ // caller should immediately stop decoding.
+ bool setSize(unsigned width, unsigned height)
+ {
+ if (isOverSize(width, height)) {
+ m_failed = true;
+ return false;
+ }
+ m_size = IntSize(width, height);
+ m_sizeAvailable = true;
+ return true;
+ }
+
+ RefPtr<SharedBuffer> m_data; // The encoded data.
+ Vector<RGBA32Buffer> m_frameBufferCache;
+ mutable bool m_failed;
+
+ private:
+ // This function allows us to make sure the image is not too large. Very
+ // large images, even if the allocation succeeds, can take a very long time
+ // to process, giving the appearance of a DoS.
+ //
+ // WebKit also seems to like to ask for the size before data is available
+ // and in some cases when the failed flag is set. Some of these code paths
+ // such as BitmapImage::resetAnimation then compute the size of the image
+ // based on the width and height. Because of this, our total computed image
+ // byte size must never overflow an int.
+ static bool isOverSize(unsigned width, unsigned height)
+ {
+ unsigned long long total_size = static_cast<unsigned long long>(width)
+ * static_cast<unsigned long long>(height);
+ if (total_size > 32 * 1024 * 1024) // 32M = 128MB memory total (32 bpp).
+ return true;
+ return false;
+ }
+
+ IntSize m_size;
+ bool m_sizeAvailable;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp
new file mode 100644
index 0000000..98f622e
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp
@@ -0,0 +1,512 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ *
+ * Portions are Copyright (C) 2001-6 mozilla.org
+ *
+ * Other contributors:
+ * Stuart Parmenter <stuart@mozilla.com>
+ *
+ * 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.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+#include "JPEGImageDecoder.h"
+#include <assert.h>
+
+extern "C" {
+#include "jpeglib.h"
+}
+
+#include <setjmp.h>
+
+namespace WebCore {
+
+struct decoder_error_mgr {
+ struct jpeg_error_mgr pub; /* "public" fields for IJG library*/
+ jmp_buf setjmp_buffer; /* For handling catastropic errors */
+};
+
+enum jstate {
+ JPEG_HEADER, /* Reading JFIF headers */
+ JPEG_START_DECOMPRESS,
+ JPEG_DECOMPRESS_PROGRESSIVE, /* Output progressive pixels */
+ JPEG_DECOMPRESS_SEQUENTIAL, /* Output sequential pixels */
+ JPEG_DONE,
+ JPEG_SINK_NON_JPEG_TRAILER, /* Some image files have a */
+ /* non-JPEG trailer */
+ JPEG_ERROR
+};
+
+void init_source(j_decompress_ptr jd);
+boolean fill_input_buffer(j_decompress_ptr jd);
+void skip_input_data(j_decompress_ptr jd, long num_bytes);
+void term_source(j_decompress_ptr jd);
+void error_exit(j_common_ptr cinfo);
+
+/*
+ * Implementation of a JPEG src object that understands our state machine
+ */
+struct decoder_source_mgr {
+ /* public fields; must be first in this struct! */
+ struct jpeg_source_mgr pub;
+
+ JPEGImageReader *decoder;
+};
+
+class JPEGImageReader
+{
+public:
+ JPEGImageReader(JPEGImageDecoder* decoder)
+ : m_decoder(decoder)
+ , m_bufferLength(0)
+ , m_bytesToSkip(0)
+ , m_state(JPEG_HEADER)
+ , m_samples(0)
+ {
+ memset(&m_info, 0, sizeof(jpeg_decompress_struct));
+
+ /* We set up the normal JPEG error routines, then override error_exit. */
+ m_info.err = jpeg_std_error(&m_err.pub);
+ m_err.pub.error_exit = error_exit;
+
+ /* Allocate and initialize JPEG decompression object */
+ jpeg_create_decompress(&m_info);
+
+ decoder_source_mgr* src = NULL;
+ if (!m_info.src) {
+ src = (decoder_source_mgr*)fastCalloc(sizeof(decoder_source_mgr), 1);
+ if (!src) {
+ m_state = JPEG_ERROR;
+ return;
+ }
+ }
+
+ m_info.src = (jpeg_source_mgr*)src;
+
+ /* Set up callback functions. */
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart;
+ src->pub.term_source = term_source;
+ src->decoder = this;
+ }
+
+ ~JPEGImageReader()
+ {
+ close();
+ }
+
+ void close() {
+ decoder_source_mgr* src = (decoder_source_mgr*)m_info.src;
+ if (src)
+ fastFree(src);
+ m_info.src = 0;
+
+ jpeg_destroy_decompress(&m_info);
+ }
+
+ void skipBytes(long num_bytes) {
+ decoder_source_mgr* src = (decoder_source_mgr*)m_info.src;
+ long bytesToSkip = std::min(num_bytes, (long)src->pub.bytes_in_buffer);
+ src->pub.bytes_in_buffer -= (size_t)bytesToSkip;
+ src->pub.next_input_byte += bytesToSkip;
+
+ if (num_bytes > bytesToSkip)
+ m_bytesToSkip = (size_t)(num_bytes - bytesToSkip);
+ else
+ m_bytesToSkip = 0;
+ }
+
+ bool decode(const Vector<char>& data, bool sizeOnly) {
+ m_decodingSizeOnly = sizeOnly;
+
+ unsigned newByteCount = data.size() - m_bufferLength;
+ unsigned readOffset = m_bufferLength - m_info.src->bytes_in_buffer;
+
+ m_info.src->bytes_in_buffer += newByteCount;
+ m_info.src->next_input_byte = (JOCTET*)(data.data()) + readOffset;
+
+ // If we still have bytes to skip, try to skip those now.
+ if (m_bytesToSkip)
+ skipBytes(m_bytesToSkip);
+
+ m_bufferLength = data.size();
+
+ // We need to do the setjmp here. Otherwise bad things will happen
+ if (setjmp(m_err.setjmp_buffer)) {
+ m_state = JPEG_SINK_NON_JPEG_TRAILER;
+ close();
+ return false;
+ }
+
+ switch (m_state) {
+ case JPEG_HEADER:
+ {
+ /* Read file parameters with jpeg_read_header() */
+ if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED)
+ return true; /* I/O suspension */
+
+ /* let libjpeg take care of gray->RGB and YCbCr->RGB conversions */
+ switch (m_info.jpeg_color_space) {
+ case JCS_GRAYSCALE:
+ case JCS_RGB:
+ case JCS_YCbCr:
+ m_info.out_color_space = JCS_RGB;
+ break;
+ case JCS_CMYK:
+ case JCS_YCCK:
+ default:
+ m_state = JPEG_ERROR;
+ return false;
+ }
+
+ /*
+ * Don't allocate a giant and superfluous memory buffer
+ * when the image is a sequential JPEG.
+ */
+ m_info.buffered_image = jpeg_has_multiple_scans(&m_info);
+
+ /* Used to set up image size so arrays can be allocated */
+ jpeg_calc_output_dimensions(&m_info);
+
+ /*
+ * Make a one-row-high sample array that will go away
+ * when done with image. Always make it big enough to
+ * hold an RGB row. Since this uses the IJG memory
+ * manager, it must be allocated before the call to
+ * jpeg_start_compress().
+ */
+ int row_stride = m_info.output_width * 4; // RGBA buffer
+
+
+ m_samples = (*m_info.mem->alloc_sarray)((j_common_ptr) &m_info,
+ JPOOL_IMAGE,
+ row_stride, 1);
+
+ m_state = JPEG_START_DECOMPRESS;
+
+ // We can fill in the size now that the header is available.
+ if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) {
+ m_state = JPEG_ERROR;
+ return false;
+ }
+
+ if (m_decodingSizeOnly) {
+ // We can stop here.
+ // Reduce our buffer length and available data.
+ m_bufferLength -= m_info.src->bytes_in_buffer;
+ m_info.src->bytes_in_buffer = 0;
+ return true;
+ }
+ }
+
+ case JPEG_START_DECOMPRESS:
+ {
+ /* Set parameters for decompression */
+ /* FIXME -- Should reset dct_method and dither mode
+ * for final pass of progressive JPEG
+ */
+ m_info.dct_method = JDCT_ISLOW;
+ m_info.dither_mode = JDITHER_FS;
+ m_info.do_fancy_upsampling = true;
+ m_info.enable_2pass_quant = false;
+ m_info.do_block_smoothing = true;
+
+ /* Start decompressor */
+ if (!jpeg_start_decompress(&m_info))
+ return true; /* I/O suspension */
+
+ /* If this is a progressive JPEG ... */
+ m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL;
+ }
+
+ case JPEG_DECOMPRESS_SEQUENTIAL:
+ {
+ if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) {
+
+ if (!m_decoder->outputScanlines())
+ return true; /* I/O suspension */
+
+ /* If we've completed image output ... */
+ assert(m_info.output_scanline == m_info.output_height);
+ m_state = JPEG_DONE;
+ }
+ }
+
+ case JPEG_DECOMPRESS_PROGRESSIVE:
+ {
+ if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) {
+ int status;
+ do {
+ status = jpeg_consume_input(&m_info);
+ } while ((status != JPEG_SUSPENDED) &&
+ (status != JPEG_REACHED_EOI));
+
+ for (;;) {
+ if (m_info.output_scanline == 0) {
+ int scan = m_info.input_scan_number;
+
+ /* if we haven't displayed anything yet (output_scan_number==0)
+ and we have enough data for a complete scan, force output
+ of the last full scan */
+ if ((m_info.output_scan_number == 0) &&
+ (scan > 1) &&
+ (status != JPEG_REACHED_EOI))
+ scan--;
+
+ if (!jpeg_start_output(&m_info, scan))
+ return true; /* I/O suspension */
+ }
+
+ if (m_info.output_scanline == 0xffffff)
+ m_info.output_scanline = 0;
+
+ if (!m_decoder->outputScanlines()) {
+ if (m_info.output_scanline == 0)
+ /* didn't manage to read any lines - flag so we don't call
+ jpeg_start_output() multiple times for the same scan */
+ m_info.output_scanline = 0xffffff;
+ return true; /* I/O suspension */
+ }
+
+ if (m_info.output_scanline == m_info.output_height) {
+ if (!jpeg_finish_output(&m_info))
+ return true; /* I/O suspension */
+
+ if (jpeg_input_complete(&m_info) &&
+ (m_info.input_scan_number == m_info.output_scan_number))
+ break;
+
+ m_info.output_scanline = 0;
+ }
+ }
+
+ m_state = JPEG_DONE;
+ }
+ }
+
+ case JPEG_DONE:
+ {
+ /* Finish decompression */
+ if (!jpeg_finish_decompress(&m_info))
+ return true; /* I/O suspension */
+
+ m_state = JPEG_SINK_NON_JPEG_TRAILER;
+
+ /* we're done */
+ break;
+ }
+
+ case JPEG_SINK_NON_JPEG_TRAILER:
+ break;
+
+ case JPEG_ERROR:
+ break;
+ }
+
+ return true;
+ }
+
+ jpeg_decompress_struct* info() { return &m_info; }
+ JSAMPARRAY samples() const { return m_samples; }
+ JPEGImageDecoder* decoder() { return m_decoder; }
+
+private:
+ JPEGImageDecoder* m_decoder;
+ unsigned m_bufferLength;
+ int m_bytesToSkip;
+ bool m_decodingSizeOnly;
+ bool m_initialized;
+
+ jpeg_decompress_struct m_info;
+ decoder_error_mgr m_err;
+ jstate m_state;
+
+ JSAMPARRAY m_samples;
+};
+
+/* Override the standard error method in the IJG JPEG decoder code. */
+void error_exit(j_common_ptr cinfo)
+{
+ /* Return control to the setjmp point. */
+ decoder_error_mgr *err = (decoder_error_mgr *) cinfo->err;
+ longjmp(err->setjmp_buffer, -1);
+}
+
+void init_source(j_decompress_ptr jd)
+{
+}
+
+void skip_input_data(j_decompress_ptr jd, long num_bytes)
+{
+ decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
+ src->decoder->skipBytes(num_bytes);
+}
+
+boolean fill_input_buffer(j_decompress_ptr jd)
+{
+ // Our decode step always sets things up properly, so if this method is ever
+ // called, then we have hit the end of the buffer. A return value of FALSE indicates
+ // that we have no data to supply yet.
+ return false;
+}
+
+void term_source (j_decompress_ptr jd)
+{
+ decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
+ src->decoder->decoder()->jpegComplete();
+}
+
+JPEGImageDecoder::JPEGImageDecoder()
+: m_reader(0)
+{}
+
+JPEGImageDecoder::~JPEGImageDecoder()
+{
+ delete m_reader;
+}
+
+// Take the data and store it.
+void JPEGImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
+{
+ if (m_failed)
+ return;
+
+ // Cache our new data.
+ ImageDecoder::setData(data, allDataReceived);
+
+ // Create the JPEG reader.
+ if (!m_reader && !m_failed)
+ m_reader = new JPEGImageReader(this);
+}
+
+// Whether or not the size information has been decoded yet.
+bool JPEGImageDecoder::isSizeAvailable() const
+{
+ // If we have pending data to decode, send it to the JPEG reader now.
+ if (!ImageDecoder::isSizeAvailable() && m_reader) {
+ if (m_failed)
+ return false;
+
+ // The decoder will go ahead and aggressively consume everything up until the
+ // size is encountered.
+ decode(true);
+ }
+
+ return !m_failed && ImageDecoder::isSizeAvailable();
+}
+
+RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index)
+{
+ if (index)
+ return 0;
+
+ if (m_frameBufferCache.isEmpty())
+ m_frameBufferCache.resize(1);
+
+ RGBA32Buffer& frame = m_frameBufferCache[0];
+ if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
+ // Decode this frame.
+ decode();
+ return &frame;
+}
+
+// Feed data to the JPEG reader.
+void JPEGImageDecoder::decode(bool sizeOnly) const
+{
+ if (m_failed)
+ return;
+
+ m_failed = !m_reader->decode(m_data->buffer(), sizeOnly);
+
+ if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) {
+ delete m_reader;
+ m_reader = 0;
+ }
+}
+
+bool JPEGImageDecoder::outputScanlines()
+{
+ if (m_frameBufferCache.isEmpty())
+ return false;
+
+ // Resize to the width and height of the image.
+ RGBA32Buffer& buffer = m_frameBufferCache[0];
+ if (buffer.status() == RGBA32Buffer::FrameEmpty) {
+ // Let's resize our buffer now to the correct width/height. This will
+ // also initialize it to transparent.
+ if (!buffer.setSize(size().width(), size().height())) {
+ m_failed = true;
+ buffer.setStatus(RGBA32Buffer::FrameComplete);
+ return false;
+ }
+
+ // Update our status to be partially complete.
+ buffer.setStatus(RGBA32Buffer::FramePartial);
+
+ // For JPEGs, the frame always fills the entire image.
+ buffer.setRect(IntRect(0, 0, size().width(), size().height()));
+
+ // We don't have alpha (this is the default when the buffer is constructed).
+ }
+
+ jpeg_decompress_struct* info = m_reader->info();
+ JSAMPARRAY samples = m_reader->samples();
+
+ while (info->output_scanline < info->output_height) {
+ /* Request one scanline. Returns 0 or 1 scanlines. */
+ if (jpeg_read_scanlines(info, samples, 1) != 1)
+ return false;
+ JSAMPLE *j1 = samples[0];
+ for (unsigned x = 0; x < info->output_width; ++x) {
+ unsigned r = *j1++;
+ unsigned g = *j1++;
+ unsigned b = *j1++;
+ // read_scanlines has increased the scanline counter, so we
+ // actually mean the previous one.
+ buffer.setRGBA(x, info->output_scanline - 1, r, g, b, 0xFF);
+ }
+ }
+
+ return true;
+}
+
+void JPEGImageDecoder::jpegComplete()
+{
+ if (m_frameBufferCache.isEmpty())
+ return;
+
+ // Hand back an appropriately sized buffer, even if the image ended up being empty.
+ RGBA32Buffer& buffer = m_frameBufferCache[0];
+ buffer.setStatus(RGBA32Buffer::FrameComplete);
+}
+
+}
diff --git a/WebCore/platform/qt/SharedTimerQt.h b/WebCore/platform/image-decoders/skia/JPEGImageDecoder.h
index 30e1e21..51dd050 100644
--- a/WebCore/platform/qt/SharedTimerQt.h
+++ b/WebCore/platform/image-decoders/skia/JPEGImageDecoder.h
@@ -1,7 +1,6 @@
/*
- * Copyright (C) 2006 George Staikos <staikos@kde.org>
- *
- * All rights reserved.
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,67 +24,45 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SharedTimerQt_h
-#define SharedTimerQt_h
-
-#include "SharedTimerQt.h"
-#include "SystemTime.h"
+#ifndef JPEGImageDecoder_h
+#define JPEGImageDecoder_h
-#include <QTimer>
-#include <QCoreApplication>
+#include "ImageDecoder.h"
namespace WebCore {
-class SharedTimerQt : public QTimer {
-Q_OBJECT
-protected:
- SharedTimerQt()
- : QTimer()
- , m_timerFunction(0)
- {
- connect(this, SIGNAL(timeout()), this, SLOT(fire()));
- setSingleShot(true);
- }
+ class JPEGImageReader;
- ~SharedTimerQt()
- {
- }
+ // This class decodes the JPEG image format.
+ class JPEGImageDecoder : public ImageDecoder {
+ public:
+ JPEGImageDecoder();
+ ~JPEGImageDecoder();
-public:
- static void cleanup()
- {
- if (s_self->isActive())
- s_self->fire();
+ virtual String filenameExtension() const { return "jpg"; }
- delete s_self;
- s_self = 0;
- }
+ // Take the data and store it.
+ virtual void setData(SharedBuffer* data, bool allDataReceived);
- static SharedTimerQt* inst()
- {
- if (!s_self) {
- s_self = new SharedTimerQt();
- qAddPostRoutine(SharedTimerQt::cleanup);
- }
+ // Whether or not the size information has been decoded yet.
+ virtual bool isSizeAvailable() const;
- return s_self;
- }
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+
+ virtual bool supportsAlpha() const { return false; }
- void (*m_timerFunction)();
+ void decode(bool sizeOnly = false) const;
-public Q_SLOTS:
- void fire()
- {
- if (m_timerFunction)
- (m_timerFunction)();
- }
+ JPEGImageReader* reader() { return m_reader; }
-private:
- static SharedTimerQt* s_self;
-};
+ bool outputScanlines();
+ void jpegComplete();
-}
+ private:
+ friend class JPEGImageReader;
+ mutable JPEGImageReader* m_reader;
+ };
-#endif
+} // namespace WebCore
-// vim: ts=4 sw=4 et
+#endif
diff --git a/WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp
new file mode 100644
index 0000000..ec1ebbe
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ *
+ * Portions are Copyright (C) 2001 mozilla.org
+ *
+ * Other contributors:
+ * Stuart Parmenter <stuart@mozilla.com>
+ *
+ * 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.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+#include "PNGImageDecoder.h"
+#include "png.h"
+#include "assert.h"
+
+namespace WebCore {
+
+// Gamma constants.
+const double cMaxGamma = 21474.83;
+const double cDefaultGamma = 2.2;
+const double cInverseGamma = 0.45455;
+
+// Protect against large PNGs. See Mozilla's bug #251381 for more info.
+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);
+
+// Callbacks given to the read struct. The first is for warnings (we want to treat a particular warning
+// as an error, which is why we have to register this callback.
+static void PNGAPI decodingWarning(png_structp png_ptr, png_const_charp warning_msg);
+
+// Called when we have obtained the header information (including the size).
+static void PNGAPI headerAvailable(png_structp png_ptr, png_infop info_ptr);
+
+// Called when a row is ready.
+static void PNGAPI rowAvailable(png_structp png_ptr, png_bytep new_row,
+ png_uint_32 row_num, int pass);
+
+// Called when we have completely finished decoding the image.
+static void PNGAPI pngComplete(png_structp png_ptr, png_infop info_ptr);
+
+class PNGImageReader
+{
+public:
+ PNGImageReader(PNGImageDecoder* decoder)
+ : 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_info = png_create_info_struct(m_png);
+ png_set_progressive_read_fn(m_png, decoder, headerAvailable, rowAvailable, pngComplete);
+ }
+
+ ~PNGImageReader()
+ {
+ close();
+ }
+
+ void close() {
+ if (m_png && m_info)
+ png_destroy_read_struct(&m_png, &m_info, 0); // Will zero the pointers.
+ delete []m_interlaceBuffer;
+ m_interlaceBuffer = 0;
+ m_readOffset = 0;
+ }
+
+ void decode(const Vector<char>& data, bool sizeOnly)
+ {
+ m_decodingSizeOnly = sizeOnly;
+
+ // We need to do the setjmp here. Otherwise bad things will happen
+ if (setjmp(m_png->jmpbuf)) {
+ close();
+ return;
+ }
+
+ // Go ahead and assume we consumed all the data. If we consume less, the
+ // callback will adjust our read offset accordingly. Do not attempt to adjust the
+ // offset after png_process_data returns.
+ unsigned offset = m_readOffset;
+ unsigned remaining = data.size() - m_readOffset;
+ m_readOffset = data.size();
+ png_process_data(m_png, m_info, (png_bytep)(data.data()) + offset, remaining);
+ }
+
+ bool decodingSizeOnly() const { return m_decodingSizeOnly; }
+ png_structp pngPtr() const { return m_png; }
+ png_infop infoPtr() const { return m_info; }
+ png_bytep interlaceBuffer() const { return m_interlaceBuffer; }
+ bool hasAlpha() const { return m_hasAlpha; }
+
+ void setReadOffset(unsigned offset) { m_readOffset = offset; }
+ void setHasAlpha(bool b) { m_hasAlpha = b; }
+
+ void createInterlaceBuffer(int size) {
+ m_interlaceBuffer = new png_byte[size];
+ }
+
+private:
+ unsigned m_readOffset;
+ bool m_decodingSizeOnly;
+ png_structp m_png;
+ png_infop m_info;
+ png_bytep m_interlaceBuffer;
+ bool m_hasAlpha;
+};
+
+PNGImageDecoder::PNGImageDecoder()
+: m_reader(0)
+{}
+
+PNGImageDecoder::~PNGImageDecoder()
+{
+ delete m_reader;
+}
+
+// Take the data and store it.
+void PNGImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
+{
+ if (m_failed)
+ return;
+
+ // Cache our new data.
+ ImageDecoder::setData(data, allDataReceived);
+
+ // Create the PNG reader.
+ if (!m_reader && !m_failed)
+ m_reader = new PNGImageReader(this);
+}
+
+// Whether or not the size information has been decoded yet.
+bool PNGImageDecoder::isSizeAvailable() const
+{
+ // If we have pending data to decode, send it to the PNG reader now.
+ if (!ImageDecoder::isSizeAvailable() && m_reader) {
+ if (m_failed)
+ return false;
+
+ // The decoder will go ahead and aggressively consume everything up until the
+ // size is encountered.
+ decode(true);
+ }
+
+ return !m_failed && ImageDecoder::isSizeAvailable();
+}
+
+RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index)
+{
+ if (index)
+ return 0;
+
+ if (m_frameBufferCache.isEmpty())
+ m_frameBufferCache.resize(1);
+
+ RGBA32Buffer& frame = m_frameBufferCache[0];
+ if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
+ // Decode this frame.
+ decode();
+ return &frame;
+}
+
+// Feed data to the PNG reader.
+void PNGImageDecoder::decode(bool sizeOnly) const
+{
+ if (m_failed)
+ return;
+
+ m_reader->decode(m_data->buffer(), sizeOnly);
+
+ if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) {
+ delete m_reader;
+ m_reader = 0;
+ }
+}
+
+void decodingFailed(png_structp png, png_const_charp errorMsg)
+{
+ static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->decodingFailed();
+ longjmp(png->jmpbuf, 1);
+}
+
+void decodingWarning(png_structp png, png_const_charp warningMsg)
+{
+ // Mozilla did this, so we will too.
+ // Convert a tRNS warning to be an error (documented in bugzilla.mozilla.org bug #251381)
+ if (!strncmp(warningMsg, "Missing PLTE before tRNS", 24))
+ png_error(png, warningMsg);
+}
+
+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();
+ png_infop info = reader()->infoPtr();
+ png_uint_32 width = png->width;
+ png_uint_32 height = png->height;
+
+ // Protect against large images.
+ if (png->width > cMaxPNGSize || png->height > cMaxPNGSize) {
+ m_failed = true;
+ longjmp(png->jmpbuf, 1);
+ return;
+ }
+
+ // We can fill in the size now that the header is available.
+ if (!ImageDecoder::isSizeAvailable()) {
+ if (!setSize(width, height)) {
+ // Size unreasonable, bail out.
+ longjmp(png->jmpbuf, 1);
+ return;
+ }
+ }
+
+ int bitDepth, colorType, interlaceType, compressionType, filterType, channels;
+ png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType,
+ &interlaceType, &compressionType, &filterType);
+
+ // The options we set here match what Mozilla does.
+
+ // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA.
+ if (colorType == PNG_COLOR_TYPE_PALETTE ||
+ (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8))
+ png_set_expand(png);
+
+ png_bytep trns = 0;
+ int trnsCount = 0;
+ if (png_get_valid(png, info, PNG_INFO_tRNS)) {
+ png_get_tRNS(png, info, &trns, &trnsCount, 0);
+ png_set_expand(png);
+ }
+
+ if (bitDepth == 16)
+ png_set_strip_16(png);
+
+ if (colorType == PNG_COLOR_TYPE_GRAY ||
+ colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png);
+
+ // Deal with gamma and keep it under our control.
+ double gamma;
+ if (png_get_gAMA(png, info, &gamma)) {
+ if ((gamma <= 0.0) || (gamma > cMaxGamma)) {
+ gamma = cInverseGamma;
+ png_set_gAMA(png, info, gamma);
+ }
+ png_set_gamma(png, cDefaultGamma, gamma);
+ }
+ else
+ png_set_gamma(png, cDefaultGamma, cInverseGamma);
+
+ // Tell libpng to send us rows for interlaced pngs.
+ if (interlaceType == PNG_INTERLACE_ADAM7)
+ png_set_interlace_handling(png);
+
+ // Update our info now
+ png_read_update_info(png, info);
+ channels = png_get_channels(png, info);
+ assert(channels == 3 || channels == 4);
+
+ reader()->setHasAlpha(channels == 4);
+
+ if (reader()->decodingSizeOnly()) {
+ // If we only needed the size, halt the reader.
+ reader()->setReadOffset(m_data->size() - png->buffer_size);
+ png->buffer_size = 0;
+ }
+}
+
+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);
+}
+
+void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass)
+{
+ if (m_frameBufferCache.isEmpty())
+ return;
+
+ // Resize to the width and height of the image.
+ RGBA32Buffer& buffer = m_frameBufferCache[0];
+ if (buffer.status() == RGBA32Buffer::FrameEmpty) {
+ // Let's resize our buffer now to the correct width/height.
+ if (!buffer.setSize(size().width(), size().height())) {
+ // Error allocating the bitmap. We should not continue.
+ static_cast<PNGImageDecoder*>(png_get_progressive_ptr(reader()->pngPtr()))->decodingFailed();
+ longjmp(reader()->pngPtr()->jmpbuf, 1);
+ return;
+ }
+
+ // 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, size().width(), size().height()));
+
+ if (reader()->pngPtr()->interlaced)
+ reader()->createInterlaceBuffer((reader()->hasAlpha() ? 4 : 3) * size().width() * size().height());
+ }
+
+ if (rowBuffer == 0)
+ return;
+
+ /* libpng comments (pasted in here to explain what follows)
+ *
+ * this function is called for every row in the image. If the
+ * image is interlacing, and you turned on the interlace handler,
+ * this function will be called for every row in every pass.
+ * Some of these rows will not be changed from the previous pass.
+ * When the row is not changed, the new_row variable will be NULL.
+ * The rows and passes are called in order, so you don't really
+ * need the row_num and pass, but I'm supplying them because it
+ * may make your life easier.
+ *
+ * For the non-NULL rows of interlaced images, you must call
+ * png_progressive_combine_row() passing in the row and the
+ * old row. You can call this function for NULL rows (it will
+ * just return) and for non-interlaced images (it just does the
+ * memcpy for you) if it will make the code easier. Thus, you
+ * can just do this for all cases:
+ *
+ * png_progressive_combine_row(png_ptr, old_row, new_row);
+ *
+ * where old_row is what was displayed for previous rows. Note
+ * that the first pass (pass == 0 really) will completely cover
+ * the old row, so the rows do not have to be initialized. After
+ * the first pass (and only for interlaced images), you will have
+ * to pass the current row, and the function will combine the
+ * old row and the new row.
+ */
+
+ png_structp png = reader()->pngPtr();
+ bool hasAlpha = reader()->hasAlpha();
+ unsigned colorChannels = hasAlpha ? 4 : 3;
+ png_bytep row;
+ png_bytep interlaceBuffer = reader()->interlaceBuffer();
+ if (interlaceBuffer) {
+ row = interlaceBuffer + (rowIndex * colorChannels * size().width());
+ png_progressive_combine_row(png, row, rowBuffer);
+ }
+ else
+ row = rowBuffer;
+
+ // Copy the data into our buffer.
+ int width = size().width();
+ bool sawAlpha = false;
+ for (int x = 0; x < width; x++) {
+ unsigned red = *row++;
+ unsigned green = *row++;
+ unsigned blue = *row++;
+ unsigned alpha = (hasAlpha ? *row++ : 255);
+ buffer.setRGBA(x, rowIndex, red, green, blue, alpha);
+ if (!sawAlpha && alpha < 255) {
+ sawAlpha = true;
+ buffer.setHasAlpha(true);
+ }
+ }
+}
+
+void pngComplete(png_structp png, png_infop info)
+{
+ static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->pngComplete();
+}
+
+void PNGImageDecoder::pngComplete()
+{
+ if (m_frameBufferCache.isEmpty())
+ return;
+
+ // Hand back an appropriately sized buffer, even if the image ended up being empty.
+ RGBA32Buffer& buffer = m_frameBufferCache[0];
+ buffer.setStatus(RGBA32Buffer::FrameComplete);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/skia/PNGImageDecoder.h b/WebCore/platform/image-decoders/skia/PNGImageDecoder.h
new file mode 100644
index 0000000..83cf343
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/PNGImageDecoder.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ *
+ * 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 PNGImageDecoder_h
+#define PNGImageDecoder_h
+
+#include "ImageDecoder.h"
+
+namespace WebCore {
+
+ class PNGImageReader;
+
+ // This class decodes the PNG image format.
+ class PNGImageDecoder : public ImageDecoder {
+ public:
+ PNGImageDecoder();
+ ~PNGImageDecoder();
+
+ virtual String filenameExtension() const { return "png"; }
+
+ // 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;
+
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+
+ void decode(bool sizeOnly = false) const;
+
+ PNGImageReader* reader() { return m_reader; }
+
+ // Callbacks from libpng
+ void decodingFailed();
+ void headerAvailable();
+ void rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass);
+ void pngComplete();
+
+ private:
+ mutable PNGImageReader* m_reader;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/image-decoders/skia/XBMImageDecoder.cpp b/WebCore/platform/image-decoders/skia/XBMImageDecoder.cpp
new file mode 100644
index 0000000..8908504
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/XBMImageDecoder.cpp
@@ -0,0 +1,280 @@
+/*
+ * 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 "config.h"
+#include "XBMImageDecoder.h"
+
+#include <algorithm>
+
+namespace WebCore {
+
+XBMImageDecoder::XBMImageDecoder()
+ : m_decodeOffset(0)
+ , m_allDataReceived(false)
+ , m_decodedHeader(false)
+ , m_dataType(Unknown)
+ , m_bitsDecoded(0)
+{
+}
+
+void XBMImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
+{
+ ImageDecoder::setData(data, allDataReceived);
+
+ const Vector<char>& buf = m_data->buffer();
+ if (buf.size() > m_xbmString.size())
+ m_xbmString.append(&buf[m_xbmString.size()], buf.size() - m_xbmString.size());
+
+ m_allDataReceived = allDataReceived;
+}
+
+bool XBMImageDecoder::isSizeAvailable() const
+{
+ // This method should either (a) not be const, or (b) not be expected to
+ // do anything that changes m_sizeAvailable. The png and jpeg decoders
+ // get around this with callbacks from external libraries.
+ //
+ // FIXME: Find out if we can patch webkit to take care of this.
+ if (!ImageDecoder::isSizeAvailable() && !m_failed)
+ const_cast<XBMImageDecoder*>(this)->decodeXBM(true);
+
+ return !m_failed && ImageDecoder::isSizeAvailable();
+}
+
+RGBA32Buffer* XBMImageDecoder::frameBufferAtIndex(size_t index)
+{
+ // Allocate a framebuffer if necessary. New framebuffers have their status
+ // initialized to RGBA32Buffer::FrameEmpty.
+ if (m_frameBufferCache.isEmpty())
+ m_frameBufferCache.resize(1);
+
+ RGBA32Buffer& frame = m_frameBufferCache[0];
+
+ // Attempt to get the size if we don't have it yet.
+ if (!ImageDecoder::isSizeAvailable())
+ decodeXBM(true);
+
+ // Size the framebuffer once we know the right size.
+ if (ImageDecoder::isSizeAvailable() &&
+ frame.status() == RGBA32Buffer::FrameEmpty) {
+ if (!frame.setSize(size().width(), size().height())) {
+ m_failed = true;
+ frame.setStatus(RGBA32Buffer::FrameComplete);
+ return 0;
+ }
+ frame.setStatus(RGBA32Buffer::FramePartial);
+ }
+
+ // Keep trying to decode until we've got the entire image.
+ if (frame.status() != RGBA32Buffer::FrameComplete)
+ decodeXBM(false);
+
+ return &frame;
+}
+
+bool XBMImageDecoder::decodeHeader()
+{
+ ASSERT(m_decodeOffset <= m_xbmString.size());
+ ASSERT(!m_decodedHeader);
+
+ const char* input = m_xbmString.c_str();
+
+ // At least 2 "#define <string> <unsigned>" sequences are required. These
+ // specify the width and height of the image.
+ int width, height;
+ if (!ImageDecoder::isSizeAvailable()) {
+ int count;
+ if (sscanf(&input[m_decodeOffset], "#define %*s %i #define %*s %i%n",
+ &width, &height, &count) != 2)
+ return false;
+
+ // The width and height need to follow some rules.
+ if (width < 0 || width > maxDimension || height < 0 || height > maxDimension) {
+ // If this happens, decoding should not continue.
+ setFailed();
+ return false;
+ }
+
+ if (!setSize(width, height)) {
+ setFailed();
+ return false;
+ }
+ m_decodeOffset += count;
+ ASSERT(m_decodeOffset <= m_xbmString.size());
+ }
+
+ ASSERT(ImageDecoder::isSizeAvailable());
+
+ // Now we're looking for something that tells us that we've seen all of the
+ // "#define <string> <unsigned>" sequences that we're going to. Mozilla
+ // just looks for " char " or " short ". We'll do the same.
+ if (m_dataType == Unknown) {
+ const char* x11hint = " char ";
+ const char* x11HintLocation = strstr(&input[m_decodeOffset], x11hint);
+ if (x11HintLocation) {
+ m_dataType = X11;
+ m_decodeOffset += ((x11HintLocation - &input[m_decodeOffset]) + strlen(x11hint));
+ } else {
+ const char* x10hint = " short ";
+ const char* x10HintLocation = strstr(&input[m_decodeOffset], x10hint);
+ if (x10HintLocation) {
+ m_dataType = X10;
+ m_decodeOffset += ((x10HintLocation - &input[m_decodeOffset]) + strlen(x10hint));
+ } else
+ return false;
+ }
+ ASSERT(m_decodeOffset <= m_xbmString.size());
+ }
+
+ // Find the start of the data. Again, we do what mozilla does and just
+ // look for a '{' in the input.
+ const char* found = strchr(&input[m_decodeOffset], '{');
+ if (!found)
+ return false;
+
+ // Advance to character after the '{'
+ m_decodeOffset += ((found - &input[m_decodeOffset]) + 1);
+ ASSERT(m_decodeOffset <= m_xbmString.size());
+ m_decodedHeader = true;
+
+ return true;
+}
+
+// The data in an XBM file is provided as an array of either "char" or "short"
+// values. These values are decoded one at a time using strtoul() and the bits
+// are used to set the alpha value for the image.
+//
+// The value for the color is always set to RGB(0,0,0), the alpha value takes
+// care of whether or not the pixel shows up.
+//
+// Since the data may arrive in chunks, and many prefixes of valid numbers are
+// themselves valid numbers, this code needs to check to make sure that the
+// value is not truncated. This is done by consuming space after the value
+// read until a ',' or a '}' occurs. In a valid XBM, one of these characters
+// will occur after each value.
+//
+// The checks after strtoul are based on Mozilla's nsXBMDecoder.cpp.
+bool XBMImageDecoder::decodeDatum(uint16_t* result)
+{
+ const char* input = m_xbmString.c_str();
+ char* endPtr;
+ const uint16_t value = strtoul(&input[m_decodeOffset], &endPtr, 0);
+
+ // End of input or couldn't decode anything, can't go any further.
+ if (endPtr == &input[m_decodeOffset] || !*endPtr)
+ return false;
+
+ // Possibly a hex value truncated at "0x". Need more data.
+ if (value == 0 && (*endPtr == 'x' || *endPtr == 'X'))
+ return false;
+
+ // Skip whitespace
+ while (*endPtr && isspace(*endPtr))
+ ++endPtr;
+
+ // Out of input, don't know what comes next.
+ if (!*endPtr)
+ return false;
+
+ // If the next non-whitespace character is not one of these, it's an error.
+ // Every valid entry in the data array needs to be followed by ',' or '}'.
+ if (*endPtr != ',' && *endPtr != '}') {
+ setFailed();
+ return false;
+ }
+
+ // At this point we have a value.
+ *result = value;
+
+ // Skip over the decoded value plus the delimiter (',' or '}').
+ m_decodeOffset += ((endPtr - &input[m_decodeOffset]) + 1);
+ ASSERT(m_decodeOffset <= m_xbmString.size());
+
+ return true;
+}
+
+bool XBMImageDecoder::decodeData()
+{
+ ASSERT(m_decodeOffset <= m_xbmString.size());
+ ASSERT(m_decodedHeader && !m_frameBufferCache.isEmpty());
+
+ RGBA32Buffer& frame = m_frameBufferCache[0];
+
+ ASSERT(frame.status() == RGBA32Buffer::FramePartial);
+
+ const int bitsPerRow = size().width();
+
+ ASSERT(m_dataType != Unknown);
+
+ while (m_bitsDecoded < (size().width() * size().height())) {
+ uint16_t value;
+ if (!decodeDatum(&value))
+ return false;
+
+ int x = m_bitsDecoded % bitsPerRow;
+ const int y = m_bitsDecoded / bitsPerRow;
+
+ // How many bits will be written?
+ const int bits = std::min(bitsPerRow - x, (m_dataType == X11) ? 8 : 16);
+
+ // Only the alpha channel matters here, so the color values are always
+ // set to 0.
+ for (int i = 0; i < bits; ++i)
+ frame.setRGBA(x++, y, 0, 0, 0, value & (1 << i) ? 255 : 0);
+
+ m_bitsDecoded += bits;
+ }
+
+ frame.setStatus(RGBA32Buffer::FrameComplete);
+
+ return true;
+}
+
+// Decode as much as we can of the XBM file.
+void XBMImageDecoder::decodeXBM(bool sizeOnly)
+{
+ if (failed())
+ return;
+
+ bool decodeResult = false;
+
+ if (!m_decodedHeader)
+ decodeResult = decodeHeader();
+
+ if (m_decodedHeader && !sizeOnly)
+ decodeResult = decodeData();
+
+ // The header or the data could not be decoded, but there is no more
+ // data: decoding has failed.
+ if (!decodeResult && m_allDataReceived)
+ setFailed();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/skia/XBMImageDecoder.h b/WebCore/platform/image-decoders/skia/XBMImageDecoder.h
new file mode 100644
index 0000000..44c6be2
--- /dev/null
+++ b/WebCore/platform/image-decoders/skia/XBMImageDecoder.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef XBMImageDecoder_h
+#define XBMImageDecoder_h
+
+#include "config.h"
+#include <string>
+#include "ImageDecoder.h"
+
+namespace WebCore {
+
+ // This class decodes the XBM image format.
+ class XBMImageDecoder : public ImageDecoder {
+ public:
+ XBMImageDecoder();
+ virtual ~XBMImageDecoder() {}
+
+ virtual String filenameExtension() const { return "xbm"; }
+
+ virtual void setData(SharedBuffer* data, bool allDataReceived);
+ // Whether or not the size information has been decoded yet.
+ virtual bool isSizeAvailable() const;
+ virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+
+ private:
+ // Restricts image size to something "reasonable".
+ // This protects agains ridiculously large XBMs and prevents bad things
+ // like overflow of m_bitsDecoded.
+ static const int maxDimension = 65535;
+
+ // In X10, an array of type "short" is used to declare the image bits,
+ // but in X11, the type is "char".
+ enum DataType {
+ Unknown,
+ X10,
+ X11,
+ };
+
+ bool decodeHeader();
+ bool decodeDatum(uint16_t* result);
+ bool decodeData();
+ void decodeXBM(bool sizeOnly);
+
+ std::string m_xbmString; // Null-terminated copy of the XBM data.
+ size_t m_decodeOffset; // The current offset in m_xbmString for decoding.
+ bool m_allDataReceived;
+ bool m_decodedHeader;
+ enum DataType m_dataType;
+ int m_bitsDecoded;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h
index 7c693f4..dc6d8d4 100644
--- a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h
+++ b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h
@@ -36,6 +36,8 @@ class XBMImageReader;
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;
diff --git a/WebCore/platform/mac/ClipboardMac.mm b/WebCore/platform/mac/ClipboardMac.mm
index 8117b2b..cfa334b 100644
--- a/WebCore/platform/mac/ClipboardMac.mm
+++ b/WebCore/platform/mac/ClipboardMac.mm
@@ -36,6 +36,7 @@
#import "Page.h"
#import "Pasteboard.h"
#import "RenderImage.h"
+#import "SecurityOrigin.h"
#import "WebCoreSystemInterface.h"
namespace WebCore {
@@ -211,7 +212,7 @@ bool ClipboardMac::setData(const String &type, const String &data)
NSURL *url = [[NSURL alloc] initWithString:cocoaData];
[url writeToPasteboard:m_pasteboard.get()];
- if ([url isFileURL]) {
+ if ([url isFileURL] && m_frame->document()->securityOrigin()->canLoadLocalResources()) {
[m_pasteboard.get() addTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];
NSArray *fileList = [NSArray arrayWithObject:[url path]];
[m_pasteboard.get() setPropertyList:fileList forType:NSFilenamesPboardType];
diff --git a/WebCore/platform/mac/CookieJar.mm b/WebCore/platform/mac/CookieJar.mm
index 5fe7a63..94b7d77 100644
--- a/WebCore/platform/mac/CookieJar.mm
+++ b/WebCore/platform/mac/CookieJar.mm
@@ -34,53 +34,77 @@
typedef unsigned NSUInteger;
#endif
+@interface NSHTTPCookie (WebCoreHTTPOnlyCookies)
+- (BOOL)isHTTPOnly;
+@end
+
namespace WebCore {
-String cookies(const Document* /*document*/, const KURL& url)
+static bool isHTTPOnly(NSHTTPCookie *cookie)
{
- BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ // Once we require a newer version of Foundation with the isHTTPOnly method,
+ // we can eliminate the instancesRespondToSelector: check.
+ static bool supportsHTTPOnlyCookies = [NSHTTPCookie instancesRespondToSelector:@selector(isHTTPOnly)];
+ return supportsHTTPOnlyCookies && [cookie isHTTPOnly];
+}
- NSURL *cookieURL = url;
- NSArray *cookiesForURL = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:cookieURL];
+static RetainPtr<NSArray> filterCookies(NSArray *unfilteredCookies)
+{
+ NSUInteger count = [unfilteredCookies count];
+ RetainPtr<NSMutableArray> filteredCookies(AdoptNS, [[NSMutableArray alloc] initWithCapacity:count]);
- // <rdar://problem/5632883> On 10.5, NSHTTPCookieStorage would happily store an empty cookie, which would be sent as "Cookie: =".
- // We have a workaround in setCookies() to prevent that, but we also need to avoid sending cookies that were previously stored.
- NSUInteger count = [cookiesForURL count];
- RetainPtr<NSMutableArray> cookiesForURLFilteredCopy(AdoptNS, [[NSMutableArray alloc] initWithCapacity:count]);
for (NSUInteger i = 0; i < count; ++i) {
- NSHTTPCookie *cookie = (NSHTTPCookie *)[cookiesForURL objectAtIndex:i];
- if ([[cookie name] length] != 0)
- [cookiesForURLFilteredCopy.get() addObject:cookie];
+ NSHTTPCookie *cookie = (NSHTTPCookie *)[unfilteredCookies objectAtIndex:i];
+
+ // <rdar://problem/5632883> On 10.5, NSHTTPCookieStorage would store an empty cookie,
+ // which would be sent as "Cookie: =". We have a workaround in setCookies() to prevent
+ // that, but we also need to avoid sending cookies that were previously stored, and
+ // there's no harm to doing this check because such a cookie is never valid.
+ if (![[cookie name] length])
+ continue;
+
+ if (isHTTPOnly(cookie))
+ continue;
+
+ [filteredCookies.get() addObject:cookie];
}
- NSDictionary *header = [NSHTTPCookie requestHeaderFieldsWithCookies:cookiesForURLFilteredCopy.get()];
- return [header objectForKey:@"Cookie"];
+ return filteredCookies;
+}
+
+String cookies(const Document*, const KURL& url)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ NSURL *cookieURL = url;
+ NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:cookieURL];
+ return [[NSHTTPCookie requestHeaderFieldsWithCookies:filterCookies(cookies).get()] objectForKey:@"Cookie"];
END_BLOCK_OBJC_EXCEPTIONS;
return String();
}
-void setCookies(Document* /*document*/, const KURL& url, const KURL& policyBaseURL, const String& cookieStr)
+void setCookies(Document*, const KURL& url, const KURL& policyBaseURL, const String& cookieStr)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- // <rdar://problem/5632883> On 10.5, NSHTTPCookieStorage would happily store an empty cookie, which would be sent as "Cookie: =".
+ // <rdar://problem/5632883> On 10.5, NSHTTPCookieStorage would store an empty cookie,
+ // which would be sent as "Cookie: =".
if (cookieStr.isEmpty())
return;
- NSURL *cookieURL = url;
-
// <http://bugs.webkit.org/show_bug.cgi?id=6531>, <rdar://4409034>
// cookiesWithResponseHeaderFields doesn't parse cookies without a value
String cookieString = cookieStr.contains('=') ? cookieStr : cookieStr + "=";
-
+
+ NSURL *cookieURL = url;
NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[NSDictionary dictionaryWithObject:cookieString forKey:@"Set-Cookie"] forURL:cookieURL];
- [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:cookieURL mainDocumentURL:policyBaseURL];
+ [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:filterCookies(cookies).get() forURL:cookieURL mainDocumentURL:policyBaseURL];
END_BLOCK_OBJC_EXCEPTIONS;
}
-bool cookiesEnabled(const Document* /*document*/)
+bool cookiesEnabled(const Document*)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
diff --git a/WebCore/platform/mac/CursorMac.mm b/WebCore/platform/mac/CursorMac.mm
index b07964b..c28f149 100644
--- a/WebCore/platform/mac/CursorMac.mm
+++ b/WebCore/platform/mac/CursorMac.mm
@@ -30,6 +30,7 @@
#import "FoundationExtras.h"
#import "Image.h"
#import "IntPoint.h"
+#import <wtf/StdLibExtras.h>
@interface WebCoreCursorBundle : NSObject { }
@end
@@ -72,7 +73,7 @@ static NSCursor* leakNamedCursor(const char* name, int x, int y)
}
return cursor;
END_BLOCK_OBJC_EXCEPTIONS;
- return 0;
+ return nil;
}
Cursor::Cursor(Image* image, const IntPoint& hotspot)
@@ -105,193 +106,193 @@ Cursor::Cursor(NSCursor* c)
const Cursor& pointerCursor()
{
- static Cursor c = [NSCursor arrowCursor];
+ DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor arrowCursor]));
return c;
}
const Cursor& crossCursor()
{
- static Cursor c = leakNamedCursor("crossHairCursor", 11, 11);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("crossHairCursor", 11, 11)));
return c;
}
const Cursor& handCursor()
{
- static Cursor c = leakNamedCursor("linkCursor", 6, 1);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("linkCursor", 6, 1)));
return c;
}
const Cursor& moveCursor()
{
- static Cursor c = leakNamedCursor("moveCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("moveCursor", 7, 7)));
return c;
}
const Cursor& verticalTextCursor()
{
- static Cursor c = leakNamedCursor("verticalTextCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("verticalTextCursor", 7, 7)));
return c;
}
const Cursor& cellCursor()
{
- static Cursor c = leakNamedCursor("cellCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("cellCursor", 7, 7)));
return c;
}
const Cursor& contextMenuCursor()
{
- static Cursor c = leakNamedCursor("contextMenuCursor", 3, 2);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("contextMenuCursor", 3, 2)));
return c;
}
const Cursor& aliasCursor()
{
- static Cursor c = leakNamedCursor("aliasCursor", 11, 3);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("aliasCursor", 11, 3)));
return c;
}
const Cursor& zoomInCursor()
{
- static Cursor c = leakNamedCursor("zoomInCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("zoomInCursor", 7, 7)));
return c;
}
const Cursor& zoomOutCursor()
{
- static Cursor c = leakNamedCursor("zoomOutCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("zoomOutCursor", 7, 7)));
return c;
}
const Cursor& copyCursor()
{
- static Cursor c = leakNamedCursor("copyCursor", 3, 2);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("copyCursor", 3, 2)));
return c;
}
const Cursor& noneCursor()
{
- static Cursor c = leakNamedCursor("noneCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("noneCursor", 7, 7)));
return c;
}
const Cursor& progressCursor()
{
- static Cursor c = leakNamedCursor("progressCursor", 3, 2);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("progressCursor", 3, 2)));
return c;
}
const Cursor& noDropCursor()
{
- static Cursor c = leakNamedCursor("noDropCursor", 3, 1);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("noDropCursor", 3, 1)));
return c;
}
const Cursor& notAllowedCursor()
{
- static Cursor c = leakNamedCursor("notAllowedCursor", 11, 11);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("notAllowedCursor", 11, 11)));
return c;
}
const Cursor& iBeamCursor()
{
- static Cursor c = [NSCursor IBeamCursor];
+ DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor IBeamCursor]));
return c;
}
const Cursor& waitCursor()
{
- static Cursor c = leakNamedCursor("waitCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("waitCursor", 7, 7)));
return c;
}
const Cursor& helpCursor()
{
- static Cursor c = leakNamedCursor("helpCursor", 8, 8);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("helpCursor", 8, 8)));
return c;
}
const Cursor& eastResizeCursor()
{
- static Cursor c = leakNamedCursor("eastResizeCursor", 14, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("eastResizeCursor", 14, 7)));
return c;
}
const Cursor& northResizeCursor()
{
- static Cursor c = leakNamedCursor("northResizeCursor", 7, 1);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northResizeCursor", 7, 1)));
return c;
}
const Cursor& northEastResizeCursor()
{
- static Cursor c = leakNamedCursor("northEastResizeCursor", 14, 1);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northEastResizeCursor", 14, 1)));
return c;
}
const Cursor& northWestResizeCursor()
{
- static Cursor c = leakNamedCursor("northWestResizeCursor", 0, 0);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northWestResizeCursor", 0, 0)));
return c;
}
const Cursor& southResizeCursor()
{
- static Cursor c = leakNamedCursor("southResizeCursor", 7, 14);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southResizeCursor", 7, 14)));
return c;
}
const Cursor& southEastResizeCursor()
{
- static Cursor c = leakNamedCursor("southEastResizeCursor", 14, 14);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southEastResizeCursor", 14, 14)));
return c;
}
const Cursor& southWestResizeCursor()
{
- static Cursor c = leakNamedCursor("southWestResizeCursor", 1, 14);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southWestResizeCursor", 1, 14)));
return c;
}
const Cursor& westResizeCursor()
{
- static Cursor c = leakNamedCursor("westResizeCursor", 1, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("westResizeCursor", 1, 7)));
return c;
}
const Cursor& northSouthResizeCursor()
{
- static Cursor c = leakNamedCursor("northSouthResizeCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northSouthResizeCursor", 7, 7)));
return c;
}
const Cursor& eastWestResizeCursor()
{
- static Cursor c = leakNamedCursor("eastWestResizeCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("eastWestResizeCursor", 7, 7)));
return c;
}
const Cursor& northEastSouthWestResizeCursor()
{
- static Cursor c = leakNamedCursor("northEastSouthWestResizeCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northEastSouthWestResizeCursor", 7, 7)));
return c;
}
const Cursor& northWestSouthEastResizeCursor()
{
- static Cursor c = leakNamedCursor("northWestSouthEastResizeCursor", 7, 7);
+ DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northWestSouthEastResizeCursor", 7, 7)));
return c;
}
const Cursor& columnResizeCursor()
{
- static Cursor c = [NSCursor resizeLeftRightCursor];
+ DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor resizeLeftRightCursor]));
return c;
}
const Cursor& rowResizeCursor()
{
- static Cursor c = [NSCursor resizeUpDownCursor];
+ DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor resizeUpDownCursor]));
return c;
}
@@ -342,13 +343,13 @@ const Cursor& westPanningCursor()
const Cursor& grabCursor()
{
- static Cursor c = [NSCursor openHandCursor];
+ DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor openHandCursor]));
return c;
}
const Cursor& grabbingCursor()
{
- static Cursor c = [NSCursor closedHandCursor];
+ DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor closedHandCursor]));
return c;
}
diff --git a/WebCore/platform/mac/DragDataMac.mm b/WebCore/platform/mac/DragDataMac.mm
index bd66787..5cf2e14 100644
--- a/WebCore/platform/mac/DragDataMac.mm
+++ b/WebCore/platform/mac/DragDataMac.mm
@@ -122,7 +122,7 @@ String DragData::asURL(String* title) const
return m_pasteboardHelper->urlFromPasteboard([m_platformDragData draggingPasteboard], title);
}
-PassRefPtr<DocumentFragment> DragData::asFragment(Document* doc) const
+PassRefPtr<DocumentFragment> DragData::asFragment(Document*) const
{
return [m_pasteboardHelper->fragmentFromPasteboard([m_platformDragData draggingPasteboard]) _documentFragment];
}
diff --git a/WebCore/platform/mac/DragImageMac.mm b/WebCore/platform/mac/DragImageMac.mm
index 098a548..842e6d4 100644
--- a/WebCore/platform/mac/DragImageMac.mm
+++ b/WebCore/platform/mac/DragImageMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 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
@@ -22,31 +22,29 @@
* (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 "DragImage.h"
#import "CachedImage.h"
#import "Image.h"
#import "KURL.h"
-#import "PlatformString.h"
#import "ResourceResponse.h"
-#import <FoundationExtras.h>
namespace WebCore {
-
-
-IntSize dragImageSize(DragImageRef image)
+IntSize dragImageSize(RetainPtr<NSImage> image)
{
return (IntSize)[image.get() size];
}
-void deleteDragImage(DragImageRef image)
+void deleteDragImage(RetainPtr<NSImage>)
{
- //DragImageRef is a RetainPtr, so we don't need to explicitly delete it
+ // Since this is a RetainPtr, there's nothing additional we need to do to
+ // delete it. It will be released when it falls out of scope.
}
-DragImageRef scaleDragImage(DragImageRef image, FloatSize scale)
+RetainPtr<NSImage> scaleDragImage(RetainPtr<NSImage> image, FloatSize scale)
{
NSSize originalSize = [image.get() size];
NSSize newSize = NSMakeSize((originalSize.width * scale.width()), (originalSize.height * scale.height()));
@@ -57,7 +55,7 @@ DragImageRef scaleDragImage(DragImageRef image, FloatSize scale)
return image;
}
-DragImageRef dissolveDragImageToFraction(DragImageRef image, float delta)
+RetainPtr<NSImage> dissolveDragImageToFraction(RetainPtr<NSImage> image, float delta)
{
RetainPtr<NSImage> dissolvedImage(AdoptNS, [[NSImage alloc] initWithSize:[image.get() size]]);
@@ -77,14 +75,14 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float delta)
return image;
}
-DragImageRef createDragImageFromImage(Image* image)
+RetainPtr<NSImage> createDragImageFromImage(Image* image)
{
- DragImageRef dragImage(AdoptNS, [image->getNSImage() copy]);
+ RetainPtr<NSImage> dragImage(AdoptNS, [image->getNSImage() copy]);
[dragImage.get() setSize:(NSSize)(image->size())];
return dragImage;
}
-DragImageRef createDragImageIconForCachedImage(CachedImage* image)
+RetainPtr<NSImage> createDragImageIconForCachedImage(CachedImage* image)
{
const String& filename = image->response().suggestedFilename();
NSString *extension = nil;
@@ -92,12 +90,12 @@ DragImageRef createDragImageIconForCachedImage(CachedImage* image)
if (dotIndex > 0 && dotIndex < (int)(filename.length() - 1)) // require that a . exists after the first character and before the last
extension = filename.substring(dotIndex + 1);
- else
- //It might be worth doing a further look up to pull the extension from the mimetype
+ else {
+ // It might be worth doing a further lookup to pull the extension from the MIME type.
extension = @"";
+ }
- return DragImageRef([[NSWorkspace sharedWorkspace] iconForFileType:extension]);
-
+ return [[NSWorkspace sharedWorkspace] iconForFileType:extension];
}
}
diff --git a/WebCore/platform/mac/LocalizedStringsMac.mm b/WebCore/platform/mac/LocalizedStringsMac.mm
index d458778..d465758 100644
--- a/WebCore/platform/mac/LocalizedStringsMac.mm
+++ b/WebCore/platform/mac/LocalizedStringsMac.mm
@@ -401,6 +401,14 @@ String contextMenuItemTagWritingDirectionMenu()
return String();
}
+String contextMenuItemTagTextDirectionMenu()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return [[WebCoreViewFactory sharedFactory] contextMenuItemTagTextDirectionMenu];
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return String();
+}
+
String contextMenuItemTagDefaultDirection()
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
diff --git a/WebCore/platform/mac/MIMETypeRegistryMac.mm b/WebCore/platform/mac/MIMETypeRegistryMac.mm
index c67b891..7d43505 100644
--- a/WebCore/platform/mac/MIMETypeRegistryMac.mm
+++ b/WebCore/platform/mac/MIMETypeRegistryMac.mm
@@ -31,16 +31,6 @@
namespace WebCore
{
-String getMIMETypeForUTI(const String & uti)
-{
- CFStringRef utiref = uti.createCFString();
- CFStringRef mime = UTTypeCopyPreferredTagWithClass(utiref, kUTTagClassMIMEType);
- String mimeType = mime;
- if (mime)
- CFRelease(mime);
- CFRelease(utiref);
- return mimeType;
-}
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
diff --git a/WebCore/platform/mac/PasteboardMac.mm b/WebCore/platform/mac/PasteboardMac.mm
index 4e15ad0..de369fc 100644
--- a/WebCore/platform/mac/PasteboardMac.mm
+++ b/WebCore/platform/mac/PasteboardMac.mm
@@ -44,7 +44,9 @@
#import "WebCoreNSStringExtras.h"
#import "markup.h"
+#import <wtf/StdLibExtras.h>
#import <wtf/RetainPtr.h>
+#import <wtf/UnusedParam.h>
@interface NSAttributedString (AppKitSecretsIKnowAbout)
- (id)_initWithDOMRange:(DOMRange *)domRange;
@@ -78,27 +80,27 @@ static NSArray* selectionPasteboardTypes(bool canSmartCopyOrDelete, bool selecti
static NSArray* writableTypesForURL()
{
- static RetainPtr<NSArray> types = nil;
- if (!types) {
- types = [[NSArray alloc] initWithObjects:
+ DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, ([[NSArray alloc] initWithObjects:
WebURLsWithTitlesPboardType,
NSURLPboardType,
WebURLPboardType,
WebURLNamePboardType,
NSStringPboardType,
- nil];
- }
+ nil]));
return types.get();
}
+static inline NSArray* createWritableTypesForImage()
+{
+ NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil];
+ [types addObjectsFromArray:writableTypesForURL()];
+ [types addObject:NSRTFDPboardType];
+ return types;
+}
+
static NSArray* writableTypesForImage()
{
- static RetainPtr<NSMutableArray> types = nil;
- if (!types) {
- types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil];
- [types.get() addObjectsFromArray:writableTypesForURL()];
- [types.get() addObject:NSRTFDPboardType];
- }
+ DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, (createWritableTypesForImage()));
return types.get();
}
@@ -121,7 +123,7 @@ void Pasteboard::clear()
static NSAttributedString *stripAttachmentCharacters(NSAttributedString *string)
{
const unichar attachmentCharacter = NSAttachmentCharacter;
- static RetainPtr<NSString> attachmentCharacterString = [NSString stringWithCharacters:&attachmentCharacter length:1];
+ DEFINE_STATIC_LOCAL(RetainPtr<NSString>, attachmentCharacterString, ([NSString stringWithCharacters:&attachmentCharacter length:1]));
NSMutableAttributedString *result = [[string mutableCopy] autorelease];
NSRange attachmentRange = [[result string] rangeOfString:attachmentCharacterString.get()];
while (attachmentRange.location != NSNotFound) {
@@ -142,7 +144,8 @@ void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange,
// 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
// we can't call WebCore::Pasteboard's method for setting types.
-
+ UNUSED_PARAM(canSmartCopyOrDelete);
+
NSArray *types = frame->editor()->client()->pasteboardTypesForSelection(frame);
// Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
NSMutableArray *mutableTypes = nil;
@@ -181,8 +184,7 @@ void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange,
if ([types containsObject:NSStringPboardType]) {
// Map &nbsp; to a plain old space because this is better for source code, other browsers do it,
// and because HTML forces you to do this any time you want two spaces in a row.
- String text = selectedRange->text();
- text.replace('\\', frame->backslashAsCurrencySymbol());
+ String text = frame->displayStringModifiedByEncoding(selectedRange->text());
NSMutableString *s = [[[(NSString*)text copy] autorelease] mutableCopy];
NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&noBreakSpace length:1];
@@ -246,8 +248,7 @@ void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
static NSFileWrapper* fileWrapperForImage(CachedResource* resource, NSURL *url)
{
SharedBuffer* coreData = resource->data();
- NSData *data = [[[NSData alloc] initWithBytes:coreData->platformData()
- length:coreData->platformDataSize()] autorelease];
+ NSData *data = [[[NSData alloc] initWithBytes:coreData->data() length:coreData->size()] autorelease];
NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease];
String coreMIMEType = resource->response().mimeType();
NSString *MIMEType = nil;
diff --git a/WebCore/platform/mac/PlatformMouseEventMac.mm b/WebCore/platform/mac/PlatformMouseEventMac.mm
index af7415d..8979124 100644
--- a/WebCore/platform/mac/PlatformMouseEventMac.mm
+++ b/WebCore/platform/mac/PlatformMouseEventMac.mm
@@ -116,25 +116,6 @@ IntPoint globalPointForEvent(NSEvent *event)
}
}
-int eventNumberForEvent(NSEvent *event)
-{
- switch ([event type]) {
- case NSLeftMouseDown:
- case NSLeftMouseUp:
- case NSLeftMouseDragged:
- case NSRightMouseDown:
- case NSRightMouseUp:
- case NSRightMouseDragged:
- case NSOtherMouseDown:
- case NSOtherMouseUp:
- case NSOtherMouseDragged:
- case NSMouseMoved:
- return [event eventNumber];
- default:
- return 0;
- }
-}
-
static MouseEventType mouseEventForNSEvent(NSEvent* event)
{
switch ([event type]) {
diff --git a/WebCore/platform/mac/PurgeableBufferMac.cpp b/WebCore/platform/mac/PurgeableBufferMac.cpp
new file mode 100644
index 0000000..1b49de0
--- /dev/null
+++ b/WebCore/platform/mac/PurgeableBufferMac.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#ifndef BUILDING_ON_TIGER
+
+#include "PurgeableBuffer.h"
+
+#include <mach/mach.h>
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+static const size_t minPurgeableBufferSize = 4096; // one page
+
+PurgeableBuffer::PurgeableBuffer(char* data, size_t size)
+ : m_data(data)
+ , m_size(size)
+ , m_purgePriority(PurgeDefault)
+ , m_state(NonVolatile)
+{
+}
+
+PurgeableBuffer::~PurgeableBuffer()
+{
+ vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), m_size);
+}
+
+PurgeableBuffer* PurgeableBuffer::create(const char* data, size_t size)
+{
+ if (size < minPurgeableBufferSize)
+ return 0;
+
+ vm_address_t buffer = 0;
+ kern_return_t ret = vm_allocate(mach_task_self(), &buffer, size, VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE);
+
+ ASSERT(ret == KERN_SUCCESS);
+ if (ret != KERN_SUCCESS)
+ return 0;
+
+ ret = vm_copy(mach_task_self(), reinterpret_cast<vm_address_t>(data), size, buffer);
+
+ ASSERT(ret == KERN_SUCCESS);
+ if (ret != KERN_SUCCESS) {
+ vm_deallocate(mach_task_self(), buffer, size);
+ return 0;
+ }
+
+ return new PurgeableBuffer(reinterpret_cast<char*>(buffer), size);
+}
+
+bool PurgeableBuffer::makePurgeable(bool purgeable)
+{
+ if (purgeable) {
+ if (m_state != NonVolatile)
+ return true;
+
+ int volatileGroup;
+ if (m_purgePriority == PurgeFirst)
+ volatileGroup = VM_VOLATILE_GROUP_0;
+ else if (m_purgePriority == PurgeMiddle)
+ volatileGroup = VM_VOLATILE_GROUP_4;
+ else
+ volatileGroup = VM_VOLATILE_GROUP_7;
+
+ int state = VM_PURGABLE_VOLATILE | volatileGroup;
+ // So apparently "purgeable" is the correct spelling and the API here is misspelled.
+ kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), VM_PURGABLE_SET_STATE, &state);
+
+ if (ret != KERN_SUCCESS) {
+ // If that failed we have no clue what state we are in so assume purged.
+ m_state = Purged;
+ return true;
+ }
+
+ m_state = Volatile;
+ return true;
+ }
+
+ if (m_state == NonVolatile)
+ return true;
+ if (m_state == Purged)
+ return false;
+
+ int state = VM_PURGABLE_NONVOLATILE;
+ kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), VM_PURGABLE_SET_STATE, &state);
+
+ if (ret != KERN_SUCCESS) {
+ // If that failed we have no clue what state we are in so assume purged.
+ m_state = Purged;
+ return false;
+ }
+
+ m_state = state & VM_PURGABLE_EMPTY ? Purged : NonVolatile;
+ return m_state == NonVolatile;
+}
+
+bool PurgeableBuffer::wasPurged() const
+{
+ if (m_state == NonVolatile)
+ return false;
+ if (m_state == Purged)
+ return true;
+
+ int state;
+ kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), VM_PURGABLE_GET_STATE, &state);
+
+ if (ret != KERN_SUCCESS) {
+ // If that failed we have no clue what state we are in so assume purged.
+ m_state = Purged;
+ return true;
+ }
+
+ if (state & VM_PURGABLE_EMPTY) {
+ m_state = Purged;
+ return true;
+ }
+
+ return false;
+}
+
+void PurgeableBuffer::setPurgePriority(PurgePriority priority)
+{
+ if (priority == m_purgePriority)
+ return;
+ m_purgePriority = priority;
+ if (m_state != Volatile)
+ return;
+ m_state = NonVolatile;
+ makePurgeable(true);
+}
+
+const char* PurgeableBuffer::data() const
+{
+ ASSERT(m_state == NonVolatile);
+ return m_data;
+}
+
+}
+
+#endif // BUILDING_ON_TIGER
diff --git a/WebCore/platform/mac/ScrollViewMac.mm b/WebCore/platform/mac/ScrollViewMac.mm
index 6d477e2..5ff0ff5 100644
--- a/WebCore/platform/mac/ScrollViewMac.mm
+++ b/WebCore/platform/mac/ScrollViewMac.mm
@@ -92,14 +92,19 @@ void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode
[scrollView() scrollingModes:&horizontal vertical:&vertical];
END_BLOCK_OBJC_EXCEPTIONS;
}
-
-void ScrollView::platformSetCanBlitOnScroll()
+
+void ScrollView::platformSetCanBlitOnScroll(bool canBlitOnScroll)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- [[scrollView() contentView] setCopiesOnScroll:canBlitOnScroll()];
+ [[scrollView() contentView] setCopiesOnScroll:canBlitOnScroll];
END_BLOCK_OBJC_EXCEPTIONS;
}
+bool ScrollView::platformCanBlitOnScroll() const
+{
+ return [[scrollView() contentView] copiesOnScroll];
+}
+
IntRect ScrollView::platformVisibleContentRect(bool includeScrollbars) const
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
@@ -152,7 +157,7 @@ bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity)
{
// FIXME: It would be nice to implement this so that all of the code in WebFrameView could go away.
notImplemented();
- return true;
+ return false;
}
void ScrollView::platformRepaintContentRectangle(const IntRect& rect, bool now)
diff --git a/WebCore/platform/mac/ScrollbarThemeMac.mm b/WebCore/platform/mac/ScrollbarThemeMac.mm
index dd2c233..22bfe46 100644
--- a/WebCore/platform/mac/ScrollbarThemeMac.mm
+++ b/WebCore/platform/mac/ScrollbarThemeMac.mm
@@ -34,8 +34,9 @@
#include "Scrollbar.h"
#include "ScrollbarClient.h"
#include "Settings.h"
-
#include <Carbon/Carbon.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/UnusedParam.h>
// FIXME: There are repainting problems due to Aqua scroll bar buttons' visual overflow.
@@ -57,8 +58,10 @@ static HashSet<Scrollbar*>* gScrollbars;
@implementation ScrollbarPrefsObserver
-+ (void)appearancePrefsChanged:(NSNotification*)theNotification
++ (void)appearancePrefsChanged:(NSNotification*)unusedNotification
{
+ UNUSED_PARAM(unusedNotification);
+
static_cast<ScrollbarThemeMac*>(ScrollbarTheme::nativeTheme())->preferencesChanged();
if (!gScrollbars)
return;
@@ -69,8 +72,10 @@ static HashSet<Scrollbar*>* gScrollbars;
}
}
-+ (void)behaviorPrefsChanged:(NSNotification*)theNotification
++ (void)behaviorPrefsChanged:(NSNotification*)unusedNotification
{
+ UNUSED_PARAM(unusedNotification);
+
static_cast<ScrollbarThemeMac*>(ScrollbarTheme::nativeTheme())->preferencesChanged();
}
@@ -86,7 +91,7 @@ namespace WebCore {
ScrollbarTheme* ScrollbarTheme::nativeTheme()
{
- static ScrollbarThemeMac theme;
+ DEFINE_STATIC_LOCAL(ScrollbarThemeMac, theme, ());
return &theme;
}
diff --git a/WebCore/platform/mac/SharedBufferMac.mm b/WebCore/platform/mac/SharedBufferMac.mm
index ecf01c7..f1d9517 100644
--- a/WebCore/platform/mac/SharedBufferMac.mm
+++ b/WebCore/platform/mac/SharedBufferMac.mm
@@ -24,9 +24,10 @@
*/
#include "config.h"
-#include "FoundationExtras.h"
#include "SharedBuffer.h"
+
#include "WebCoreObjCExtras.h"
+#include <runtime/InitializeThreading.h>
#include <string.h>
#include <wtf/PassRefPtr.h>
@@ -46,12 +47,13 @@ using namespace WebCore;
@implementation WebCoreSharedBufferData
-#ifndef BUILDING_ON_TIGER
+ (void)initialize
{
+ JSC::initializeThreading();
+#ifndef BUILDING_ON_TIGER
WebCoreObjCFinalizeOnMainThread(self);
-}
#endif
+}
- (void)dealloc
{
@@ -113,7 +115,7 @@ CFDataRef SharedBuffer::createCFData()
return m_cfData.get();
}
- return (CFDataRef)HardRetainWithNSRelease([[WebCoreSharedBufferData alloc] initWithSharedBuffer:this]);
+ return (CFDataRef)RetainPtr<WebCoreSharedBufferData>(AdoptNS, [[WebCoreSharedBufferData alloc] initWithSharedBuffer:this]).releaseRef();
}
PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& filePath)
diff --git a/WebCore/platform/mac/SharedTimerMac.mm b/WebCore/platform/mac/SharedTimerMac.mm
index 991f527..b9eaaef 100644
--- a/WebCore/platform/mac/SharedTimerMac.mm
+++ b/WebCore/platform/mac/SharedTimerMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,8 +26,8 @@
#import "config.h"
#import "SharedTimer.h"
-#include <Foundation/Foundation.h>
-#include <wtf/Assertions.h>
+#import <wtf/Assertions.h>
+#import <wtf/UnusedParam.h>
@class WebCorePowerNotifier;
@@ -58,8 +58,10 @@ static void timerFired(CFRunLoopTimerRef, void*);
return self;
}
-- (void)didWake:(NSNotification *)notification
+- (void)didWake:(NSNotification *)unusedNotification
{
+ UNUSED_PARAM(unusedNotification);
+
if (WebCore::sharedTimer) {
WebCore::stopSharedTimer();
WebCore::timerFired(0, 0);
diff --git a/WebCore/platform/mac/SystemTimeMac.cpp b/WebCore/platform/mac/SystemTimeMac.cpp
index dd5e500..1b2aae0 100644
--- a/WebCore/platform/mac/SystemTimeMac.cpp
+++ b/WebCore/platform/mac/SystemTimeMac.cpp
@@ -31,11 +31,6 @@
namespace WebCore {
-double currentTime()
-{
- return CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;
-}
-
float userIdleTime()
{
return static_cast<float>(CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType));
diff --git a/WebCore/platform/mac/ThemeMac.mm b/WebCore/platform/mac/ThemeMac.mm
index 3b1da55..a3e743f 100644
--- a/WebCore/platform/mac/ThemeMac.mm
+++ b/WebCore/platform/mac/ThemeMac.mm
@@ -30,6 +30,7 @@
#import "LocalCurrentGraphicsContext.h"
#import "ScrollView.h"
#import "WebCoreSystemInterface.h"
+#include <wtf/StdLibExtras.h>
using namespace std;
@@ -46,7 +47,7 @@ enum {
Theme* platformTheme()
{
- static ThemeMac themeMac;
+ DEFINE_STATIC_LOCAL(ThemeMac, themeMac, ());
return &themeMac;
}
diff --git a/WebCore/platform/mac/ThreadCheck.mm b/WebCore/platform/mac/ThreadCheck.mm
index 6320c70..b862598 100644
--- a/WebCore/platform/mac/ThreadCheck.mm
+++ b/WebCore/platform/mac/ThreadCheck.mm
@@ -28,6 +28,7 @@
#import "StringHash.h"
#import <wtf/HashSet.h>
+#import <wtf/StdLibExtras.h>
namespace WebCore {
@@ -79,7 +80,7 @@ void reportThreadViolation(const char* function)
void WebCoreReportThreadViolation(const char* function)
{
using namespace WebCore;
- static HashSet<String> loggedFunctions;
+ DEFINE_STATIC_LOCAL(HashSet<String>, loggedFunctions, ());
switch (threadViolationBehavior) {
case NoThreadCheck:
break;
diff --git a/WebCore/platform/mac/WebCoreKeyGenerator.m b/WebCore/platform/mac/WebCoreKeyGenerator.m
index c1004a7..a1e780c 100644
--- a/WebCore/platform/mac/WebCoreKeyGenerator.m
+++ b/WebCore/platform/mac/WebCoreKeyGenerator.m
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003 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,6 +27,7 @@
#import "WebCoreKeyGenerator.h"
#import <wtf/Assertions.h>
+#import <wtf/UnusedParam.h>
static WebCoreKeyGenerator *sharedGenerator;
@@ -50,8 +51,12 @@ static WebCoreKeyGenerator *sharedGenerator;
return nil;
}
-- (NSString *)signedPublicKeyAndChallengeStringWithStrengthIndex:(unsigned)index challenge:(NSString *)challenge pageURL:(NSURL *)pageURL
+- (NSString *)signedPublicKeyAndChallengeStringWithStrengthIndex:(unsigned)unusedIndex challenge:(NSString *)unusedChallenge pageURL:(NSURL *)unusedPageURL
{
+ UNUSED_PARAM(unusedIndex);
+ UNUSED_PARAM(unusedChallenge);
+ UNUSED_PARAM(unusedPageURL);
+
return nil;
}
diff --git a/WebCore/platform/mac/WebCoreNSStringExtras.h b/WebCore/platform/mac/WebCoreNSStringExtras.h
index 95d2031..f040f16 100644
--- a/WebCore/platform/mac/WebCoreNSStringExtras.h
+++ b/WebCore/platform/mac/WebCoreNSStringExtras.h
@@ -26,15 +26,25 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import <Cocoa/Cocoa.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <objc/objc.h>
+
+#ifdef __OBJC__
+#include <Foundation/Foundation.h>
+@class NSString;
+#else
+typedef struct NSString NSString;
+#endif
#ifdef __cplusplus
extern "C" {
#endif
+BOOL stringIsCaseInsensitiveEqualToString(NSString *first, NSString *second);
BOOL hasCaseInsensitiveSuffix(NSString *string, NSString *suffix);
BOOL hasCaseInsensitiveSubstring(NSString *string, NSString *substring);
NSString *filenameByFixingIllegalCharacters(NSString *string);
+CFStringEncoding stringEncodingForResource(Handle resource);
#ifdef __cplusplus
}
diff --git a/WebCore/platform/mac/WebCoreNSStringExtras.mm b/WebCore/platform/mac/WebCoreNSStringExtras.mm
index a2b0a28..b7087f1 100644
--- a/WebCore/platform/mac/WebCoreNSStringExtras.mm
+++ b/WebCore/platform/mac/WebCoreNSStringExtras.mm
@@ -29,6 +29,11 @@
#import "config.h"
#import "WebCoreNSStringExtras.h"
+BOOL stringIsCaseInsensitiveEqualToString(NSString *first, NSString *second)
+{
+ return [first compare:second options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
+}
+
BOOL hasCaseInsensitiveSuffix(NSString *string, NSString *suffix)
{
return [string rangeOfString:suffix options:(NSCaseInsensitiveSearch | NSBackwardsSearch | NSAnchoredSearch)].location != NSNotFound;
@@ -60,3 +65,55 @@ NSString *filenameByFixingIllegalCharacters(NSString *string)
return filename;
}
+
+CFStringEncoding stringEncodingForResource(Handle resource)
+{
+ short resRef = HomeResFile(resource);
+ if (ResError() != noErr) {
+ return NSMacOSRomanStringEncoding;
+ }
+
+ // Get the FSRef for the current resource file
+ FSRef fref;
+ OSStatus error = FSGetForkCBInfo(resRef, 0, NULL, NULL, NULL, &fref, NULL);
+ if (error != noErr) {
+ return NSMacOSRomanStringEncoding;
+ }
+
+ CFURLRef URL = CFURLCreateFromFSRef(NULL, &fref);
+ if (URL == NULL) {
+ return NSMacOSRomanStringEncoding;
+ }
+
+ NSString *path = [(NSURL *)URL path];
+ CFRelease(URL);
+
+ // Get the lproj directory name
+ path = [path stringByDeletingLastPathComponent];
+ if (!stringIsCaseInsensitiveEqualToString([path pathExtension], @"lproj")) {
+ return NSMacOSRomanStringEncoding;
+ }
+
+ NSString *directoryName = [[path stringByDeletingPathExtension] lastPathComponent];
+ CFStringRef locale = CFLocaleCreateCanonicalLocaleIdentifierFromString(NULL, (CFStringRef)directoryName);
+ if (locale == NULL) {
+ return NSMacOSRomanStringEncoding;
+ }
+
+ LangCode lang;
+ RegionCode region;
+ error = LocaleStringToLangAndRegionCodes([(NSString *)locale UTF8String], &lang, &region);
+ CFRelease(locale);
+ if (error != noErr) {
+ return NSMacOSRomanStringEncoding;
+ }
+
+ TextEncoding encoding;
+ error = UpgradeScriptInfoToTextEncoding(kTextScriptDontCare, lang, region, NULL, &encoding);
+ if (error != noErr) {
+ return NSMacOSRomanStringEncoding;
+ }
+
+ return encoding;
+}
+
diff --git a/WebCore/platform/mac/WebCoreObjCExtras.mm b/WebCore/platform/mac/WebCoreObjCExtras.mm
index 105c462..cb8d504 100644
--- a/WebCore/platform/mac/WebCoreObjCExtras.mm
+++ b/WebCore/platform/mac/WebCoreObjCExtras.mm
@@ -34,17 +34,17 @@
#include <wtf/Assertions.h>
#include <wtf/MainThread.h>
#include <wtf/Threading.h>
+#include <wtf/UnusedParam.h>
void WebCoreObjCFinalizeOnMainThread(Class cls)
{
+ // This method relies on threading being initialized by the caller, otherwise
+ // WebCoreObjCScheduleDeallocateOnMainThread will crash.
#if !defined(BUILDING_ON_TIGER) && !defined(DONT_FINALIZE_ON_MAIN_THREAD)
objc_finalizeOnMainThread(cls);
+#else
+ UNUSED_PARAM(cls);
#endif
-
- // The reason we call initializeThreading here is that we'd like to have
- // threading initialized early, otherwise WebCoreObjCScheduleDeallocateOnMainThread
- // will crash
- WTF::initializeThreading();
}
#ifdef BUILDING_ON_TIGER
diff --git a/WebCore/platform/mac/WebCoreSystemInterface.h b/WebCore/platform/mac/WebCoreSystemInterface.h
index 6085483..14d1713 100644
--- a/WebCore/platform/mac/WebCoreSystemInterface.h
+++ b/WebCore/platform/mac/WebCoreSystemInterface.h
@@ -95,15 +95,8 @@ extern void (*wkDrawFocusRing)(CGContextRef, CGColorRef, int radius);
extern NSFont* (*wkGetFontInLanguageForRange)(NSFont*, NSString*, NSRange);
extern NSFont* (*wkGetFontInLanguageForCharacter)(NSFont*, UniChar);
extern BOOL (*wkGetGlyphTransformedAdvances)(CGFontRef, NSFont*, CGAffineTransform*, ATSGlyphRef*, CGSize* advance);
-extern void (*wkDrawMediaFullscreenButton)(CGContextRef context, CGRect rect, BOOL active);
-extern void (*wkDrawMediaMuteButton)(CGContextRef context, CGRect rect, BOOL active);
-extern void (*wkDrawMediaPauseButton)(CGContextRef context, CGRect rect, BOOL active);
-extern void (*wkDrawMediaPlayButton)(CGContextRef context, CGRect rect, BOOL active);
-extern void (*wkDrawMediaSeekBackButton)(CGContextRef context, CGRect rect, BOOL active);
-extern void (*wkDrawMediaSeekForwardButton)(CGContextRef context, CGRect rect, BOOL active);
-extern void (*wkDrawMediaSliderTrack)(CGContextRef context, CGRect rect, float percentLoaded);
-extern void (*wkDrawMediaSliderThumb)(CGContextRef context, CGRect rect, BOOL active);
-extern void (*wkDrawMediaUnMuteButton)(CGContextRef context, CGRect rect, BOOL active);
+extern void (*wkDrawMediaSliderTrack)(int themeStyle, CGContextRef context, CGRect rect, float timeLoaded, float currentTime, float duration);
+extern void (*wkDrawMediaUIPart)(int part, int themeStyle, CGContextRef context, CGRect rect, BOOL active);
extern NSString* (*wkGetPreferredExtensionForMIMEType)(NSString*);
extern NSArray* (*wkGetExtensionsForMIMEType)(NSString*);
extern NSString* (*wkGetMIMETypeForExtension)(NSString*);
@@ -112,6 +105,8 @@ extern double (*wkGetNSURLResponseCalculatedExpiration)(NSURLResponse *response)
extern NSDate *(*wkGetNSURLResponseLastModifiedDate)(NSURLResponse *response);
extern BOOL (*wkGetNSURLResponseMustRevalidate)(NSURLResponse *response);
extern void (*wkGetWheelEventDeltas)(NSEvent*, float* deltaX, float* deltaY, BOOL* continuous);
+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 int (*wkQTMovieDataRate)(QTMovie*);
extern float (*wkQTMovieMaxTimeLoaded)(QTMovie*);
@@ -147,6 +142,8 @@ extern void (*wkReleaseStyleGroup)(void* group);
extern BOOL (*wkSupportsMultipartXMixedReplace)(NSMutableURLRequest *);
#endif
+extern BOOL (*wkUseSharedMediaUI)();
+
#ifdef __cplusplus
}
#endif
diff --git a/WebCore/platform/mac/WebCoreSystemInterface.mm b/WebCore/platform/mac/WebCoreSystemInterface.mm
index c0305ae..b629b4e 100644
--- a/WebCore/platform/mac/WebCoreSystemInterface.mm
+++ b/WebCore/platform/mac/WebCoreSystemInterface.mm
@@ -38,15 +38,10 @@ void (*wkDrawFocusRing)(CGContextRef, CGColorRef, int radius);
NSFont* (*wkGetFontInLanguageForRange)(NSFont*, NSString*, NSRange);
NSFont* (*wkGetFontInLanguageForCharacter)(NSFont*, UniChar);
BOOL (*wkGetGlyphTransformedAdvances)(CGFontRef, NSFont*, CGAffineTransform*, ATSGlyphRef*, CGSize* advance);
-void (*wkDrawMediaFullscreenButton)(CGContextRef context, CGRect rect, BOOL active);
-void (*wkDrawMediaMuteButton)(CGContextRef context, CGRect rect, BOOL active);
-void (*wkDrawMediaPauseButton)(CGContextRef context, CGRect rect, BOOL active);
-void (*wkDrawMediaPlayButton)(CGContextRef context, CGRect rect, BOOL active);
-void (*wkDrawMediaSeekBackButton)(CGContextRef context, CGRect rect, BOOL active);
-void (*wkDrawMediaSeekForwardButton)(CGContextRef context, CGRect rect, BOOL active);
-void (*wkDrawMediaSliderTrack)(CGContextRef context, CGRect rect, float percentLoaded);
-void (*wkDrawMediaSliderThumb)(CGContextRef context, CGRect rect, BOOL active);
-void (*wkDrawMediaUnMuteButton)(CGContextRef context, CGRect rect, BOOL active);
+void (*wkDrawMediaSliderTrack)(int themeStyle, CGContextRef context, CGRect rect, float timeLoaded, float currentTime, float duration);
+BOOL (*wkHitTestMediaUIPart)(int part, int themeStyle, CGRect bounds, CGPoint point);
+void (*wkDrawMediaUIPart)(int part, int themeStyle, CGContextRef context, CGRect rect, BOOL active);
+void (*wkMeasureMediaUIPart)(int part, int themeStyle, CGRect *bounds, CGSize *naturalSize);
NSString* (*wkGetPreferredExtensionForMIMEType)(NSString*);
NSArray* (*wkGetExtensionsForMIMEType)(NSString*);
NSString* (*wkGetMIMETypeForExtension)(NSString*);
diff --git a/WebCore/platform/mac/WebFontCache.mm b/WebCore/platform/mac/WebFontCache.mm
index 84f60b5..6cf1ef4 100644
--- a/WebCore/platform/mac/WebFontCache.mm
+++ b/WebCore/platform/mac/WebFontCache.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
@@ -28,9 +28,9 @@
*/
#import "config.h"
-#import "FontTraitsMask.h"
#import "WebFontCache.h"
+#import "FontTraitsMask.h"
#import <math.h>
using namespace WebCore;
@@ -51,7 +51,7 @@ typedef int NSInteger;
| NSSmallCapsFontMask \
)
-static BOOL acceptableChoice(NSFontTraitMask desiredTraits, int desiredWeight, NSFontTraitMask candidateTraits, int candidateWeight)
+static BOOL acceptableChoice(NSFontTraitMask desiredTraits, NSFontTraitMask candidateTraits)
{
desiredTraits &= ~SYNTHESIZED_FONT_TRAITS;
return (candidateTraits & desiredTraits) == desiredTraits;
@@ -61,7 +61,7 @@ static BOOL betterChoice(NSFontTraitMask desiredTraits, int desiredWeight,
NSFontTraitMask chosenTraits, int chosenWeight,
NSFontTraitMask candidateTraits, int candidateWeight)
{
- if (!acceptableChoice(desiredTraits, desiredWeight, candidateTraits, candidateWeight))
+ if (!acceptableChoice(desiredTraits, candidateTraits))
return NO;
// A list of the traits we care about.
@@ -230,7 +230,7 @@ static inline FontTraitsMask toTraitsMask(NSFontTraitMask appKitTraits, NSIntege
BOOL newWinner;
if (!choseFont)
- newWinner = acceptableChoice(desiredTraits, desiredWeight, fontTraits, fontWeight);
+ newWinner = acceptableChoice(desiredTraits, fontTraits);
else
newWinner = betterChoice(desiredTraits, desiredWeight, chosenTraits, chosenWeight, fontTraits, fontWeight);
diff --git a/WebCore/platform/mac/WidgetMac.mm b/WebCore/platform/mac/WidgetMac.mm
index 3fe8e0d..ecd4f30 100644
--- a/WebCore/platform/mac/WidgetMac.mm
+++ b/WebCore/platform/mac/WidgetMac.mm
@@ -26,6 +26,10 @@
#import "config.h"
#import "Widget.h"
+#ifdef BUILDING_ON_TIGER
+#import "AutodrainedPool.h"
+#endif
+
#import "BlockExceptions.h"
#import "Cursor.h"
#import "Document.h"
@@ -38,7 +42,6 @@
#import "ScrollView.h"
#import "WebCoreFrameView.h"
#import "WebCoreView.h"
-
#import <wtf/RetainPtr.h>
@interface NSWindow (WebWindowDetails)
@@ -218,8 +221,13 @@ void Widget::paint(GraphicsContext* p, const IntRect& r)
CGContextScaleCTM(cgContext, 1, -1);
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- NSGraphicsContext *nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES];
- [view displayRectIgnoringOpacity:[view convertRect:r fromView:[view superview]] inContext:nsContext];
+ {
+#ifdef BUILDING_ON_TIGER
+ AutodrainedPool pool;
+#endif
+ NSGraphicsContext *nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES];
+ [view displayRectIgnoringOpacity:[view convertRect:r fromView:[view superview]] inContext:nsContext];
+ }
END_BLOCK_OBJC_EXCEPTIONS;
CGContextRestoreGState(cgContext);
@@ -252,10 +260,10 @@ void Widget::removeFromSuperview()
}
}
-void Widget::beforeMouseDown(NSView *view, Widget* widget)
+void Widget::beforeMouseDown(NSView *unusedView, Widget* widget)
{
if (widget) {
- ASSERT(view == widget->getOuterView());
+ ASSERT_UNUSED(unusedView, unusedView == widget->getOuterView());
ASSERT(!widget->m_data->mustStayInWindow);
widget->m_data->mustStayInWindow = true;
}
diff --git a/WebCore/platform/network/AuthenticationChallengeBase.h b/WebCore/platform/network/AuthenticationChallengeBase.h
index 5810a6d..9d85866 100644
--- a/WebCore/platform/network/AuthenticationChallengeBase.h
+++ b/WebCore/platform/network/AuthenticationChallengeBase.h
@@ -52,7 +52,7 @@ public:
protected:
// The AuthenticationChallenge subclass may "shadow" this method to compare platform specific fields
- static bool platformCompare(const AuthenticationChallengeBase& a, const AuthenticationChallengeBase& b) { return true; }
+ static bool platformCompare(const AuthenticationChallengeBase&, const AuthenticationChallengeBase&) { return true; }
bool m_isNull;
ProtectionSpace m_protectionSpace;
diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp
index 0d31856..3cac168 100644
--- a/WebCore/platform/network/FormData.cpp
+++ b/WebCore/platform/network/FormData.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004, 2006, 2008 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
@@ -90,6 +91,28 @@ PassRefPtr<FormData> FormData::copy() const
return adoptRef(new FormData(*this));
}
+PassRefPtr<FormData> FormData::deepCopy() const
+{
+ RefPtr<FormData> formData(create());
+
+ formData->m_alwaysStream = m_alwaysStream;
+
+ size_t n = m_elements.size();
+ formData->m_elements.reserveCapacity(n);
+ for (size_t i = 0; i < n; ++i) {
+ const FormDataElement& e = m_elements[i];
+ switch (e.m_type) {
+ case FormDataElement::data:
+ formData->m_elements.append(FormDataElement(e.m_data));
+ break;
+ case FormDataElement::encodedFile:
+ formData->m_elements.append(FormDataElement(e.m_filename, e.m_shouldGenerateFile));
+ break;
+ }
+ }
+ return formData.release();
+}
+
void FormData::appendData(const void* data, size_t size)
{
if (m_elements.isEmpty() || m_elements.last().m_type != FormDataElement::data)
diff --git a/WebCore/platform/network/FormData.h b/WebCore/platform/network/FormData.h
index cb91fab..5998b1b 100644
--- a/WebCore/platform/network/FormData.h
+++ b/WebCore/platform/network/FormData.h
@@ -68,6 +68,7 @@ public:
static PassRefPtr<FormData> create(const CString&);
static PassRefPtr<FormData> create(const Vector<char>&);
PassRefPtr<FormData> copy() const;
+ PassRefPtr<FormData> deepCopy() const;
~FormData();
void appendData(const void* data, size_t);
diff --git a/WebCore/platform/network/FormDataBuilder.cpp b/WebCore/platform/network/FormDataBuilder.cpp
new file mode 100644
index 0000000..27bdee3
--- /dev/null
+++ b/WebCore/platform/network/FormDataBuilder.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2001 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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
+ * 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 "FormDataBuilder.h"
+
+#include "CString.h"
+#include "Document.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "TextEncoding.h"
+
+#include <limits>
+#include <wtf/Assertions.h>
+#include <wtf/RandomNumber.h>
+
+namespace WebCore {
+
+FormDataBuilder::FormDataBuilder()
+ : m_isPostMethod(false)
+ , m_isMultiPartForm(false)
+ , m_encodingType("application/x-www-form-urlencoded")
+{
+}
+
+FormDataBuilder::~FormDataBuilder()
+{
+}
+
+void FormDataBuilder::parseEncodingType(const String& type)
+{
+ if (type.contains("multipart", false) || type.contains("form-data", false)) {
+ m_encodingType = "multipart/form-data";
+ m_isMultiPartForm = true;
+ } else if (type.contains("text", false) || type.contains("plain", false)) {
+ m_encodingType = "text/plain";
+ m_isMultiPartForm = false;
+ } else {
+ m_encodingType = "application/x-www-form-urlencoded";
+ m_isMultiPartForm = false;
+ }
+}
+
+void FormDataBuilder::parseMethodType(const String& type)
+{
+ if (equalIgnoringCase(type, "post"))
+ m_isPostMethod = true;
+ else if (equalIgnoringCase(type, "get"))
+ m_isPostMethod = false;
+}
+
+TextEncoding FormDataBuilder::dataEncoding(Document* document) const
+{
+ String acceptCharset = m_acceptCharset;
+ acceptCharset.replace(',', ' ');
+
+ Vector<String> charsets;
+ acceptCharset.split(' ', charsets);
+
+ TextEncoding encoding;
+
+ Vector<String>::const_iterator end = charsets.end();
+ for (Vector<String>::const_iterator it = charsets.begin(); it != end; ++it) {
+ if ((encoding = TextEncoding(*it)).isValid())
+ return encoding;
+ }
+
+ if (Frame* frame = document->frame())
+ return frame->loader()->encoding();
+
+ return Latin1Encoding();
+}
+
+// Helper functions
+static inline void append(Vector<char>& buffer, char string)
+{
+ buffer.append(string);
+}
+
+static inline void append(Vector<char>& buffer, const char* string)
+{
+ buffer.append(string, strlen(string));
+}
+
+static inline void append(Vector<char>& buffer, const CString& string)
+{
+ buffer.append(string.data(), string.length());
+}
+
+Vector<char> FormDataBuilder::generateUniqueBoundaryString()
+{
+ Vector<char> boundary;
+
+ // The RFC 2046 spec says the alphanumeric characters plus the
+ // following characters are legal for boundaries: '()+_,-./:=?
+ // However the following characters, though legal, cause some sites
+ // to fail: (),./:= (http://bugs.webkit.org/show_bug.cgi?id=13352)
+ static const char alphaNumericEncodingMap[64] = {
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
+ 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
+ 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x41
+ // FIXME <rdar://problem/5252577> gmail does not accept legal characters in the form boundary
+ // As stated above, some legal characters cause, sites to fail. Specifically
+ // the / character which was the last character in the above array. I have
+ // replaced the last character with another character already in the array
+ // (notice the first and last values are both 0x41, A). Instead of picking
+ // another unique legal character for boundary strings that, because it has
+ // never been tested, may or may not break other sites, I simply
+ // replaced / with A. This means A is twice as likely to occur in our boundary
+ // strings than any other character but I think this is fine for the time being.
+ // The FIXME here is about restoring the / character once the aforementioned
+ // radar has been resolved.
+ };
+
+ // Start with an informative prefix.
+ append(boundary, "----WebKitFormBoundary");
+
+ // Append 16 random 7bit ascii AlphaNumeric characters.
+ Vector<char> randomBytes;
+
+ for (unsigned i = 0; i < 4; ++i) {
+ unsigned randomness = static_cast<unsigned>(WTF::randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0));
+ randomBytes.append(alphaNumericEncodingMap[(randomness >> 24) & 0x3F]);
+ randomBytes.append(alphaNumericEncodingMap[(randomness >> 16) & 0x3F]);
+ randomBytes.append(alphaNumericEncodingMap[(randomness >> 8) & 0x3F]);
+ randomBytes.append(alphaNumericEncodingMap[randomness & 0x3F]);
+ }
+
+ boundary.append(randomBytes);
+ boundary.append(0); // Add a 0 at the end so we can use this as a C-style string.
+ return boundary;
+}
+
+void FormDataBuilder::beginMultiPartHeader(Vector<char>& buffer, const CString& boundary, const CString& name)
+{
+ addBoundaryToMultiPartHeader(buffer, boundary);
+
+ append(buffer, "Content-Disposition: form-data; name=\"");
+ append(buffer, name);
+ append(buffer, '"');
+}
+
+void FormDataBuilder::addBoundaryToMultiPartHeader(Vector<char>& buffer, const CString& boundary, bool isLastBoundary)
+{
+ append(buffer, "--");
+ append(buffer, boundary);
+
+ if (isLastBoundary)
+ append(buffer, "--");
+
+ append(buffer, "\r\n");
+}
+
+void FormDataBuilder::addFilenameToMultiPartHeader(Vector<char>& buffer, const TextEncoding& encoding, const String& filename)
+{
+ // FIXME: This won't work if the filename includes a " mark,
+ // or control characters like CR or LF. This also does strange
+ // things if the filename includes characters you can't encode
+ // in the website's character set.
+ append(buffer, "; filename=\"");
+ append(buffer, encoding.encode(filename.characters(), filename.length(), QuestionMarksForUnencodables));
+ append(buffer, '"');
+}
+
+void FormDataBuilder::addContentTypeToMultiPartHeader(Vector<char>& buffer, const CString& mimeType)
+{
+ append(buffer, "\r\nContent-Type: ");
+ append(buffer, mimeType);
+}
+
+void FormDataBuilder::finishMultiPartHeader(Vector<char>& buffer)
+{
+ append(buffer, "\r\n\r\n");
+}
+
+void FormDataBuilder::addKeyValuePairAsFormData(Vector<char>& buffer, const CString& key, const CString& value)
+{
+ if (!buffer.isEmpty())
+ append(buffer, '&');
+
+ encodeStringAsFormData(buffer, key);
+ append(buffer, '=');
+ encodeStringAsFormData(buffer, value);
+}
+
+void FormDataBuilder::encodeStringAsFormData(Vector<char>& buffer, const CString& string)
+{
+ static const char hexDigits[17] = "0123456789ABCDEF";
+
+ // Same safe characters as Netscape for compatibility.
+ static const char safeCharacters[] = "-._*";
+
+ // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
+ unsigned length = string.length();
+ for (unsigned i = 0; i < length; ++i) {
+ unsigned char c = string.data()[i];
+
+ if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || strchr(safeCharacters, c))
+ append(buffer, c);
+ else if (c == ' ')
+ append(buffer, '+');
+ else if (c == '\n' || (c == '\r' && (i + 1 >= length || string.data()[i + 1] != '\n')))
+ append(buffer, "%0D%0A");
+ else if (c != '\r') {
+ append(buffer, '%');
+ append(buffer, hexDigits[c >> 4]);
+ append(buffer, hexDigits[c & 0xF]);
+ }
+ }
+}
+
+}
diff --git a/WebCore/platform/network/FormDataBuilder.h b/WebCore/platform/network/FormDataBuilder.h
new file mode 100644
index 0000000..666f0c1
--- /dev/null
+++ b/WebCore/platform/network/FormDataBuilder.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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
+ * 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 FormDataBuilder_h
+#define FormDataBuilder_h
+
+#include "PlatformString.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class CString;
+class Document;
+class TextEncoding;
+
+class FormDataBuilder : Noncopyable {
+public:
+ FormDataBuilder();
+ ~FormDataBuilder();
+
+ bool isPostMethod() const { return m_isPostMethod; }
+ void setIsPostMethod(bool value) { m_isPostMethod = value; }
+
+ bool isMultiPartForm() const { return m_isMultiPartForm; }
+ void setIsMultiPartForm(bool value) { m_isMultiPartForm = value; }
+
+ String encodingType() const { return m_encodingType; }
+ void setEncodingType(const String& value) { m_encodingType = value; }
+
+ String acceptCharset() const { return m_acceptCharset; }
+ void setAcceptCharset(const String& value) { m_acceptCharset = value; }
+
+ void parseEncodingType(const String&);
+ void parseMethodType(const String&);
+
+ TextEncoding dataEncoding(Document*) const;
+
+ // Helper functions used by HTMLFormElement/WMLGoElement for multi-part form data
+ static Vector<char> generateUniqueBoundaryString();
+ static void beginMultiPartHeader(Vector<char>&, const CString& boundary, const CString& name);
+ static void addBoundaryToMultiPartHeader(Vector<char>&, const CString& boundary, bool isLastBoundary = false);
+ static void addFilenameToMultiPartHeader(Vector<char>&, const TextEncoding&, const String& filename);
+ static void addContentTypeToMultiPartHeader(Vector<char>&, const CString& mimeType);
+ static void finishMultiPartHeader(Vector<char>&);
+
+ // Helper functions used by HTMLFormElement/WMLGoElement for non multi-part form data
+ static void addKeyValuePairAsFormData(Vector<char>&, const CString& key, const CString& value);
+ static void encodeStringAsFormData(Vector<char>&, const CString&);
+
+private:
+ bool m_isPostMethod;
+ bool m_isMultiPartForm;
+
+ String m_encodingType;
+ String m_acceptCharset;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/network/HTTPHeaderMap.cpp b/WebCore/platform/network/HTTPHeaderMap.cpp
new file mode 100644
index 0000000..aa9c5fa
--- /dev/null
+++ b/WebCore/platform/network/HTTPHeaderMap.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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 "HTTPHeaderMap.h"
+
+#include <memory>
+#include <utility>
+
+using namespace std;
+
+namespace WebCore {
+
+auto_ptr<CrossThreadHTTPHeaderMapData> HTTPHeaderMap::copyData() const
+{
+ auto_ptr<CrossThreadHTTPHeaderMapData> data(new CrossThreadHTTPHeaderMapData());
+ data->reserveCapacity(size());
+
+ HTTPHeaderMap::const_iterator end_it = end();
+ for (HTTPHeaderMap::const_iterator it = begin(); it != end_it; ++it) {
+ data->append(make_pair(it->first.string().copy(), it->second.copy()));
+ }
+ return data;
+}
+
+void HTTPHeaderMap::adopt(auto_ptr<CrossThreadHTTPHeaderMapData> data)
+{
+ clear();
+ size_t dataSize = data->size();
+ for (size_t index = 0; index < dataSize; ++index) {
+ pair<String, String>& header = (*data)[index];
+ set(header.first, header.second);
+ }
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/network/HTTPHeaderMap.h b/WebCore/platform/network/HTTPHeaderMap.h
index dc204cb..6da1b90 100644
--- a/WebCore/platform/network/HTTPHeaderMap.h
+++ b/WebCore/platform/network/HTTPHeaderMap.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 Apple Computer, 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
@@ -26,12 +27,25 @@
#ifndef HTTPHeaderMap_h
#define HTTPHeaderMap_h
+#include "AtomicString.h"
+#include "AtomicStringHash.h"
#include "StringHash.h"
+#include <memory>
+#include <utility>
#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
namespace WebCore {
- typedef HashMap<String, String, CaseFoldingHash> HTTPHeaderMap;
+ typedef Vector<std::pair<String, String> > CrossThreadHTTPHeaderMapData;
+
+ class HTTPHeaderMap : public HashMap<AtomicString, String, CaseFoldingHash> {
+ public:
+ // Gets a copy of the data suitable for passing to another thread.
+ std::auto_ptr<CrossThreadHTTPHeaderMapData> copyData() const;
+
+ void adopt(std::auto_ptr<CrossThreadHTTPHeaderMapData>);
+ };
} // namespace WebCore
diff --git a/WebCore/platform/network/NetworkStateNotifier.cpp b/WebCore/platform/network/NetworkStateNotifier.cpp
index d39fc30..7638478 100644
--- a/WebCore/platform/network/NetworkStateNotifier.cpp
+++ b/WebCore/platform/network/NetworkStateNotifier.cpp
@@ -27,14 +27,16 @@
#include "NetworkStateNotifier.h"
#include <wtf/Assertions.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Threading.h>
namespace WebCore {
NetworkStateNotifier& networkStateNotifier()
{
- static NetworkStateNotifier networkStateNotifier;
+ AtomicallyInitializedStatic(NetworkStateNotifier*, networkStateNotifier = new NetworkStateNotifier);
- return networkStateNotifier;
+ return *networkStateNotifier;
}
void NetworkStateNotifier::setNetworkStateChangedFunction(void(*function)())
diff --git a/WebCore/platform/network/NetworkStateNotifier.h b/WebCore/platform/network/NetworkStateNotifier.h
index 53ab4c8..f918be6 100644
--- a/WebCore/platform/network/NetworkStateNotifier.h
+++ b/WebCore/platform/network/NetworkStateNotifier.h
@@ -89,6 +89,7 @@ public:
inline NetworkStateNotifier::NetworkStateNotifier()
: m_isOnLine(true)
+ , m_networkStateChangedFunction(0)
{
}
diff --git a/WebCore/platform/network/ResourceErrorBase.h b/WebCore/platform/network/ResourceErrorBase.h
index b2aac67..4631324 100644
--- a/WebCore/platform/network/ResourceErrorBase.h
+++ b/WebCore/platform/network/ResourceErrorBase.h
@@ -70,7 +70,7 @@ protected:
void platformLazyInit() {}
// The ResourceError subclass may "shadow" this method to compare platform specific fields
- static bool platformCompare(const ResourceError& a, const ResourceError& b) { return true; }
+ static bool platformCompare(const ResourceError&, const ResourceError&) { return true; }
String m_domain;
int m_errorCode;
diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h
index 304bdbe..c981483 100644
--- a/WebCore/platform/network/ResourceHandle.h
+++ b/WebCore/platform/network/ResourceHandle.h
@@ -83,8 +83,6 @@ class ResourceRequest;
class ResourceResponse;
class SchedulePair;
class SharedBuffer;
-class SubresourceLoader;
-class SubresourceLoaderClient;
template <typename T> class Timer;
@@ -109,6 +107,9 @@ public:
~ResourceHandle();
+#if PLATFORM(MAC) || USE(CFNETWORK)
+ bool shouldUseCredentialStorage();
+#endif
#if PLATFORM(MAC) || USE(CFNETWORK) || USE(CURL)
void didReceiveAuthenticationChallenge(const AuthenticationChallenge&);
void receivedCredential(const AuthenticationChallenge&, const Credential&);
diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h
index 08e06a2..3668d88 100644
--- a/WebCore/platform/network/ResourceHandleClient.h
+++ b/WebCore/platform/network/ResourceHandleClient.h
@@ -63,11 +63,11 @@ namespace WebCore {
virtual ~ResourceHandleClient() { }
// request may be modified
- virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse& redirectResponse) { }
- virtual void didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) { }
+ virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse& /*redirectResponse*/) { }
+ virtual void didSendData(ResourceHandle*, unsigned long long /*bytesSent*/, unsigned long long /*totalBytesToBeSent*/) { }
virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&) { }
- virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived) { }
+ virtual void didReceiveData(ResourceHandle*, const char*, int, int /*lengthReceived*/) { }
virtual void didFinishLoading(ResourceHandle*) { }
virtual void didFail(ResourceHandle*, const ResourceError&) { }
virtual void wasBlocked(ResourceHandle*) { }
@@ -75,6 +75,7 @@ namespace WebCore {
virtual void willCacheResponse(ResourceHandle*, CacheStoragePolicy&) { }
+ 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&) { }
diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h
index 0bfa9da..cc90cc8 100644
--- a/WebCore/platform/network/ResourceHandleInternal.h
+++ b/WebCore/platform/network/ResourceHandleInternal.h
@@ -122,6 +122,7 @@ namespace WebCore {
, m_buffer(0)
, m_bufsize(0)
, m_total(0)
+ , m_idleHandler(0)
#endif
#if PLATFORM(QT)
, m_job(0)
@@ -194,6 +195,7 @@ namespace WebCore {
GCancellable* m_cancellable;
char* m_buffer;
gsize m_bufsize, m_total;
+ guint m_idleHandler;
#endif
#if PLATFORM(QT)
#if QT_VERSION < 0x040400
diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp
index 4784bbe..15469a0 100644
--- a/WebCore/platform/network/ResourceRequestBase.cpp
+++ b/WebCore/platform/network/ResourceRequestBase.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003, 2006 Apple Computer, 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
@@ -26,6 +27,8 @@
#include "ResourceRequestBase.h"
#include "ResourceRequest.h"
+using namespace std;
+
namespace WebCore {
inline const ResourceRequest& ResourceRequestBase::asResourceRequest() const
@@ -33,6 +36,57 @@ inline const ResourceRequest& ResourceRequestBase::asResourceRequest() const
return *static_cast<const ResourceRequest*>(this);
}
+auto_ptr<ResourceRequest> ResourceRequestBase::adopt(auto_ptr<CrossThreadResourceRequestData> data)
+{
+ auto_ptr<ResourceRequest> request(new ResourceRequest());
+ request->setURL(data->m_url);
+ request->setCachePolicy(data->m_cachePolicy);
+ request->setTimeoutInterval(data->m_timeoutInterval);
+ request->setMainDocumentURL(data->m_mainDocumentURL);
+ request->setHTTPMethod(data->m_httpMethod);
+
+ request->updateResourceRequest();
+ request->m_httpHeaderFields.adopt(auto_ptr<CrossThreadHTTPHeaderMapData>(data->m_httpHeaders.release()));
+
+ size_t encodingCount = data->m_responseContentDispositionEncodingFallbackArray.size();
+ if (encodingCount > 0) {
+ String encoding1 = data->m_responseContentDispositionEncodingFallbackArray[0];
+ String encoding2;
+ String encoding3;
+ if (encodingCount > 1) {
+ encoding2 = data->m_responseContentDispositionEncodingFallbackArray[1];
+ if (encodingCount > 2)
+ encoding3 = data->m_responseContentDispositionEncodingFallbackArray[2];
+ }
+ ASSERT(encodingCount <= 3);
+ request->setResponseContentDispositionEncodingFallbackArray(encoding1, encoding2, encoding3);
+ }
+ request->setHTTPBody(data->m_httpBody);
+ request->setAllowHTTPCookies(data->m_allowHTTPCookies);
+ return request;
+}
+
+auto_ptr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const
+{
+ auto_ptr<CrossThreadResourceRequestData> data(new CrossThreadResourceRequestData());
+ data->m_url = url().copy();
+ data->m_cachePolicy = cachePolicy();
+ data->m_timeoutInterval = timeoutInterval();
+ data->m_mainDocumentURL = mainDocumentURL().copy();
+ data->m_httpMethod = httpMethod().copy();
+ data->m_httpHeaders.adopt(httpHeaderFields().copyData());
+
+ data->m_responseContentDispositionEncodingFallbackArray.reserveCapacity(m_responseContentDispositionEncodingFallbackArray.size());
+ size_t encodingArraySize = m_responseContentDispositionEncodingFallbackArray.size();
+ for (size_t index = 0; index < encodingArraySize; ++index) {
+ data->m_responseContentDispositionEncodingFallbackArray.append(m_responseContentDispositionEncodingFallbackArray[index].copy());
+ }
+ if (m_httpBody)
+ data->m_httpBody = m_httpBody->deepCopy();
+ data->m_allowHTTPCookies = m_allowHTTPCookies;
+ return data;
+}
+
bool ResourceRequestBase::isEmpty() const
{
updateResourceRequest();
@@ -134,14 +188,14 @@ const HTTPHeaderMap& ResourceRequestBase::httpHeaderFields() const
return m_httpHeaderFields;
}
-String ResourceRequestBase::httpHeaderField(const String& name) const
+String ResourceRequestBase::httpHeaderField(const AtomicString& name) const
{
updateResourceRequest();
return m_httpHeaderFields.get(name);
}
-void ResourceRequestBase::setHTTPHeaderField(const String& name, const String& value)
+void ResourceRequestBase::setHTTPHeaderField(const AtomicString& name, const String& value)
{
updateResourceRequest();
@@ -150,6 +204,21 @@ void ResourceRequestBase::setHTTPHeaderField(const String& name, const String& v
m_platformRequestUpdated = false;
}
+void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2, const String& encoding3)
+{
+ updateResourceRequest();
+
+ m_responseContentDispositionEncodingFallbackArray.clear();
+ if (!encoding1.isNull())
+ m_responseContentDispositionEncodingFallbackArray.append(encoding1);
+ if (!encoding2.isNull())
+ m_responseContentDispositionEncodingFallbackArray.append(encoding2);
+ if (!encoding3.isNull())
+ m_responseContentDispositionEncodingFallbackArray.append(encoding3);
+
+ m_platformRequestUpdated = false;
+}
+
FormData* ResourceRequestBase::httpBody() const
{
updateResourceRequest();
@@ -182,7 +251,7 @@ void ResourceRequestBase::setAllowHTTPCookies(bool allowHTTPCookies)
m_platformRequestUpdated = false;
}
-void ResourceRequestBase::addHTTPHeaderField(const String& name, const String& value)
+void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const String& value)
{
updateResourceRequest();
pair<HTTPHeaderMap::iterator, bool> result = m_httpHeaderFields.add(name, value);
diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h
index 32a3384..0f6bb47 100644
--- a/WebCore/platform/network/ResourceRequestBase.h
+++ b/WebCore/platform/network/ResourceRequestBase.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ * Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,6 +32,9 @@
#include "KURL.h"
#include "HTTPHeaderMap.h"
+#include <memory>
+#include <wtf/OwnPtr.h>
+
namespace WebCore {
enum ResourceRequestCachePolicy {
@@ -43,10 +47,16 @@ namespace WebCore {
const int unspecifiedTimeoutInterval = INT_MAX;
class ResourceRequest;
+ struct CrossThreadResourceRequestData;
// Do not use this type directly. Use ResourceRequest instead.
class ResourceRequestBase {
public:
+ static std::auto_ptr<ResourceRequest> adopt(std::auto_ptr<CrossThreadResourceRequestData>);
+
+ // Gets a copy of the data suitable for passing to another thread.
+ std::auto_ptr<CrossThreadResourceRequestData> copyData() const;
+
bool isNull() const;
bool isEmpty() const;
@@ -66,9 +76,9 @@ namespace WebCore {
void setHTTPMethod(const String& httpMethod);
const HTTPHeaderMap& httpHeaderFields() const;
- String httpHeaderField(const String& name) const;
- void setHTTPHeaderField(const String& name, const String& value);
- void addHTTPHeaderField(const String& name, const String& value);
+ String httpHeaderField(const AtomicString& name) const;
+ void setHTTPHeaderField(const AtomicString& name, const String& value);
+ void addHTTPHeaderField(const AtomicString& name, const String& value);
void addHTTPHeaderFields(const HTTPHeaderMap& headerFields);
String httpContentType() const { return httpHeaderField("Content-Type"); }
@@ -88,6 +98,8 @@ namespace WebCore {
String httpAccept() const { return httpHeaderField("Accept"); }
void setHTTPAccept(const String& httpAccept) { setHTTPHeaderField("Accept", httpAccept); }
+ void setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2 = String(), const String& encoding3 = String());
+
FormData* httpBody() const;
void setHTTPBody(PassRefPtr<FormData> httpBody);
@@ -125,6 +137,7 @@ namespace WebCore {
KURL m_mainDocumentURL;
String m_httpMethod;
HTTPHeaderMap m_httpHeaderFields;
+ Vector<String> m_responseContentDispositionEncodingFallbackArray;
RefPtr<FormData> m_httpBody;
bool m_allowHTTPCookies;
mutable bool m_resourceRequestUpdated;
@@ -139,6 +152,20 @@ namespace WebCore {
bool operator==(const ResourceRequestBase&, const ResourceRequestBase&);
inline bool operator!=(ResourceRequestBase& a, const ResourceRequestBase& b) { return !(a == b); }
+ struct CrossThreadResourceRequestData {
+ KURL m_url;
+
+ ResourceRequestCachePolicy m_cachePolicy;
+ double m_timeoutInterval;
+ KURL m_mainDocumentURL;
+
+ String m_httpMethod;
+ OwnPtr<CrossThreadHTTPHeaderMapData> m_httpHeaders;
+ Vector<String> m_responseContentDispositionEncodingFallbackArray;
+ RefPtr<FormData> m_httpBody;
+ bool m_allowHTTPCookies;
+ };
+
} // namespace WebCore
#endif // ResourceRequestBase_h
diff --git a/WebCore/platform/network/ResourceResponseBase.cpp b/WebCore/platform/network/ResourceResponseBase.cpp
index a9ddc30..f84e97d 100644
--- a/WebCore/platform/network/ResourceResponseBase.cpp
+++ b/WebCore/platform/network/ResourceResponseBase.cpp
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2008 Apple 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
@@ -25,10 +26,58 @@
#include "config.h"
#include "ResourceResponseBase.h"
+
#include "ResourceResponse.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);
+
+auto_ptr<ResourceResponse> ResourceResponseBase::adopt(auto_ptr<CrossThreadResourceResponseData> data)
+{
+ auto_ptr<ResourceResponse> response(new ResourceResponse());
+ response->setUrl(data->m_url);
+ response->setMimeType(data->m_mimeType);
+ response->setExpectedContentLength(data->m_expectedContentLength);
+ response->setTextEncodingName(data->m_textEncodingName);
+ response->setSuggestedFilename(data->m_suggestedFilename);
+
+ response->setHTTPStatusCode(data->m_httpStatusCode);
+ response->setHTTPStatusText(data->m_httpStatusText);
+
+ 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;
+}
+
+auto_ptr<CrossThreadResourceResponseData> ResourceResponseBase::copyData() const
+{
+ auto_ptr<CrossThreadResourceResponseData> data(new CrossThreadResourceResponseData());
+ data->m_url = url().copy();
+ data->m_mimeType = mimeType().copy();
+ data->m_expectedContentLength = expectedContentLength();
+ data->m_textEncodingName = textEncodingName().copy();
+ data->m_suggestedFilename = suggestedFilename().copy();
+ 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;
+}
+
bool ResourceResponseBase::isHTTP() const
{
lazyInit();
@@ -142,17 +191,19 @@ void ResourceResponseBase::setHTTPStatusText(const String& statusText)
m_httpStatusText = statusText;
}
-String ResourceResponseBase::httpHeaderField(const String& name) const
+String ResourceResponseBase::httpHeaderField(const AtomicString& name) const
{
lazyInit();
return m_httpHeaderFields.get(name);
}
-void ResourceResponseBase::setHTTPHeaderField(const String& name, const String& value)
+void ResourceResponseBase::setHTTPHeaderField(const AtomicString& name, const String& value)
{
lazyInit();
+ if (equalIgnoringCase(name, "cache-control"))
+ m_haveParsedCacheControl = false;
m_httpHeaderFields.set(name, value);
}
@@ -160,7 +211,42 @@ const HTTPHeaderMap& ResourceResponseBase::httpHeaderFields() const
{
lazyInit();
- return m_httpHeaderFields;
+ return m_httpHeaderFields;
+}
+
+void ResourceResponseBase::parseCacheControlDirectives() const
+{
+ ASSERT(!m_haveParsedCacheControl);
+
+ lazyInit();
+
+ m_haveParsedCacheControl = 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].second);
+ for (size_t i = 0; i < directiveValues.size(); ++i) {
+ if (equalIgnoringCase(directiveValues[i], "no-cache"))
+ m_cacheControlContainsNoCache = true;
+ else if (equalIgnoringCase(directiveValues[i], "must-revalidate"))
+ m_cacheControlContainsMustRevalidate = true;
+ }
+ }
}
bool ResourceResponseBase::isAttachment() const
@@ -233,4 +319,107 @@ bool ResourceResponseBase::compare(const ResourceResponse& a, const ResourceResp
return ResourceResponse::platformCompare(a, b);
}
+static bool isCacheHeaderSeparator(UChar c)
+{
+ // See RFC 2616, Section 2.2
+ switch (c) {
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case ':':
+ case '\\':
+ case '"':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+ case '{':
+ case '}':
+ case ' ':
+ case '\t':
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool isControlCharacter(UChar c)
+{
+ return c < ' ' || c == 127;
+}
+
+static inline String trimToNextSeparator(const String& str)
+{
+ return str.substring(0, str.find(isCacheHeaderSeparator, 0));
+}
+
+static void parseCacheHeader(const String& header, Vector<pair<String, String> >& result)
+{
+ const String safeHeader = header.removeCharacters(isControlCharacter);
+ unsigned max = safeHeader.length();
+ for (unsigned pos = 0; pos < max; /* pos incremented in loop */) {
+ int nextCommaPosition = safeHeader.find(',', pos);
+ int nextEqualSignPosition = safeHeader.find('=', pos);
+ if (nextEqualSignPosition >= 0 && (nextEqualSignPosition < nextCommaPosition || nextCommaPosition < 0)) {
+ // Get directive name, parse right hand side of equal sign, then add to map
+ String directive = trimToNextSeparator(safeHeader.substring(pos, nextEqualSignPosition - pos).stripWhiteSpace());
+ pos += nextEqualSignPosition - pos + 1;
+
+ String value = safeHeader.substring(pos, max - pos).stripWhiteSpace();
+ if (value[0] == '"') {
+ // The value is a quoted string
+ int nextDoubleQuotePosition = value.find('"', 1);
+ if (nextDoubleQuotePosition >= 0) {
+ // Store the value as a quoted string without quotes
+ result.append(pair<String, String>(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
+ pos += (safeHeader.find('"', pos) - pos) + nextDoubleQuotePosition + 1;
+ // Move past next comma, if there is one
+ int nextCommaPosition2 = safeHeader.find(',', pos);
+ if (nextCommaPosition2 >= 0)
+ pos += nextCommaPosition2 - pos + 1;
+ else
+ return; // Parse error if there is anything left with no comma
+ } else {
+ // Parse error; just use the rest as the value
+ result.append(pair<String, String>(directive, trimToNextSeparator(value.substring(1, value.length() - 1).stripWhiteSpace())));
+ return;
+ }
+ } else {
+ // The value is a token until the next comma
+ int nextCommaPosition2 = value.find(',', 0);
+ if (nextCommaPosition2 >= 0) {
+ // The value is delimited by the next comma
+ result.append(pair<String, String>(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
+ pos += (safeHeader.find(',', pos) - pos) + 1;
+ } else {
+ // The rest is the value; no change to value needed
+ result.append(pair<String, String>(directive, trimToNextSeparator(value)));
+ return;
+ }
+ }
+ } else if (nextCommaPosition >= 0 && (nextCommaPosition < nextEqualSignPosition || nextEqualSignPosition < 0)) {
+ // Add directive to map with empty string as value
+ result.append(pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), ""));
+ pos += nextCommaPosition - pos + 1;
+ } else {
+ // Add last directive to map with empty string as value
+ result.append(pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), ""));
+ return;
+ }
+ }
+}
+
+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 06b0499..abc756e 100644
--- a/WebCore/platform/network/ResourceResponseBase.h
+++ b/WebCore/platform/network/ResourceResponseBase.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2008 Apple 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
@@ -29,13 +30,20 @@
#include "HTTPHeaderMap.h"
#include "KURL.h"
+#include <memory>
+
namespace WebCore {
class ResourceResponse;
+struct CrossThreadResourceResponseData;
// Do not use this class directly, use the class ResponseResponse instead
class ResourceResponseBase {
- public:
+public:
+ static std::auto_ptr<ResourceResponse> adopt(std::auto_ptr<CrossThreadResourceResponseData>);
+
+ // Gets a copy of the data suitable for passing to another thread.
+ std::auto_ptr<CrossThreadResourceResponseData> copyData() const;
bool isNull() const { return m_isNull; }
bool isHTTP() const;
@@ -62,8 +70,8 @@ class ResourceResponseBase {
const String& httpStatusText() const;
void setHTTPStatusText(const String&);
- String httpHeaderField(const String& name) const;
- void setHTTPHeaderField(const String& name, const String& value);
+ String httpHeaderField(const AtomicString& name) const;
+ void setHTTPHeaderField(const AtomicString& name, const String& value);
const HTTPHeaderMap& httpHeaderFields() const;
bool isMultipart() const { return mimeType() == "multipart/x-mixed-replace"; }
@@ -76,15 +84,29 @@ class ResourceResponseBase {
void setLastModifiedDate(time_t);
time_t lastModifiedDate() const;
+ bool cacheControlContainsNoCache() const
+ {
+ if (!m_haveParsedCacheControl)
+ parseCacheControlDirectives();
+ return m_cacheControlContainsMustRevalidate;
+ }
+ bool cacheControlContainsMustRevalidate() const
+ {
+ if (!m_haveParsedCacheControl)
+ parseCacheControlDirectives();
+ return m_cacheControlContainsMustRevalidate;
+ }
+
static bool compare(const ResourceResponse& a, const ResourceResponse& b);
- protected:
+protected:
ResourceResponseBase()
: m_expectedContentLength(0)
, m_httpStatusCode(0)
, m_expirationDate(0)
, m_lastModifiedDate(0)
, m_isNull(true)
+ , m_haveParsedCacheControl(false)
{
}
@@ -98,16 +120,17 @@ class ResourceResponseBase {
, m_expirationDate(0)
, m_lastModifiedDate(0)
, m_isNull(false)
+ , m_haveParsedCacheControl(false)
{
}
void lazyInit() const;
// The ResourceResponse subclass may "shadow" this method to lazily initialize platform specific fields
- void platformLazyInit() {}
+ void platformLazyInit() { }
// The ResourceResponse subclass may "shadow" this method to compare platform specific fields
- static bool platformCompare(const ResourceResponse& a, const ResourceResponse& b) { return true; }
+ static bool platformCompare(const ResourceResponse&, const ResourceResponse&) { return true; }
KURL m_url;
String m_mimeType;
@@ -119,13 +142,35 @@ class ResourceResponseBase {
HTTPHeaderMap m_httpHeaderFields;
time_t m_expirationDate;
time_t m_lastModifiedDate;
- bool m_isNull;
+ bool m_isNull : 1;
+
+private:
+ void parseCacheControlDirectives() const;
+ mutable bool m_haveParsedCacheControl : 1;
+ mutable bool m_cacheControlContainsMustRevalidate : 1;
+ mutable bool m_cacheControlContainsNoCache : 1;
};
inline bool operator==(const ResourceResponse& a, const ResourceResponse& b) { return ResourceResponseBase::compare(a, b); }
inline bool operator!=(const ResourceResponse& a, const ResourceResponse& b) { return !(a == b); }
+struct CrossThreadResourceResponseData {
+ KURL m_url;
+ String m_mimeType;
+ long long m_expectedContentLength;
+ String m_textEncodingName;
+ String m_suggestedFilename;
+ 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
#endif // ResourceResponseBase_h
diff --git a/WebCore/platform/network/cf/DNSCFNet.cpp b/WebCore/platform/network/cf/DNSCFNet.cpp
index e571494..bf21ab1 100644
--- a/WebCore/platform/network/cf/DNSCFNet.cpp
+++ b/WebCore/platform/network/cf/DNSCFNet.cpp
@@ -30,7 +30,7 @@
namespace WebCore {
-void prefetchDNS(const String& hostname)
+void prefetchDNS(const String&)
{
notImplemented();
}
diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
index fa7947f..a4000a3 100644
--- a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
@@ -53,6 +53,51 @@
namespace WebCore {
+static HMODULE findCFNetworkModule()
+{
+ if (HMODULE module = GetModuleHandleA("CFNetwork"))
+ return module;
+ return GetModuleHandleA("CFNetwork_debug");
+}
+
+static DWORD cfNetworkVersion()
+{
+ HMODULE cfNetworkModule = findCFNetworkModule();
+ WCHAR filename[MAX_PATH];
+ GetModuleFileName(cfNetworkModule, filename, MAX_PATH);
+ DWORD handle;
+ DWORD versionInfoSize = GetFileVersionInfoSize(filename, &handle);
+ Vector<BYTE> versionInfo(versionInfoSize);
+ GetFileVersionInfo(filename, handle, versionInfoSize, versionInfo.data());
+ VS_FIXEDFILEINFO* fixedFileInfo;
+ UINT fixedFileInfoLength;
+ VerQueryValue(versionInfo.data(), TEXT("\\"), reinterpret_cast<LPVOID*>(&fixedFileInfo), &fixedFileInfoLength);
+ return fixedFileInfo->dwProductVersionMS;
+}
+
+static CFIndex highestSupportedCFURLConnectionClientVersion()
+{
+ const DWORD firstCFNetworkVersionWithConnectionClientV2 = 0x000101a8; // 1.424
+ const DWORD firstCFNetworkVersionWithConnectionClientV3 = 0x000101ad; // 1.429
+
+#ifndef _CFURLConnectionClientV2Present
+ return 1;
+#else
+
+ DWORD version = cfNetworkVersion();
+ if (version < firstCFNetworkVersionWithConnectionClientV2)
+ return 1;
+#ifndef _CFURLConnectionClientV3Present
+ return 2;
+#else
+
+ if (version < firstCFNetworkVersionWithConnectionClientV3)
+ return 2;
+ return 3;
+#endif // _CFURLConnectionClientV3Present
+#endif // _CFURLConnectionClientV2Present
+}
+
static HashSet<String>& allowsAnyHTTPSCertificateHosts()
{
static HashSet<String> hosts;
@@ -109,6 +154,30 @@ void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLen
handle->client()->didReceiveData(handle, (const char*)bytes, length, originalLength);
}
+#ifdef _CFURLConnectionClientV2Present
+static void didSendBodyData(CFURLConnectionRef conn, CFIndex bytesWritten, CFIndex totalBytesWritten, CFIndex totalBytesExpectedToWrite, const void *clientInfo)
+{
+ ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ if (!handle || !handle->client())
+ return;
+ handle->client()->didSendData(handle, totalBytesWritten, totalBytesExpectedToWrite);
+}
+#endif
+
+#ifdef _CFURLConnectionClientV3Present
+static Boolean shouldUseCredentialStorageCallback(CFURLConnectionRef conn, const void* clientInfo)
+{
+ ResourceHandle* handle = const_cast<ResourceHandle*>(static_cast<const ResourceHandle*>(clientInfo));
+
+ LOG(Network, "CFNet - shouldUseCredentialStorage(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data());
+
+ if (!handle)
+ return false;
+
+ return handle->shouldUseCredentialStorage();
+}
+#endif
+
void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo)
{
ResourceHandle* handle = (ResourceHandle*)clientInfo;
@@ -279,11 +348,20 @@ bool ResourceHandle::start(Frame* frame)
RetainPtr<CFURLRequestRef> request(AdoptCF, makeFinalRequest(d->m_request, d->m_shouldContentSniff));
- // CFURLConnection Callback API currently at version 1
- const int CFURLConnectionClientVersion = 1;
- CFURLConnectionClient client = {CFURLConnectionClientVersion, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge};
-
- d->m_connection.adoptCF(CFURLConnectionCreate(0, request.get(), &client));
+ static CFIndex clientVersion = highestSupportedCFURLConnectionClientVersion();
+ CFURLConnectionClient* client;
+#if defined(_CFURLConnectionClientV3Present)
+ CFURLConnectionClient_V3 client_V3 = {clientVersion, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0};
+ client = reinterpret_cast<CFURLConnectionClient*>(&client_V3);
+#elif defined(_CFURLConnectionClientV2Present)
+ CFURLConnectionClient_V2 client_V2 = {clientVersion, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData};
+ client = reinterpret_cast<CFURLConnectionClient*>(&client_V2);
+#else
+ CFURLConnectionClient client_V1 = {1, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge};
+ client = &client_V1;
+#endif
+
+ d->m_connection.adoptCF(CFURLConnectionCreate(0, request.get(), client));
CFURLConnectionScheduleWithCurrentMessageQueue(d->m_connection.get());
CFURLConnectionScheduleDownloadWithRunLoop(d->m_connection.get(), loaderRunLoop(), kCFRunLoopDefaultMode);
@@ -313,6 +391,15 @@ bool ResourceHandle::supportsBufferedData()
return false;
}
+bool ResourceHandle::shouldUseCredentialStorage()
+{
+ LOG(Network, "CFNet - shouldUseCredentialStorage()");
+ if (client())
+ return client()->shouldUseCredentialStorage(this);
+
+ return false;
+}
+
void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
{
LOG(Network, "CFNet - didReceiveAuthenticationChallenge()");
diff --git a/WebCore/platform/network/cf/ResourceRequestCFNet.cpp b/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
index b73df13..df6bbf9 100644
--- a/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,6 +33,41 @@
namespace WebCore {
+typedef void (*CFURLRequestSetContentDispositionEncodingFallbackArrayFunction)(CFMutableURLRequestRef, CFArrayRef);
+typedef CFArrayRef (*CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction)(CFURLRequestRef);
+
+static HMODULE findCFNetworkModule()
+{
+ if (HMODULE module = GetModuleHandleA("CFNetwork"))
+ return module;
+ return GetModuleHandleA("CFNetwork_debug");
+}
+
+static CFURLRequestSetContentDispositionEncodingFallbackArrayFunction findCFURLRequestSetContentDispositionEncodingFallbackArrayFunction()
+{
+ return reinterpret_cast<CFURLRequestSetContentDispositionEncodingFallbackArrayFunction>(GetProcAddress(findCFNetworkModule(), "_CFURLRequestSetContentDispositionEncodingFallbackArray"));
+}
+
+static CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction findCFURLRequestCopyContentDispositionEncodingFallbackArrayFunction()
+{
+ return reinterpret_cast<CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction>(GetProcAddress(findCFNetworkModule(), "_CFURLRequestCopyContentDispositionEncodingFallbackArray"));
+}
+
+static void setContentDispositionEncodingFallbackArray(CFMutableURLRequestRef request, CFArrayRef fallbackArray)
+{
+ static CFURLRequestSetContentDispositionEncodingFallbackArrayFunction function = findCFURLRequestSetContentDispositionEncodingFallbackArrayFunction();
+ if (function)
+ function(request, fallbackArray);
+}
+
+static CFArrayRef copyContentDispositionEncodingFallbackArray(CFURLRequestRef request)
+{
+ static CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction function = findCFURLRequestCopyContentDispositionEncodingFallbackArrayFunction();
+ if (!function)
+ return 0;
+ return function(request);
+}
+
CFURLRequestRef ResourceRequest::cfURLRequest() const
{
updatePlatformRequest();
@@ -76,6 +111,16 @@ void ResourceRequest::doUpdatePlatformRequest()
WebCore::setHTTPBody(cfRequest, httpBody());
CFURLRequestSetShouldHandleHTTPCookies(cfRequest, allowHTTPCookies());
+ unsigned fallbackCount = m_responseContentDispositionEncodingFallbackArray.size();
+ RetainPtr<CFMutableArrayRef> encodingFallbacks(AdoptCF, CFArrayCreateMutable(kCFAllocatorDefault, fallbackCount, 0));
+ for (unsigned i = 0; i != fallbackCount; ++i) {
+ RetainPtr<CFStringRef> encodingName(AdoptCF, m_responseContentDispositionEncodingFallbackArray[i].createCFString());
+ CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding(encodingName.get());
+ if (encoding != kCFStringEncodingInvalidId)
+ CFArrayAppendValue(encodingFallbacks.get(), reinterpret_cast<const void*>(encoding));
+ }
+ setContentDispositionEncodingFallbackArray(cfRequest, encodingFallbacks.get());
+
if (m_cfRequest) {
RetainPtr<CFHTTPCookieStorageRef> cookieStorage(AdoptCF, CFURLRequestCopyHTTPCookieStorage(m_cfRequest.get()));
if (cookieStorage)
@@ -110,6 +155,17 @@ void ResourceRequest::doUpdateResourceRequest()
CFRelease(headers);
}
+ m_responseContentDispositionEncodingFallbackArray.clear();
+ RetainPtr<CFArrayRef> encodingFallbacks(AdoptCF, copyContentDispositionEncodingFallbackArray(m_cfRequest.get()));
+ if (encodingFallbacks) {
+ CFIndex count = CFArrayGetCount(encodingFallbacks.get());
+ 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_httpBody = httpBodyFromRequest(m_cfRequest.get());
}
diff --git a/WebCore/platform/network/chromium/AuthenticationChallenge.h b/WebCore/platform/network/chromium/AuthenticationChallenge.h
new file mode 100644
index 0000000..cd1b430
--- /dev/null
+++ b/WebCore/platform/network/chromium/AuthenticationChallenge.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * 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 AuthenticationChallenge_h
+#define AuthenticationChallenge_h
+
+#include "AuthenticationChallengeBase.h"
+#include "ResourceHandle.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+ class ResourceHandle;
+
+ class AuthenticationChallenge : public AuthenticationChallengeBase {
+ public:
+ AuthenticationChallenge() {}
+ AuthenticationChallenge(const ProtectionSpace&, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse&, const ResourceError&);
+
+ ResourceHandle* sourceHandle() const { return m_sourceHandle.get(); }
+
+ private:
+ friend class AuthenticationChallengeBase;
+ static bool platformCompare(const AuthenticationChallenge&, const AuthenticationChallenge&);
+
+ RefPtr<ResourceHandle> m_sourceHandle;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/network/chromium/AuthenticationChallengeChromium.cpp b/WebCore/platform/network/chromium/AuthenticationChallengeChromium.cpp
new file mode 100644
index 0000000..3c13b39
--- /dev/null
+++ b/WebCore/platform/network/chromium/AuthenticationChallengeChromium.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "AuthenticationChallenge.h"
+
+namespace WebCore {
+
+bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge&, const AuthenticationChallenge&)
+{
+ return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/network/chromium/CookieJarChromium.cpp b/WebCore/platform/network/chromium/CookieJarChromium.cpp
new file mode 100644
index 0000000..50cab3b
--- /dev/null
+++ b/WebCore/platform/network/chromium/CookieJarChromium.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CookieJar.h"
+
+#include "ChromiumBridge.h"
+#include "Document.h"
+
+namespace WebCore {
+
+void setCookies(Document* document, const KURL& url, const KURL& policyURL, 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);
+}
+
+String cookies(const Document* document, const KURL& url)
+{
+ return ChromiumBridge::cookies(url, document->policyBaseURL());
+}
+
+bool cookiesEnabled(const Document*)
+{
+ // FIXME: For now just assume cookies are always on.
+ return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/network/chromium/DNSChromium.cpp b/WebCore/platform/network/chromium/DNSChromium.cpp
new file mode 100644
index 0000000..4da29e1
--- /dev/null
+++ b/WebCore/platform/network/chromium/DNSChromium.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 Collin Jackson <collinj@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DNS.h"
+
+#include "ChromiumBridge.h"
+
+namespace WebCore {
+
+void prefetchDNS(const String& hostname)
+{
+ ChromiumBridge::prefetchDNS(hostname);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/network/chromium/NetworkStateNotifierChromium.cpp b/WebCore/platform/network/chromium/NetworkStateNotifierChromium.cpp
new file mode 100644
index 0000000..3b28fbd
--- /dev/null
+++ b/WebCore/platform/network/chromium/NetworkStateNotifierChromium.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "NetworkStateNotifier.h"
+
+namespace WebCore {
+
+// Chromium doesn't currently support network state notifications. This causes
+// an extra DLL to get loaded into the renderer which can slow things down a
+// bit. We may want an alternate design.
+
+void NetworkStateNotifier::updateState()
+{
+}
+
+NetworkStateNotifier::NetworkStateNotifier()
+ : m_isOnLine(true)
+ , m_networkStateChangedFunction(0)
+{
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/network/chromium/NetworkStateNotifierPrivate.h b/WebCore/platform/network/chromium/NetworkStateNotifierPrivate.h
new file mode 100644
index 0000000..7628d59
--- /dev/null
+++ b/WebCore/platform/network/chromium/NetworkStateNotifierPrivate.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NetworkStateNotifierPrivate_h
+#define NetworkStateNotifierPrivate_h
+
+namespace WebCore {
+
+ struct NetworkStateNotifierPrivate {};
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/network/chromium/ResourceError.h b/WebCore/platform/network/chromium/ResourceError.h
new file mode 100644
index 0000000..a1fbe11
--- /dev/null
+++ b/WebCore/platform/network/chromium/ResourceError.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * 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 ResourceError_h
+#define ResourceError_h
+
+#include "ResourceErrorBase.h"
+
+namespace WebCore {
+
+ class ResourceError : public ResourceErrorBase {
+ public:
+ ResourceError()
+ {
+ }
+
+ ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription)
+ : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription)
+ {
+ }
+
+ private:
+ friend class ResourceErrorBase;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/network/chromium/ResourceRequest.h b/WebCore/platform/network/chromium/ResourceRequest.h
new file mode 100644
index 0000000..76b8b99
--- /dev/null
+++ b/WebCore/platform/network/chromium/ResourceRequest.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * 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 ResourceRequest_h
+#define ResourceRequest_h
+
+#include "CString.h"
+#include "ResourceRequestBase.h"
+
+namespace WebCore {
+
+ class Frame;
+
+ class ResourceRequest : public ResourceRequestBase {
+ public:
+ enum TargetType {
+ TargetIsMainFrame,
+ TargetIsSubFrame,
+ TargetIsSubResource,
+ TargetIsObject,
+ TargetIsMedia
+ };
+
+ ResourceRequest(const String& url)
+ : ResourceRequestBase(KURL(url), UseProtocolCachePolicy)
+ , m_frame(0)
+ , m_originPid(0)
+ , m_targetType(TargetIsSubResource)
+ {
+ }
+
+ ResourceRequest(const KURL& url, const CString& securityInfo)
+ : ResourceRequestBase(url, UseProtocolCachePolicy)
+ , m_frame(0)
+ , m_originPid(0)
+ , m_targetType(TargetIsSubResource)
+ , m_securityInfo(securityInfo)
+ {
+ }
+
+ ResourceRequest(const KURL& url)
+ : ResourceRequestBase(url, UseProtocolCachePolicy)
+ , m_frame(0)
+ , m_originPid(0)
+ , m_targetType(TargetIsSubResource)
+ {
+ }
+
+ ResourceRequest(const KURL& url, const String& referrer, ResourceRequestCachePolicy policy = UseProtocolCachePolicy)
+ : ResourceRequestBase(url, policy)
+ , m_frame(0)
+ , m_originPid(0)
+ , m_targetType(TargetIsSubResource)
+ {
+ setHTTPReferrer(referrer);
+ }
+
+ ResourceRequest()
+ : ResourceRequestBase(KURL(), UseProtocolCachePolicy)
+ , m_frame(0)
+ , m_originPid(0)
+ , m_targetType(TargetIsSubResource)
+ {
+ }
+
+ // Provides context for the resource request.
+ Frame* frame() const { return m_frame; }
+ void setFrame(Frame* frame) { m_frame = frame; }
+
+ // What this request is for.
+ void setTargetType(TargetType type) { m_targetType = type; }
+ TargetType targetType() const { return m_targetType; }
+
+ // The origin pid is 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 view process).
+ int originPid() const { return m_originPid; }
+ void setOriginPid(int originPid) { m_originPid = originPid; }
+
+ // 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
+ // connection for request (typically when showing error page, so the
+ // error page has the errors of the page that actually failed). Empty
+ // string if not a secure connection.
+ CString securityInfo() const { return m_securityInfo; }
+ void setSecurityInfo(const CString& value) { m_securityInfo = value; }
+
+ private:
+ friend class ResourceRequestBase;
+
+ void doUpdatePlatformRequest() {}
+ void doUpdateResourceRequest() {}
+
+ Frame* m_frame;
+ int m_originPid;
+ TargetType m_targetType;
+ CString m_securityInfo;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/network/chromium/ResourceResponse.h b/WebCore/platform/network/chromium/ResourceResponse.h
new file mode 100644
index 0000000..256df74
--- /dev/null
+++ b/WebCore/platform/network/chromium/ResourceResponse.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * 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 ResourceResponse_h
+#define ResourceResponse_h
+
+#include "CString.h"
+#include "NotImplemented.h"
+#include "ResourceResponseBase.h"
+
+namespace WebCore {
+
+ class ResourceResponse : public ResourceResponseBase {
+ public:
+ ResourceResponse()
+ : m_isContentFiltered(false)
+ {
+ }
+
+ 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)
+ {
+ }
+
+ const CString& getSecurityInfo() const { return m_securityInfo; }
+ void setSecurityInfo(const CString& securityInfo)
+ {
+ m_securityInfo = securityInfo;
+ }
+
+ bool isContentFiltered() const { return m_isContentFiltered; }
+ void setIsContentFiltered(bool isContentFiltered)
+ {
+ m_isContentFiltered = isContentFiltered;
+ }
+
+ private:
+ friend class ResourceResponseBase;
+
+ // An opaque value that contains some information regarding the security of
+ // the connection for this request, such as SSL connection info (empty
+ // string if not over HTTPS).
+ CString m_securityInfo;
+
+ void doUpdateResourceResponse()
+ {
+ notImplemented();
+ }
+
+ // Whether the contents for this response has been altered/blocked (usually
+ // for security reasons.
+ bool m_isContentFiltered;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/network/curl/ResourceHandleCurl.cpp b/WebCore/platform/network/curl/ResourceHandleCurl.cpp
index bbc31d4..ca24ec5 100644
--- a/WebCore/platform/network/curl/ResourceHandleCurl.cpp
+++ b/WebCore/platform/network/curl/ResourceHandleCurl.cpp
@@ -104,7 +104,6 @@ ResourceHandle::~ResourceHandle()
bool ResourceHandle::start(Frame* frame)
{
ASSERT(frame);
- ref();
ResourceHandleManager::sharedInstance()->add(this);
return true;
}
diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp
index b022913..6a44233 100644
--- a/WebCore/platform/network/curl/ResourceHandleManager.cpp
+++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp
@@ -43,6 +43,7 @@
#include "TextEncoding.h"
#include <errno.h>
+#include <stdio.h>
#include <wtf/Vector.h>
#if PLATFORM(GTK)
@@ -263,8 +264,7 @@ void ResourceHandleManager::downloadTimerCallback(Timer<ResourceHandleManager>*
timeout.tv_sec = 0;
timeout.tv_usec = selectTimeoutMS * 1000; // select waits microseconds
- // Temporarily disable timers since signals may interrupt select(), raising EINTR errors on some platforms
- setDeferringTimers(true);
+ // Retry 'select' if it was interrupted by a process signal.
int rc = 0;
do {
FD_ZERO(&fdread);
@@ -277,7 +277,6 @@ void ResourceHandleManager::downloadTimerCallback(Timer<ResourceHandleManager>*
if (maxfd >= 0)
rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
} while (rc == -1 && errno == EINTR);
- setDeferringTimers(false);
if (-1 == rc) {
#ifndef NDEBUG
@@ -324,7 +323,7 @@ void ResourceHandleManager::downloadTimerCallback(Timer<ResourceHandleManager>*
#ifndef NDEBUG
char* url = 0;
curl_easy_getinfo(d->m_handle, CURLINFO_EFFECTIVE_URL, &url);
- printf("Curl ERROR for url='%s', error: '%s'\n", url, curl_easy_strerror(msg->data.result));
+ 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());
@@ -349,6 +348,7 @@ void ResourceHandleManager::removeFromCurl(ResourceHandle* job)
curl_multi_remove_handle(m_curlMultiHandle, d->m_handle);
curl_easy_cleanup(d->m_handle);
d->m_handle = 0;
+ job->deref();
}
void ResourceHandleManager::setupPUT(ResourceHandle*, struct curl_slist**)
@@ -362,12 +362,14 @@ void ResourceHandleManager::setupPUT(ResourceHandle*, struct curl_slist**)
void ResourceHandleManager::setupPOST(ResourceHandle* job, struct curl_slist** headers)
{
ResourceHandleInternal* d = job->getInternal();
- Vector<FormDataElement> elements;
- // Fix crash when httpBody is null (see bug #16906).
- if (job->request().httpBody())
- elements = job->request().httpBody()->elements();
- size_t numElements = elements.size();
+ curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE);
+ curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, 0);
+
+ if (!job->request().httpBody())
+ return;
+ Vector<FormDataElement> elements = job->request().httpBody()->elements();
+ size_t numElements = elements.size();
if (!numElements)
return;
@@ -375,7 +377,6 @@ void ResourceHandleManager::setupPOST(ResourceHandle* job, struct curl_slist** h
if (numElements == 1) {
job->request().httpBody()->flatten(d->m_postBytes);
if (d->m_postBytes.size() != 0) {
- curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE);
curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, d->m_postBytes.size());
curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDS, d->m_postBytes.data());
}
@@ -422,8 +423,6 @@ void ResourceHandleManager::setupPOST(ResourceHandle* job, struct curl_slist** h
size += elements[i].m_data.size();
}
- curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE);
-
// cURL guesses that we want chunked encoding as long as we specify the header
if (chunkedTransfer)
*headers = curl_slist_append(*headers, "Transfer-Encoding: chunked");
@@ -442,6 +441,7 @@ void ResourceHandleManager::add(ResourceHandle* job)
{
// we can be called from within curl, so to avoid re-entrancy issues
// schedule this job to be added the next time we enter curl download loop
+ job->ref();
m_resourceHandleList.append(job);
if (!m_downloadTimer.isActive())
m_downloadTimer.startOneShot(pollTimeSeconds);
@@ -453,6 +453,7 @@ bool ResourceHandleManager::removeScheduledJob(ResourceHandle* job)
for (int i = 0; i < size; i++) {
if (job == m_resourceHandleList[i]) {
m_resourceHandleList.remove(i);
+ job->deref();
return true;
}
}
@@ -585,7 +586,7 @@ void ResourceHandleManager::startJob(ResourceHandle* job)
// timeout will occur and do curl_multi_perform
if (ret && ret != CURLM_CALL_MULTI_PERFORM) {
#ifndef NDEBUG
- printf("Error %d starting job %s\n", ret, encodeWithURLEscapeSequences(job->request().url().string()).latin1().data());
+ fprintf(stderr, "Error %d starting job %s\n", ret, encodeWithURLEscapeSequences(job->request().url().string()).latin1().data());
#endif
job->cancel();
return;
diff --git a/WebCore/platform/network/mac/FormDataStreamMac.mm b/WebCore/platform/network/mac/FormDataStreamMac.mm
index 3ef224d..b618949 100644
--- a/WebCore/platform/network/mac/FormDataStreamMac.mm
+++ b/WebCore/platform/network/mac/FormDataStreamMac.mm
@@ -42,6 +42,7 @@
#import <wtf/Assertions.h>
#import <wtf/HashMap.h>
#import <wtf/MainThread.h>
+#import <wtf/StdLibExtras.h>
#import <wtf/Threading.h>
namespace WebCore {
@@ -49,14 +50,14 @@ namespace WebCore {
typedef HashMap<CFReadStreamRef, RefPtr<FormData> > StreamFormDataMap;
static StreamFormDataMap& getStreamFormDataMap()
{
- static StreamFormDataMap streamFormDataMap;
+ DEFINE_STATIC_LOCAL(StreamFormDataMap, streamFormDataMap, ());
return streamFormDataMap;
}
typedef HashMap<CFReadStreamRef, RefPtr<ResourceHandle> > StreamResourceHandleMap;
static StreamResourceHandleMap& getStreamResourceHandleMap()
{
- static StreamResourceHandleMap streamResourceHandleMap;
+ DEFINE_STATIC_LOCAL(StreamResourceHandleMap, streamResourceHandleMap, ());
return streamResourceHandleMap;
}
@@ -222,7 +223,7 @@ static void formFinalize(CFReadStreamRef stream, void* context)
delete form;
}
-static Boolean formOpen(CFReadStreamRef stream, CFStreamError* error, Boolean* openComplete, void* context)
+static Boolean formOpen(CFReadStreamRef, CFStreamError* error, Boolean* openComplete, void* context)
{
FormStreamFields* form = static_cast<FormStreamFields*>(context);
@@ -278,14 +279,14 @@ static Boolean formCanRead(CFReadStreamRef stream, void* context)
return CFReadStreamHasBytesAvailable(form->currentStream);
}
-static void formClose(CFReadStreamRef stream, void* context)
+static void formClose(CFReadStreamRef, void* context)
{
FormStreamFields* form = static_cast<FormStreamFields*>(context);
closeCurrentStream(form);
}
-static void formSchedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
+static void formSchedule(CFReadStreamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
{
FormStreamFields* form = static_cast<FormStreamFields*>(context);
@@ -294,7 +295,7 @@ static void formSchedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringR
form->scheduledRunLoopPairs.add(SchedulePair::create(runLoop, runLoopMode));
}
-static void formUnschedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
+static void formUnschedule(CFReadStreamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
{
FormStreamFields* form = static_cast<FormStreamFields*>(context);
diff --git a/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp b/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp
index 6e0b70d..c0918a4 100644
--- a/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp
+++ b/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp
@@ -28,6 +28,11 @@
#include <SystemConfiguration/SystemConfiguration.h>
+#ifdef BUILDING_ON_TIGER
+// This function is available on Tiger, but not declared in the CFRunLoop.h header on Tiger.
+extern "C" CFRunLoopRef CFRunLoopGetMain();
+#endif
+
namespace WebCore {
static const double StateChangeTimerInterval = 2.0;
@@ -71,7 +76,7 @@ void NetworkStateNotifier::updateState()
}
}
-void NetworkStateNotifier::dynamicStoreCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
+void NetworkStateNotifier::dynamicStoreCallback(SCDynamicStoreRef, CFArrayRef, void* info)
{
NetworkStateNotifier* notifier = static_cast<NetworkStateNotifier*>(info);
@@ -95,6 +100,7 @@ void NetworkStateNotifier::networkStateChangeTimerFired(Timer<NetworkStateNotifi
NetworkStateNotifier::NetworkStateNotifier()
: m_isOnLine(false)
+ , m_networkStateChangedFunction(0)
, m_networkStateChangeTimer(this, &NetworkStateNotifier::networkStateChangeTimerFired)
{
SCDynamicStoreContext context = { 0, this, 0, 0, 0 };
@@ -107,7 +113,7 @@ NetworkStateNotifier::NetworkStateNotifier()
if (!configSource)
return;
- CFRunLoopAddSource(CFRunLoopGetCurrent(), configSource.get(), kCFRunLoopCommonModes);
+ CFRunLoopAddSource(CFRunLoopGetMain(), configSource.get(), kCFRunLoopCommonModes);
RetainPtr<CFMutableArrayRef> keys(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
RetainPtr<CFMutableArrayRef> patterns(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm
index b4c5ddf..9bc322d 100644
--- a/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2004, 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,7 +24,6 @@
*/
#import "config.h"
-#import "ResourceHandle.h"
#import "ResourceHandleInternal.h"
#import "AuthenticationChallenge.h"
@@ -41,6 +40,7 @@
#import "SharedBuffer.h"
#import "SubresourceLoader.h"
#import "WebCoreSystemInterface.h"
+#import <wtf/UnusedParam.h>
#ifdef BUILDING_ON_TIGER
typedef int NSInteger;
@@ -64,6 +64,7 @@ using namespace WebCore;
@end
#ifndef BUILDING_ON_TIGER
+
@interface WebCoreSynchronousLoader : NSObject {
NSURL *m_url;
NSURLResponse *m_response;
@@ -75,6 +76,7 @@ using namespace WebCore;
@end
static NSString *WebCoreSynchronousLoaderRunLoopMode = @"WebCoreSynchronousLoaderRunLoopMode";
+
#endif
namespace WebCore {
@@ -116,12 +118,7 @@ ResourceHandle::~ResourceHandle()
static const double MaxFoundationVersionWithoutdidSendBodyDataDelegate = 677.21;
bool ResourceHandle::didSendBodyDataDelegateExists()
{
-// FIXME: Refine this check as the delegate becomes more widely available.
-#ifdef BUILDING_ON_LEOPARD
return NSFoundationVersionNumber > MaxFoundationVersionWithoutdidSendBodyDataDelegate;
-#else
- return false;
-#endif
}
bool ResourceHandle::start(Frame* frame)
@@ -140,6 +137,7 @@ bool ResourceHandle::start(Frame* frame)
#ifndef NDEBUG
isInitializingConnection = YES;
#endif
+
id delegate;
if (d->m_mightDownloadFromHandle) {
@@ -239,6 +237,8 @@ void ResourceHandle::schedule(SchedulePair* pair)
[d->m_connection.get() start];
d->m_startWhenScheduled = false;
}
+#else
+ UNUSED_PARAM(pair);
#endif
}
@@ -247,6 +247,8 @@ void ResourceHandle::unschedule(SchedulePair* pair)
#ifndef BUILDING_ON_TIGER
if (NSRunLoop *runLoop = pair->nsRunLoop())
[d->m_connection.get() unscheduleFromRunLoop:runLoop forMode:(NSString *)pair->mode()];
+#else
+ UNUSED_PARAM(pair);
#endif
}
@@ -363,6 +365,14 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, R
error = nsError;
}
+bool ResourceHandle::shouldUseCredentialStorage()
+{
+ if (client())
+ return client()->shouldUseCredentialStorage(this);
+
+ return false;
+}
+
void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
{
ASSERT(!d->m_currentMacChallenge);
@@ -388,7 +398,7 @@ void ResourceHandle::didCancelAuthenticationChallenge(const AuthenticationChalle
ASSERT(d->m_currentWebChallenge == challenge);
if (client())
- client()->didCancelAuthenticationChallenge(this, d->m_currentWebChallenge);
+ client()->didCancelAuthenticationChallenge(this, challenge);
}
void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential)
@@ -448,8 +458,10 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
m_handle = 0;
}
-- (NSURLRequest *)connection:(NSURLConnection *)con willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse
+- (NSURLRequest *)connection:(NSURLConnection *)unusedConnection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse
{
+ UNUSED_PARAM(unusedConnection);
+
// the willSendRequest call may cancel this load, in which case self could be deallocated
RetainPtr<WebCoreResourceHandleAsDelegate> protect(self);
@@ -483,8 +495,21 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
return request.nsURLRequest();
}
-- (void)connection:(NSURLConnection *)con didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)unusedConnection
+{
+ UNUSED_PARAM(unusedConnection);
+
+ if (!m_handle)
+ return NO;
+
+ CallbackGuard guard;
+ return m_handle->shouldUseCredentialStorage();
+}
+
+- (void)connection:(NSURLConnection *)unusedConnection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
+ UNUSED_PARAM(unusedConnection);
+
#ifndef BUILDING_ON_TIGER
if ([challenge previousFailureCount] == 0) {
NSString *user = [m_url user];
@@ -507,24 +532,30 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
m_handle->didReceiveAuthenticationChallenge(core(challenge));
}
-- (void)connection:(NSURLConnection *)con didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+- (void)connection:(NSURLConnection *)unusedConnection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
+ UNUSED_PARAM(unusedConnection);
+
if (!m_handle)
return;
CallbackGuard guard;
m_handle->didCancelAuthenticationChallenge(core(challenge));
}
-- (void)connection:(NSURLConnection *)con didReceiveResponse:(NSURLResponse *)r
+- (void)connection:(NSURLConnection *)unusedConnection didReceiveResponse:(NSURLResponse *)r
{
+ UNUSED_PARAM(unusedConnection);
+
if (!m_handle || !m_handle->client())
return;
CallbackGuard guard;
m_handle->client()->didReceiveResponse(m_handle, r);
}
-- (void)connection:(NSURLConnection *)con didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived
+- (void)connection:(NSURLConnection *)unusedConnection didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived
{
+ UNUSED_PARAM(unusedConnection);
+
if (!m_handle || !m_handle->client())
return;
// FIXME: If we get more than 2B bytes in a single chunk, this code won't do the right thing.
@@ -534,8 +565,10 @@ 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 *)con willStopBufferingData:(NSData *)data
+- (void)connection:(NSURLConnection *)unusedConnection willStopBufferingData:(NSData *)data
{
+ UNUSED_PARAM(unusedConnection);
+
if (!m_handle || !m_handle->client())
return;
// FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
@@ -545,16 +578,21 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
m_handle->client()->willStopBufferingData(m_handle, (const char*)[data bytes], static_cast<int>([data length]));
}
-- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
+- (void)connection:(NSURLConnection *)unusedConnection didSendBodyData:(NSInteger)unusedBytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
+ UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(unusedBytesWritten);
+
if (!m_handle || !m_handle->client())
return;
CallbackGuard guard;
m_handle->client()->didSendData(m_handle, totalBytesWritten, totalBytesExpectedToWrite);
}
-- (void)connectionDidFinishLoading:(NSURLConnection *)con
+- (void)connectionDidFinishLoading:(NSURLConnection *)unusedConnection
{
+ UNUSED_PARAM(unusedConnection);
+
if (!m_handle || !m_handle->client())
return;
CallbackGuard guard;
@@ -565,8 +603,10 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
m_handle->client()->didFinishLoading(m_handle);
}
-- (void)connection:(NSURLConnection *)con didFailWithError:(NSError *)error
+- (void)connection:(NSURLConnection *)unusedConnection didFailWithError:(NSError *)error
{
+ UNUSED_PARAM(unusedConnection);
+
if (!m_handle || !m_handle->client())
return;
CallbackGuard guard;
@@ -611,12 +651,15 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
return [result autorelease];
}
+#else
+ UNUSED_PARAM(connection);
#endif
#ifndef NDEBUG
if (isInitializingConnection)
LOG_ERROR("connection:willCacheResponse: was called inside of [NSURLConnection initWithRequest:delegate:] (4067625)");
#endif
+
if (!m_handle || !m_handle->client())
return nil;
@@ -663,6 +706,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
@end
#ifndef BUILDING_ON_TIGER
+
@implementation WebCoreSynchronousLoader
- (BOOL)_isDone
@@ -680,8 +724,11 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
[super dealloc];
}
-- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse
+- (NSURLRequest *)connection:(NSURLConnection *)unusedConnection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)unusedRedirectResponse
{
+ UNUSED_PARAM(unusedConnection);
+ UNUSED_PARAM(unusedRedirectResponse);
+
NSURL *copy = [[newRequest URL] copy];
[m_url release];
m_url = copy;
@@ -689,8 +736,10 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
return newRequest;
}
-- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+- (void)connection:(NSURLConnection *)unusedConnection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
+ UNUSED_PARAM(unusedConnection);
+
if ([challenge previousFailureCount] == 0) {
NSString *user = [m_url user];
NSString *password = [m_url password];
@@ -708,29 +757,37 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
-- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
+- (void)connection:(NSURLConnection *)unusedConnection didReceiveResponse:(NSURLResponse *)response
{
+ UNUSED_PARAM(unusedConnection);
+
NSURLResponse *r = [response copy];
[m_response release];
m_response = r;
}
-- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
+- (void)connection:(NSURLConnection *)unusedConnection didReceiveData:(NSData *)data
{
+ UNUSED_PARAM(unusedConnection);
+
if (!m_data)
m_data = [[NSMutableData alloc] init];
[m_data appendData:data];
}
-- (void)connectionDidFinishLoading:(NSURLConnection *)connection
+- (void)connectionDidFinishLoading:(NSURLConnection *)unusedConnection
{
+ UNUSED_PARAM(unusedConnection);
+
m_isDone = YES;
}
-- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
+- (void)connection:(NSURLConnection *)unusedConnection didFailWithError:(NSError *)error
{
+ UNUSED_PARAM(unusedConnection);
+
ASSERT(!m_error);
m_error = [error retain];
@@ -776,4 +833,5 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
}
@end
+
#endif
diff --git a/WebCore/platform/network/mac/ResourceRequestMac.mm b/WebCore/platform/network/mac/ResourceRequestMac.mm
index 63fffe1..a9bbd40 100644
--- a/WebCore/platform/network/mac/ResourceRequestMac.mm
+++ b/WebCore/platform/network/mac/ResourceRequestMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,6 +31,18 @@
#import <Foundation/Foundation.h>
+#ifdef BUILDING_ON_TIGER
+typedef unsigned NSUInteger;
+#endif
+
+@interface NSURLRequest (WebCoreContentDispositionEncoding)
+- (NSArray *)contentDispositionEncodingFallbackArray;
+@end
+
+@interface NSMutableURLRequest (WebCoreContentDispositionEncoding)
+- (void)setContentDispositionEncodingFallbackArray:(NSArray *)theEncodingFallbackArray;
+@end
+
namespace WebCore {
NSURLRequest* ResourceRequest::nsURLRequest() const
@@ -56,12 +68,25 @@ void ResourceRequest::doUpdateResourceRequest()
NSString *name;
while ((name = [e nextObject]))
m_httpHeaderFields.set(name, [headers objectForKey:name]);
-
+
+ // The below check can be removed once we require a version of Foundation with -[NSURLRequest contentDispositionEncodingFallbackArray] method.
+ static bool supportsContentDispositionEncodingFallbackArray = [NSURLRequest instancesRespondToSelector:@selector(contentDispositionEncodingFallbackArray)];
+ if (supportsContentDispositionEncodingFallbackArray) {
+ m_responseContentDispositionEncodingFallbackArray.clear();
+ NSArray *encodingFallbacks = [m_nsRequest.get() contentDispositionEncodingFallbackArray];
+ NSUInteger count = [encodingFallbacks count];
+ for (NSUInteger i = 0; i < count; ++i) {
+ CFStringEncoding encoding = CFStringConvertNSStringEncodingToEncoding([(NSNumber *)[encodingFallbacks objectAtIndex:i] unsignedLongValue]);
+ if (encoding != kCFStringEncodingInvalidId)
+ m_responseContentDispositionEncodingFallbackArray.append(CFStringGetNameOfEncoding(encoding));
+ }
+ }
+
if (NSData* bodyData = [m_nsRequest.get() HTTPBody])
m_httpBody = FormData::create([bodyData bytes], [bodyData length]);
else if (NSInputStream* bodyStream = [m_nsRequest.get() HTTPBodyStream])
if (FormData* formData = httpBodyFromStream(bodyStream))
- m_httpBody = formData;
+ m_httpBody = formData;
}
void ResourceRequest::doUpdatePlatformRequest()
@@ -93,7 +118,22 @@ void ResourceRequest::doUpdatePlatformRequest()
HTTPHeaderMap::const_iterator end = httpHeaderFields().end();
for (HTTPHeaderMap::const_iterator it = httpHeaderFields().begin(); it != end; ++it)
[nsRequest setValue:it->second forHTTPHeaderField:it->first];
-
+
+ // The below check can be removed once we require a version of Foundation with -[NSMutableURLRequest setContentDispositionEncodingFallbackArray] method.
+ static bool supportsContentDispositionEncodingFallbackArray = [NSMutableURLRequest instancesRespondToSelector:@selector(setContentDispositionEncodingFallbackArray)];
+ if (supportsContentDispositionEncodingFallbackArray) {
+ NSMutableArray *encodingFallbacks = [NSMutableArray array];
+ unsigned count = m_responseContentDispositionEncodingFallbackArray.size();
+ for (unsigned i = 0; i != count; ++i) {
+ CFStringRef encodingName = m_responseContentDispositionEncodingFallbackArray[i].createCFString();
+ unsigned long nsEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName));
+ CFRelease(encodingName);
+ if (nsEncoding != kCFStringEncodingInvalidId)
+ [encodingFallbacks addObject:[NSNumber numberWithUnsignedLong:nsEncoding]];
+ }
+ [nsRequest setContentDispositionEncodingFallbackArray:encodingFallbacks];
+ }
+
RefPtr<FormData> formData = httpBody();
if (formData && !formData->isEmpty())
WebCore::setHTTPBody(nsRequest, formData);
diff --git a/WebCore/platform/network/mac/ResourceResponseMac.mm b/WebCore/platform/network/mac/ResourceResponseMac.mm
index f60b496..d501b31 100644
--- a/WebCore/platform/network/mac/ResourceResponseMac.mm
+++ b/WebCore/platform/network/mac/ResourceResponseMac.mm
@@ -28,6 +28,7 @@
#import "WebCoreURLResponse.h"
#import <Foundation/Foundation.h>
+#import <wtf/StdLibExtras.h>
#import <limits>
@interface NSURLResponse (FoundationSecretsWebCoreKnowsAbout)
@@ -99,7 +100,7 @@ void ResourceResponse::platformLazyInit()
// is returning incorrect MIME type for local .xhtml files) which is only required in Leopard.
if (m_url.isLocalFile() && m_mimeType == "text/html") {
const String& path = m_url.path();
- static const String xhtmlExt(".xhtml");
+ DEFINE_STATIC_LOCAL(const String, xhtmlExt, (".xhtml"));
if (path.endsWith(xhtmlExt, false))
m_mimeType = "application/xhtml+xml";
}
diff --git a/WebCore/platform/network/soup/CookieJarSoup.cpp b/WebCore/platform/network/soup/CookieJarSoup.cpp
index 4ae90e5..88109e8 100644
--- a/WebCore/platform/network/soup/CookieJarSoup.cpp
+++ b/WebCore/platform/network/soup/CookieJarSoup.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Xan Lopez <xan@gnome.org>
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,24 +18,16 @@
*/
#include "config.h"
-#include "CString.h"
-#include "CookieJar.h"
+#include "CookieJarSoup.h"
+#include "CString.h"
#include "KURL.h"
-#include "PlatformString.h"
-#include "StringHash.h"
-
-#include <libsoup/soup.h>
namespace WebCore {
SoupCookieJar* getCookieJar()
{
- static SoupCookieJar* jar = NULL;
-
- if (!jar)
- jar = soup_cookie_jar_new();
-
+ static SoupCookieJar* jar = soup_cookie_jar_new();
return jar;
}
@@ -60,7 +53,7 @@ String cookies(const Document* /*document*/, const KURL& url)
char* cookies = soup_cookie_jar_get_cookies(jar, uri, FALSE);
soup_uri_free(uri);
- String result(cookies);
+ String result(String::fromUTF8(cookies));
g_free(cookies);
return result;
diff --git a/WebCore/platform/qt/SystemTimeQt.cpp b/WebCore/platform/network/soup/CookieJarSoup.h
index a9f3d98..61179ae 100644
--- a/WebCore/platform/qt/SystemTimeQt.cpp
+++ b/WebCore/platform/network/soup/CookieJarSoup.h
@@ -1,7 +1,6 @@
/*
- * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
- *
- * All rights reserved.
+ * Copyright (C) 2008 Xan Lopez <xan@gnome.org>
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,22 +24,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "SystemTime.h"
+#ifndef CookieJarSoup_h
+#define CookieJarSoup_h
-#include <sys/time.h>
+#include "CookieJar.h"
+#include <libsoup/soup.h>
namespace WebCore {
-
-double currentTime()
-{
- struct timeval tv;
- struct timezone tz;
-
- gettimeofday(&tv, &tz);
- return (double)tv.tv_sec + (double)(tv.tv_usec / 1000000.0);
-}
-
+ SoupCookieJar* getCookieJar();
}
-// vim: ts=4 sw=4 et
+#endif
diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index d48ce27..da96873 100644
--- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -2,6 +2,7 @@
* Copyright (C) 2008 Alp Toker <alp@atoker.com>
* Copyright (C) 2008 Xan Lopez <xan@gnome.org>
* Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2009 Holger Hans Peter Freyther
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,7 +25,7 @@
#include "ResourceHandle.h"
#include "Base64.h"
-#include "CookieJar.h"
+#include "CookieJarSoup.h"
#include "DocLoader.h"
#include "Frame.h"
#include "HTTPParsers.h"
@@ -57,12 +58,21 @@ enum
ERROR_BAD_NON_HTTP_METHOD
};
+static void cleanupGioOperation(ResourceHandleInternal* handle);
+
ResourceHandleInternal::~ResourceHandleInternal()
{
if (m_msg) {
g_object_unref(m_msg);
m_msg = 0;
}
+
+ cleanupGioOperation(this);
+
+ if (m_idleHandler) {
+ g_source_remove(m_idleHandler);
+ m_idleHandler = 0;
+ }
}
ResourceHandle::~ResourceHandle()
@@ -163,8 +173,6 @@ static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer da
return;
ResourceHandleInternal* d = handle->getInternal();
- // The message has been handled.
- d->m_msg = NULL;
ResourceHandleClient* client = handle->client();
if (!client)
@@ -200,6 +208,8 @@ static gboolean parseDataUrl(gpointer callback_data)
ResourceHandle* handle = static_cast<ResourceHandle*>(callback_data);
ResourceHandleClient* client = handle->client();
+ handle->getInternal()->m_idleHandler = 0;
+
ASSERT(client);
if (!client)
return FALSE;
@@ -264,10 +274,12 @@ static gboolean parseDataUrl(gpointer callback_data)
bool ResourceHandle::startData(String urlString)
{
- // If parseDataUrl is called synchronously the job is not yet effectively started
- // and webkit won't never know that the data has been parsed even didFinishLoading is called.
- g_idle_add(parseDataUrl, this);
- return true;
+ ResourceHandleInternal* d = this->getInternal();
+
+ // If parseDataUrl is called synchronously the job is not yet effectively started
+ // and webkit won't never know that the data has been parsed even didFinishLoading is called.
+ d->m_idleHandler = g_idle_add(parseDataUrl, this);
+ return true;
}
bool ResourceHandle::startHttp(String urlString)
@@ -298,7 +310,7 @@ bool ResourceHandle::startHttp(String urlString)
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.utf8().data(), it->second.utf8().data());
+ soup_message_headers_append(msg->request_headers, it->first.string().utf8().data(), it->second.utf8().data());
}
FormData* httpBody = d->m_request.httpBody();
@@ -337,7 +349,7 @@ bool ResourceHandle::start(Frame* frame)
if (equalIgnoringCase(protocol, "data"))
return startData(urlString);
- else if (equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https"))
+ else if ((equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) && SOUP_URI_VALID_FOR_HTTP(soup_uri_new(urlString.utf8().data())))
return startHttp(urlString);
else if (equalIgnoringCase(protocol, "file") || equalIgnoringCase(protocol, "ftp") || equalIgnoringCase(protocol, "ftps"))
// FIXME: should we be doing any other protocols here?
@@ -358,10 +370,12 @@ void ResourceHandle::cancel()
if (d->m_msg) {
soup_session_cancel_message(session, d->m_msg, SOUP_STATUS_CANCELLED);
// For re-entrancy troubles we call didFinishLoading when the message hasn't been handled yet.
- d->client()->didFinishLoading(this);
+ if (client())
+ client()->didFinishLoading(this);
} else if (d->m_cancellable) {
g_cancellable_cancel(d->m_cancellable);
- d->client()->didFinishLoading(this);
+ if (client())
+ client()->didFinishLoading(this);
}
}
@@ -411,11 +425,10 @@ static inline ResourceError networkErrorForFile(GFile* file, GError* error)
return resourceError;
}
-static void cleanupGioOperation(ResourceHandle* handle)
+static void cleanupGioOperation(ResourceHandleInternal* d)
{
- ResourceHandleInternal* d = handle->getInternal();
-
if (d->m_gfile) {
+ g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", 0);
g_object_unref(d->m_gfile);
d->m_gfile = NULL;
}
@@ -424,6 +437,7 @@ static void cleanupGioOperation(ResourceHandle* handle)
d->m_cancellable = NULL;
}
if (d->m_input_stream) {
+ g_object_set_data(G_OBJECT(d->m_input_stream), "webkit-resource", 0);
g_object_unref(d->m_input_stream);
d->m_input_stream = NULL;
}
@@ -433,25 +447,31 @@ static void cleanupGioOperation(ResourceHandle* handle)
}
}
-static void closeCallback(GObject* source, GAsyncResult* res, gpointer data)
+static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
{
- ResourceHandle* handle = static_cast<ResourceHandle*>(data);
+ ResourceHandle* handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
+ if (!handle)
+ return;
+
ResourceHandleInternal* d = handle->getInternal();
ResourceHandleClient* client = handle->client();
g_input_stream_close_finish(d->m_input_stream, res, NULL);
- cleanupGioOperation(handle);
+ cleanupGioOperation(d);
client->didFinishLoading(handle);
}
-static void readCallback(GObject* source, GAsyncResult* res, gpointer data)
+static void readCallback(GObject* source, GAsyncResult* res, gpointer)
{
- ResourceHandle* handle = static_cast<ResourceHandle*>(data);
+ ResourceHandle* handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
+ if (!handle)
+ return;
+
ResourceHandleInternal* d = handle->getInternal();
ResourceHandleClient* client = handle->client();
if (d->m_cancelled || !client) {
- cleanupGioOperation(handle);
+ cleanupGioOperation(d);
return;
}
@@ -460,12 +480,13 @@ static void readCallback(GObject* source, GAsyncResult* res, gpointer data)
nread = g_input_stream_read_finish(d->m_input_stream, res, &error);
if (error) {
- client->didFail(handle, networkErrorForFile(d->m_gfile, error));
- cleanupGioOperation(handle);
+ ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ cleanupGioOperation(d);
+ client->didFail(handle, resourceError);
return;
} else if (!nread) {
g_input_stream_close_async(d->m_input_stream, G_PRIORITY_DEFAULT,
- NULL, closeCallback, handle);
+ NULL, closeCallback, NULL);
return;
}
@@ -474,17 +495,20 @@ static void readCallback(GObject* source, GAsyncResult* res, gpointer data)
g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize,
G_PRIORITY_DEFAULT, d->m_cancellable,
- readCallback, handle);
+ readCallback, NULL);
}
-static void openCallback(GObject* source, GAsyncResult* res, gpointer data)
+static void openCallback(GObject* source, GAsyncResult* res, gpointer)
{
- ResourceHandle* handle = static_cast<ResourceHandle*>(data);
+ ResourceHandle* handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
+ if (!handle)
+ return;
+
ResourceHandleInternal* d = handle->getInternal();
ResourceHandleClient* client = handle->client();
if (d->m_cancelled || !client) {
- cleanupGioOperation(handle);
+ cleanupGioOperation(d);
return;
}
@@ -492,8 +516,9 @@ static void openCallback(GObject* source, GAsyncResult* res, gpointer data)
GError *error = NULL;
in = g_file_read_finish(G_FILE(source), res, &error);
if (error) {
- client->didFail(handle, networkErrorForFile(d->m_gfile, error));
- cleanupGioOperation(handle);
+ ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ cleanupGioOperation(d);
+ client->didFail(handle, resourceError);
return;
}
@@ -501,19 +526,23 @@ static void openCallback(GObject* source, GAsyncResult* res, gpointer data)
d->m_bufsize = 8192;
d->m_buffer = static_cast<char*>(g_malloc(d->m_bufsize));
d->m_total = 0;
+ g_object_set_data(G_OBJECT(d->m_input_stream), "webkit-resource", handle);
g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize,
G_PRIORITY_DEFAULT, d->m_cancellable,
- readCallback, handle);
+ readCallback, NULL);
}
-static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer data)
+static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
{
- ResourceHandle* handle = static_cast<ResourceHandle*>(data);
+ ResourceHandle* handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
+ if (!handle)
+ return;
+
ResourceHandleInternal* d = handle->getInternal();
ResourceHandleClient* client = handle->client();
if (d->m_cancelled) {
- cleanupGioOperation(handle);
+ cleanupGioOperation(d);
return;
}
@@ -534,8 +563,9 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer data)
// and set a timeout to unmount it later after it's been idle
// for a while).
- client->didFail(handle, networkErrorForFile(d->m_gfile, error));
- cleanupGioOperation(handle);
+ ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ cleanupGioOperation(d);
+ client->didFail(handle, resourceError);
return;
}
@@ -543,8 +573,9 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer data)
// FIXME: what if the URI points to a directory? Should we
// generate a listing? How? What do other backends do here?
- client->didFail(handle, networkErrorForFile(d->m_gfile, error));
- cleanupGioOperation(handle);
+ ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ cleanupGioOperation(d);
+ client->didFail(handle, resourceError);
return;
}
@@ -559,7 +590,7 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer data)
client->didReceiveResponse(handle, response);
g_file_read_async(d->m_gfile, G_PRIORITY_DEFAULT, d->m_cancellable,
- openCallback, handle);
+ openCallback, NULL);
}
bool ResourceHandle::startGio(String urlString)
@@ -576,6 +607,7 @@ bool ResourceHandle::startGio(String urlString)
urlString = urlString.left(fragPos);
d->m_gfile = g_file_new_for_uri(urlString.utf8().data());
+ g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", this);
d->m_cancellable = g_cancellable_new();
g_file_query_info_async(d->m_gfile,
G_FILE_ATTRIBUTE_STANDARD_TYPE ","
@@ -583,7 +615,7 @@ bool ResourceHandle::startGio(String urlString)
G_FILE_ATTRIBUTE_STANDARD_SIZE,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT, d->m_cancellable,
- queryInfoCallback, this);
+ queryInfoCallback, NULL);
return true;
}
diff --git a/WebCore/platform/network/win/CookieJarCFNetWin.cpp b/WebCore/platform/network/win/CookieJarCFNetWin.cpp
index fd795ee..56d7265 100644
--- a/WebCore/platform/network/win/CookieJarCFNetWin.cpp
+++ b/WebCore/platform/network/win/CookieJarCFNetWin.cpp
@@ -27,23 +27,67 @@
#include "CookieJar.h"
#include "CookieStorageWin.h"
+#include "Document.h"
#include "KURL.h"
#include "PlatformString.h"
-#include "Document.h"
#include "ResourceHandle.h"
-#include <windows.h>
-#include <CoreFoundation/CoreFoundation.h>
#include <CFNetwork/CFHTTPCookiesPriv.h>
+#include <CoreFoundation/CoreFoundation.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#include <windows.h>
namespace WebCore {
static const CFStringRef s_setCookieKeyCF = CFSTR("Set-Cookie");
static const CFStringRef s_cookieCF = CFSTR("Cookie");
+typedef Boolean (*IsHTTPOnlyFunction)(CFHTTPCookieRef);
+
+static HMODULE findCFNetworkModule()
+{
+ if (HMODULE module = GetModuleHandleA("CFNetwork"))
+ return module;
+ return GetModuleHandleA("CFNetwork_debug");
+}
+
+static IsHTTPOnlyFunction findIsHTTPOnlyFunction()
+{
+ return reinterpret_cast<IsHTTPOnlyFunction>(GetProcAddress(findCFNetworkModule(), "CFHTTPCookieIsHTTPOnly"));
+}
+
+static bool isHTTPOnly(CFHTTPCookieRef cookie)
+{
+ // Once we require a newer version of CFNetwork with the CFHTTPCookieIsHTTPOnly function,
+ // we can change this to be a normal function call and eliminate findIsHTTPOnlyFunction.
+ static IsHTTPOnlyFunction function = findIsHTTPOnlyFunction();
+ return function && function(cookie);
+}
+
+static RetainPtr<CFArrayRef> filterCookies(CFArrayRef unfilteredCookies)
+{
+ CFIndex count = CFArrayGetCount(unfilteredCookies);
+ RetainPtr<CFMutableArrayRef> filteredCookies(AdoptCF, CFArrayCreateMutable(0, count, &kCFTypeArrayCallBacks));
+ for (CFIndex i = 0; i < count; ++i) {
+ CFHTTPCookieRef cookie = (CFHTTPCookieRef)CFArrayGetValueAtIndex(unfilteredCookies, i);
+
+ // <rdar://problem/5632883> CFHTTPCookieStorage would store an empty cookie,
+ // which would be sent as "Cookie: =". We have a workaround in setCookies() to prevent
+ // that, but we also need to avoid sending cookies that were previously stored, and
+ // there's no harm to doing this check because such a cookie is never valid.
+ if (!CFStringGetLength(CFHTTPCookieGetName(cookie)))
+ continue;
+
+ if (isHTTPOnly(cookie))
+ continue;
+
+ CFArrayAppendValue(filteredCookies.get(), cookie);
+ }
+ return filteredCookies;
+}
+
void setCookies(Document* /*document*/, const KURL& url, const KURL& policyURL, const String& value)
{
- // <rdar://problem/5632883> CFHTTPCookieStorage happily stores an empty cookie, which would be sent as "Cookie: =".
+ // <rdar://problem/5632883> CFHTTPCookieStorage stores an empty cookie, which would be sent as "Cookie: =".
if (value.isEmpty())
return;
@@ -59,13 +103,14 @@ void setCookies(Document* /*document*/, const KURL& url, const KURL& policyURL,
String cookieString = value.contains('=') ? value : value + "=";
RetainPtr<CFStringRef> cookieStringCF(AdoptCF, cookieString.createCFString());
- RetainPtr<CFDictionaryRef> headerFieldsCF(AdoptCF, CFDictionaryCreate(kCFAllocatorDefault, (const void**)&s_setCookieKeyCF,
- (const void**)&cookieStringCF, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ RetainPtr<CFDictionaryRef> headerFieldsCF(AdoptCF, CFDictionaryCreate(kCFAllocatorDefault,
+ (const void**)&s_setCookieKeyCF, (const void**)&cookieStringCF, 1,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
RetainPtr<CFArrayRef> cookiesCF(AdoptCF, CFHTTPCookieCreateWithResponseHeaderFields(kCFAllocatorDefault,
headerFieldsCF.get(), urlCF.get()));
- CFHTTPCookieStorageSetCookies(cookieStorage, cookiesCF.get(), urlCF.get(), policyURLCF.get());
+ CFHTTPCookieStorageSetCookies(cookieStorage, filterCookies(cookiesCF.get()).get(), urlCF.get(), policyURLCF.get());
}
String cookies(const Document* /*document*/, const KURL& url)
@@ -74,24 +119,11 @@ String cookies(const Document* /*document*/, const KURL& url)
if (!cookieStorage)
return String();
- String cookieString;
RetainPtr<CFURLRef> urlCF(AdoptCF, url.createCFURL());
- bool secure = equalIgnoringCase(url.protocol(), "https");
-
+ bool secure = url.protocolIs("https");
RetainPtr<CFArrayRef> cookiesCF(AdoptCF, CFHTTPCookieStorageCopyCookiesForURL(cookieStorage, urlCF.get(), secure));
-
- // <rdar://problem/5632883> CFHTTPCookieStorage happily stores an empty cookie, which would be sent as "Cookie: =".
- // We have a workaround in setCookies() to prevent that, but we also need to avoid sending cookies that were previously stored.
- CFIndex count = CFArrayGetCount(cookiesCF.get());
- RetainPtr<CFMutableArrayRef> cookiesForURLFilteredCopy(AdoptCF, CFArrayCreateMutable(0, count, &kCFTypeArrayCallBacks));
- for (CFIndex i = 0; i < count; ++i) {
- CFHTTPCookieRef cookie = (CFHTTPCookieRef)CFArrayGetValueAtIndex(cookiesCF.get(), i);
- if (CFStringGetLength(CFHTTPCookieGetName(cookie)) != 0)
- CFArrayAppendValue(cookiesForURLFilteredCopy.get(), cookie);
- }
- RetainPtr<CFDictionaryRef> headerCF(AdoptCF, CFHTTPCookieCopyRequestHeaderFields(kCFAllocatorDefault, cookiesForURLFilteredCopy.get()));
-
+ RetainPtr<CFDictionaryRef> headerCF(AdoptCF, CFHTTPCookieCopyRequestHeaderFields(kCFAllocatorDefault, filterCookies(cookiesCF.get()).get()));
return (CFStringRef)CFDictionaryGetValue(headerCF.get(), s_cookieCF);
}
diff --git a/WebCore/platform/network/win/NetworkStateNotifierWin.cpp b/WebCore/platform/network/win/NetworkStateNotifierWin.cpp
index f8cbace..5cc381d 100644
--- a/WebCore/platform/network/win/NetworkStateNotifierWin.cpp
+++ b/WebCore/platform/network/win/NetworkStateNotifierWin.cpp
@@ -99,6 +99,7 @@ void NetworkStateNotifier::registerForAddressChange()
NetworkStateNotifier::NetworkStateNotifier()
: m_isOnLine(false)
+ , m_networkStateChangedFunction(0)
{
updateState();
diff --git a/WebCore/platform/posix/FileSystemPOSIX.cpp b/WebCore/platform/posix/FileSystemPOSIX.cpp
index 82ae087..c1bef60 100644
--- a/WebCore/platform/posix/FileSystemPOSIX.cpp
+++ b/WebCore/platform/posix/FileSystemPOSIX.cpp
@@ -163,31 +163,10 @@ String directoryName(const String& path)
return dirname(fsRep.mutableData());
}
-Vector<String> listDirectory(const String& path, const String& filter)
-{
-#ifdef ANDROID_PLUGINS
- CString fsRepPath = fileSystemRepresentation(path);
- CString fsRepFilter = fileSystemRepresentation(filter);
-#endif
- Vector<String> entries;
-#ifdef ANDROID_PLUGINS
- DIR *dir = opendir(fsRepPath.data());
- if (dir == NULL)
- return entries;
- for (;;) {
- struct dirent *entry = readdir(dir);
- if (entry == NULL)
- break;
- if (!fnmatch(fsRepFilter.data(), entry->d_name, FNM_NOESCAPE)) {
- String fullPath = path + "/" + entry->d_name;
- entries.append(fullPath);
- }
- }
- closedir(dir);
-#else
- notImplemented();
-#endif
- return entries;
-}
+// OK to not implement listDirectory at the moment, because it's only used for plug-ins, and
+// all platforms that use the shared plug-in implementation have implementations. We'd need
+// to implement it if we wanted to use PluginDatabase.cpp on the Mac. Better to not implement
+// at all and get a link error in case this arises, rather than having a stub here, because
+// with a stub you learn about the problem at runtime instead of link time.
} // namespace WebCore
diff --git a/WebCore/platform/qt/ClipboardQt.cpp b/WebCore/platform/qt/ClipboardQt.cpp
index b0a1402..1bde10b 100644
--- a/WebCore/platform/qt/ClipboardQt.cpp
+++ b/WebCore/platform/qt/ClipboardQt.cpp
@@ -242,7 +242,7 @@ void ClipboardQt::declareAndWriteDragImage(Element* element, const KURL& url, co
return;
QPixmap *pixmap = cachedImage->image()->nativeImageForCurrentFrame();
if (pixmap)
- m_writableData->setImageData(pixmap);
+ m_writableData->setImageData(*pixmap);
AtomicString imageURL = element->getAttribute(HTMLNames::srcAttr);
if (imageURL.isEmpty())
diff --git a/WebCore/platform/qt/CookieJarQt.cpp b/WebCore/platform/qt/CookieJarQt.cpp
index 43be75a..0d24c7e 100644
--- a/WebCore/platform/qt/CookieJarQt.cpp
+++ b/WebCore/platform/qt/CookieJarQt.cpp
@@ -71,6 +71,15 @@ void setCookies(Document* document, const KURL& url, const KURL& policyURL, cons
return;
QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(QString(value).toAscii());
+#if QT_VERSION >= 0x040500
+ QList<QNetworkCookie>::Iterator it = cookies.begin();
+ while (it != cookies.end()) {
+ if (it->isHttpOnly())
+ it = cookies.erase(it);
+ else
+ ++it;
+ }
+#endif
jar->setCookiesFromUrl(cookies, p);
#else
QCookieJar::cookieJar()->setCookies(u, p, (QString)value);
@@ -90,9 +99,14 @@ String cookies(const Document* document, const KURL& url)
return String();
QStringList resultCookies;
- foreach (QNetworkCookie networkCookie, cookies)
+ foreach (QNetworkCookie networkCookie, cookies) {
+#if QT_VERSION >= 0x040500
+ if (networkCookie.isHttpOnly())
+ continue;
+#endif
resultCookies.append(QString::fromAscii(
networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData()));
+ }
return resultCookies.join(QLatin1String("; "));
#else
diff --git a/WebCore/platform/qt/FileChooserQt.cpp b/WebCore/platform/qt/FileChooserQt.cpp
index b468dbe..307876c 100644
--- a/WebCore/platform/qt/FileChooserQt.cpp
+++ b/WebCore/platform/qt/FileChooserQt.cpp
@@ -21,15 +21,33 @@
#include "config.h"
#include "FileChooser.h"
+#include "LocalizedStrings.h"
#include "Font.h"
+#include <QCoreApplication>
#include <QFontMetrics>
namespace WebCore {
String FileChooser::basenameForWidth(const Font& f, int width) const
{
- QFontMetrics fm(f.font());
- return fm.elidedText(m_filenames[0], Qt::ElideLeft, width);
+ if (width <= 0)
+ return String();
+
+ String string;
+ if (m_filenames.isEmpty())
+ string = fileButtonNoFileSelectedLabel();
+ else if (m_filenames.size() == 1) {
+ String fname = m_filenames[0];
+ QFontMetrics fm(f.font());
+ string = fm.elidedText(fname, Qt::ElideLeft, width);
+ } else {
+ int n = m_filenames.size();
+ string = QCoreApplication::translate("QWebPage", "%n file(s)",
+ "number of chosen file",
+ QCoreApplication::CodecForTr, n);
+ }
+
+ return string;
}
}
diff --git a/WebCore/platform/qt/FileSystemQt.cpp b/WebCore/platform/qt/FileSystemQt.cpp
index 6b56070..6dbe464 100644
--- a/WebCore/platform/qt/FileSystemQt.cpp
+++ b/WebCore/platform/qt/FileSystemQt.cpp
@@ -118,7 +118,7 @@ Vector<String> listDirectory(const String& path, const String& filter)
CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
{
- QFile *temp = new QTemporaryFile(QString(prefix));
+ QFile *temp = new QTemporaryFile(QLatin1String(prefix));
if (temp->open(QIODevice::ReadWrite)) {
handle = temp;
return String(temp->fileName()).utf8();
@@ -163,7 +163,7 @@ bool unloadModule(PlatformModule module)
}
#endif
-#if defined(Q_OS_WIN32)
+#if defined(Q_OS_WIN)
bool unloadModule(PlatformModule module)
{
return ::FreeLibrary(module);
diff --git a/WebCore/platform/qt/KeyboardCodes.h b/WebCore/platform/qt/KeyboardCodes.h
index 21d3c67..61bc9fe 100644
--- a/WebCore/platform/qt/KeyboardCodes.h
+++ b/WebCore/platform/qt/KeyboardCodes.h
@@ -472,6 +472,10 @@ 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;
+#endif // !PLATFORM(WIN_OS)
+
+#if !PLATFORM(WIN_OS) || PLATFORM(WIN_CE)
+
// 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;
@@ -508,6 +512,10 @@ 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;
+#endif // !PLATFORM(WIN_OS) || PLATFORM(WIN_CE)
+
+#if !PLATFORM(WIN_OS)
+
// 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;
diff --git a/WebCore/platform/qt/Localizations.cpp b/WebCore/platform/qt/Localizations.cpp
index b49b880..cb805f9 100644
--- a/WebCore/platform/qt/Localizations.cpp
+++ b/WebCore/platform/qt/Localizations.cpp
@@ -233,6 +233,11 @@ String contextMenuItemTagWritingDirectionMenu()
return QCoreApplication::translate("QWebPage", "Direction", "Writing direction context sub-menu item");
}
+String contextMenuItemTagTextDirectionMenu()
+{
+ return QCoreApplication::translate("QWebPage", "Text Direction", "Text direction context sub-menu item");
+}
+
String contextMenuItemTagDefaultDirection()
{
return QCoreApplication::translate("QWebPage", "Default", "Default writing direction context menu item");
diff --git a/WebCore/platform/qt/LoggingQt.cpp b/WebCore/platform/qt/LoggingQt.cpp
index 5f6720a..b76c46e 100644
--- a/WebCore/platform/qt/LoggingQt.cpp
+++ b/WebCore/platform/qt/LoggingQt.cpp
@@ -64,18 +64,18 @@ void InitializeLoggingChannelsIfNecessary()
haveInitializedLoggingChannels = true;
- QString loggingEnv = qgetenv("QT_WEBKIT_LOG");
+ QByteArray loggingEnv = qgetenv("QT_WEBKIT_LOG");
if (loggingEnv.isEmpty())
return;
#if defined(NDEBUG)
qWarning("This is a release build. Setting QT_WEBKIT_LOG will have no effect.");
#else
- QStringList channels = loggingEnv.split(",");
- QStringListIterator iter(channels);
+ QList<QByteArray> channels = loggingEnv.split(',');
+ QListIterator<QByteArray> iter(channels);
while (iter.hasNext()) {
- QString channelName = iter.next();
+ QByteArray channelName = iter.next();
WTFLogChannel* channel = getChannelFromName(channelName);
if (!channel) continue;
channel->state = WTFLogChannelOn;
diff --git a/WebCore/platform/qt/MIMETypeRegistryQt.cpp b/WebCore/platform/qt/MIMETypeRegistryQt.cpp
index 9f4a786..2b5968a 100644
--- a/WebCore/platform/qt/MIMETypeRegistryQt.cpp
+++ b/WebCore/platform/qt/MIMETypeRegistryQt.cpp
@@ -2,6 +2,7 @@
* Copyright (C) 2006 Zack Rusin <zack@kde.org>
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2008 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
@@ -62,6 +63,8 @@ static const ExtensionMap extensionMap [] = {
{ "xpm", "image/x-xpm" },
{ "xsl", "text/xsl" },
{ "xhtml", "application/xhtml+xml" },
+ { "wml", "text/vnd.wap.wml" },
+ { "wmlc", "application/vnd.wap.wmlc" },
{ 0, 0 }
};
diff --git a/WebCore/platform/qt/PlatformMouseEventQt.cpp b/WebCore/platform/qt/PlatformMouseEventQt.cpp
index afc7452..ba7a4ad 100644
--- a/WebCore/platform/qt/PlatformMouseEventQt.cpp
+++ b/WebCore/platform/qt/PlatformMouseEventQt.cpp
@@ -28,7 +28,7 @@
#include "config.h"
#include "PlatformMouseEvent.h"
-#include "SystemTime.h"
+#include <wtf/CurrentTime.h>
#include <QMouseEvent>
@@ -36,7 +36,7 @@ namespace WebCore {
PlatformMouseEvent::PlatformMouseEvent(QInputEvent* event, int clickCount)
{
- m_timestamp = WebCore::currentTime();
+ m_timestamp = WTF::currentTime();
QMouseEvent *me = 0;
diff --git a/WebCore/platform/qt/PlatformScreenQt.cpp b/WebCore/platform/qt/PlatformScreenQt.cpp
index 5bc86d0..5dc0963 100644
--- a/WebCore/platform/qt/PlatformScreenQt.cpp
+++ b/WebCore/platform/qt/PlatformScreenQt.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2008 Holger Hans Peter Freyther
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -43,34 +44,34 @@ namespace WebCore {
int screenDepth(Widget* w)
{
QDesktopWidget* d = QApplication::desktop();
- QWidget *view = w->root()->hostWindow()->platformWindow();
+ QWidget *view = w ? w->root()->hostWindow()->platformWindow() : 0;
int screenNumber = view ? d->screenNumber(view) : 0;
return d->screen(screenNumber)->depth();
}
int screenDepthPerComponent(Widget* w)
{
- QWidget *view = w->root()->hostWindow()->platformWindow();
+ QWidget *view = w ? w->root()->hostWindow()->platformWindow() : 0;
return view ? view->depth() : QApplication::desktop()->screen(0)->depth();
}
bool screenIsMonochrome(Widget* w)
{
QDesktopWidget* d = QApplication::desktop();
- QWidget *view = w->root()->hostWindow()->platformWindow();
+ QWidget *view = w ? w->root()->hostWindow()->platformWindow(): 0;
int screenNumber = view ? d->screenNumber(view) : 0;
return d->screen(screenNumber)->numColors() < 2;
}
FloatRect screenRect(Widget* w)
{
- QRect r = QApplication::desktop()->screenGeometry(w->root()->hostWindow()->platformWindow());
+ QRect r = QApplication::desktop()->screenGeometry(w ? w->root()->hostWindow()->platformWindow(): 0);
return FloatRect(r.x(), r.y(), r.width(), r.height());
}
FloatRect screenAvailableRect(Widget* w)
{
- QRect r = QApplication::desktop()->availableGeometry(w->root()->hostWindow()->platformWindow());
+ QRect r = QApplication::desktop()->availableGeometry(w ? w->root()->hostWindow()->platformWindow(): 0);
return FloatRect(r.x(), r.y(), r.width(), r.height());
}
diff --git a/WebCore/platform/qt/QWebPopup.cpp b/WebCore/platform/qt/QWebPopup.cpp
index ae5c24e..d463ddf 100644
--- a/WebCore/platform/qt/QWebPopup.cpp
+++ b/WebCore/platform/qt/QWebPopup.cpp
@@ -35,7 +35,7 @@ QWebPopup::QWebPopup(PopupMenuClient* client)
setFont(m_client->menuStyle().font().font());
connect(this, SIGNAL(activated(int)),
- SLOT(activeChanged(int)));
+ SLOT(activeChanged(int)), Qt::QueuedConnection);
}
diff --git a/WebCore/platform/qt/RenderThemeQt.cpp b/WebCore/platform/qt/RenderThemeQt.cpp
index 2a33e45..eee8c86 100644
--- a/WebCore/platform/qt/RenderThemeQt.cpp
+++ b/WebCore/platform/qt/RenderThemeQt.cpp
@@ -6,6 +6,7 @@
* Copyright (C) 2006 Zack Rusin <zack@kde.org>
* 2006 Dirk Mueller <mueller@kde.org>
* 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2008 Holger Hans Peter Freyther
*
* All rights reserved.
*
@@ -45,7 +46,9 @@
#include <QStyleOptionFrameV2>
#include "Color.h"
+#include "CSSStyleSelector.h"
#include "CSSStyleSheet.h"
+#include "FontSelector.h"
#include "Document.h"
#include "Page.h"
#include "Font.h"
@@ -53,6 +56,7 @@
#include "GraphicsContext.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
+#include "RenderBox.h"
namespace WebCore {
@@ -151,9 +155,12 @@ bool RenderThemeQt::supportsFocusRing(const RenderStyle* style) const
int RenderThemeQt::baselinePosition(const RenderObject* o) const
{
+ if (!o->isBox())
+ return 0;
+
if (o->style()->appearance() == CheckboxPart ||
o->style()->appearance() == RadioPart)
- return o->marginTop() + o->height() - 2; // Same as in old khtml
+ return toRenderBox(o)->marginTop() + toRenderBox(o)->height() - 2; // Same as in old khtml
return RenderTheme::baselinePosition(o);
}
@@ -398,6 +405,7 @@ void RenderThemeQt::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* s
fontFamily.setFamily(m_buttonFontFamily);
fontDescription.setFamily(fontFamily);
style->setFontDescription(fontDescription);
+ style->font().update(selector->fontSelector());
style->setLineHeight(RenderStyle::initialLineHeight());
setButtonSize(style);
@@ -567,8 +575,6 @@ bool RenderThemeQt::paintMenuList(RenderObject* o, const RenderObject::PaintInfo
opt.rect.moveTo(QPoint(0,0));
opt.rect.setSize(r.size());
- opt.frame = false;
-
p.drawComplexControl(QStyle::CC_ComboBox, opt);
p.painter->translate(-topLeft);
return false;
@@ -715,8 +721,10 @@ ControlPart RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) con
// Readonly is supported on textfields.
option.state |= QStyle::State_ReadOnly;
- if (supportsFocus(o->style()->appearance()) && isFocused(o))
+ if (supportsFocus(o->style()->appearance()) && isFocused(o)) {
option.state |= QStyle::State_HasFocus;
+ option.state |= QStyle::State_KeyboardFocusChange;
+ }
if (isHovered(o))
option.state |= QStyle::State_MouseOver;
@@ -754,16 +762,18 @@ ControlPart RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) con
return result;
}
-void RenderTheme::adjustDefaultStyleSheet(CSSStyleSheet* style)
+#if ENABLE(VIDEO)
+
+String RenderThemeQt::extraMediaControlsStyleSheet()
{
- QFile platformStyleSheet(":/webcore/resources/html4-adjustments-qt.css");
+ QFile platformStyleSheet(QLatin1String(":/webcore/css/mediaControls-extras.css"));
if (platformStyleSheet.open(QFile::ReadOnly)) {
QByteArray sheetData = platformStyleSheet.readAll();
- style->parseString(QString::fromUtf8(sheetData.constData(), sheetData.length()));
+ return QString::fromUtf8(sheetData.constData(), sheetData.length());
}
-}
-#if ENABLE(VIDEO)
+ return String();
+}
// Helper class to transform the painter's world matrix to the object's content area, scaled to 0,0,100,100
class WorldMatrixTransformer
@@ -942,6 +952,11 @@ void RenderThemeQt::adjustSliderThumbSize(RenderObject* o) const
}
}
+double RenderThemeQt::caretBlinkInterval() const
+{
+ return QApplication::cursorFlashTime() / 1000.0 / 2.0;
+}
+
}
// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/qt/RenderThemeQt.h b/WebCore/platform/qt/RenderThemeQt.h
index 76e1855..9a6cf0b 100644
--- a/WebCore/platform/qt/RenderThemeQt.h
+++ b/WebCore/platform/qt/RenderThemeQt.h
@@ -70,6 +70,12 @@ public:
virtual void adjustSliderThumbSize(RenderObject*) const;
+ virtual double caretBlinkInterval() const;
+
+#if ENABLE(VIDEO)
+ virtual String extraMediaControlsStyleSheet();
+#endif
+
protected:
virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
virtual void setCheckboxSize(RenderStyle*) const;
diff --git a/WebCore/platform/qt/ScrollbarQt.cpp b/WebCore/platform/qt/ScrollbarQt.cpp
index 2d65282..29a9997 100644
--- a/WebCore/platform/qt/ScrollbarQt.cpp
+++ b/WebCore/platform/qt/ScrollbarQt.cpp
@@ -49,6 +49,9 @@ namespace WebCore {
bool Scrollbar::contextMenu(const PlatformMouseEvent& event)
{
#ifndef QT_NO_CONTEXTMENU
+ if (!QApplication::style()->styleHint(QStyle::SH_ScrollBar_ContextMenu))
+ return true;
+
bool horizontal = (m_orientation == HorizontalScrollbar);
QMenu menu;
diff --git a/WebCore/platform/qt/ScrollbarThemeQt.cpp b/WebCore/platform/qt/ScrollbarThemeQt.cpp
index 1995719..3851dfe 100644
--- a/WebCore/platform/qt/ScrollbarThemeQt.cpp
+++ b/WebCore/platform/qt/ScrollbarThemeQt.cpp
@@ -94,11 +94,17 @@ static ScrollbarPart scrollbarPart(const QStyle::SubControl& sc)
return NoPart;
}
-static QStyleOptionSlider* styleOptionSlider(Scrollbar* scrollbar)
+static QStyleOptionSlider* styleOptionSlider(Scrollbar* scrollbar, QWidget* widget = 0)
{
static QStyleOptionSlider opt;
+ if (widget)
+ opt.initFrom(widget);
+ else
+ opt.state |= QStyle::State_Active;
+
+ opt.state &= ~QStyle::State_HasFocus;
+
opt.rect = scrollbar->frameRect();
- opt.state = 0;
if (scrollbar->enabled())
opt.state |= QStyle::State_Enabled;
if (scrollbar->controlSize() != RegularScrollbar)
@@ -139,7 +145,8 @@ bool ScrollbarThemeQt::paint(Scrollbar* scrollbar, GraphicsContext* graphicsCont
return true;
p.painter->save();
- QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
+ QStyleOptionSlider* opt = styleOptionSlider(scrollbar, p.widget);
+
p.painter->setClipRect(opt->rect.intersected(damageRect));
#ifdef Q_WS_MAC
diff --git a/WebCore/platform/qt/SharedTimerQt.cpp b/WebCore/platform/qt/SharedTimerQt.cpp
index 49f55c1..e9bcaee 100644
--- a/WebCore/platform/qt/SharedTimerQt.cpp
+++ b/WebCore/platform/qt/SharedTimerQt.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006 George Staikos <staikos@kde.org>
* Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2008 Holger Hans Peter Freyther
*
* All rights reserved.
*
@@ -26,30 +27,105 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "SharedTimerQt.h"
-#include <QApplication>
+#include "config.h"
+
+#include <wtf/CurrentTime.h>
+
+#include <QBasicTimer>
+#include <QCoreApplication>
+#include <QDebug>
+#include <QPointer>
namespace WebCore {
-SharedTimerQt* SharedTimerQt::s_self = 0; // FIXME: staticdeleter
+class SharedTimerQt : public QObject {
+ friend void setSharedTimerFiredFunction(void (*f)());
+public:
+ static SharedTimerQt* inst();
+
+ void start(double);
+ void stop();
+
+protected:
+ void timerEvent(QTimerEvent* ev);
+
+private:
+ SharedTimerQt(QObject* parent);
+ ~SharedTimerQt();
+ QBasicTimer m_timer;
+ void (*m_timerFunction)();
+};
+
+SharedTimerQt::SharedTimerQt(QObject* parent)
+ : QObject(parent)
+ , m_timerFunction(0)
+{}
+
+SharedTimerQt::~SharedTimerQt()
+{
+ if (m_timer.isActive())
+ (m_timerFunction)();
+}
+
+SharedTimerQt* SharedTimerQt::inst()
+{
+ static QPointer<SharedTimerQt> timer;
+ if (!timer)
+ timer = new SharedTimerQt(QCoreApplication::instance());
+
+ return timer;
+}
+
+void SharedTimerQt::start(double fireTime)
+{
+ double interval = fireTime - currentTime();
+ unsigned int intervalInMS;
+ if (interval < 0)
+ intervalInMS = 0;
+ else {
+ interval *= 1000;
+ intervalInMS = (unsigned int)interval;
+ }
+
+ m_timer.start(intervalInMS, this);
+}
+
+void SharedTimerQt::stop()
+{
+ m_timer.stop();
+}
+
+void SharedTimerQt::timerEvent(QTimerEvent* ev)
+{
+ if (!m_timerFunction || ev->timerId() != m_timer.timerId())
+ return;
+
+ m_timer.stop();
+ (m_timerFunction)();
+}
void setSharedTimerFiredFunction(void (*f)())
{
+ if (!QCoreApplication::instance())
+ return;
+
SharedTimerQt::inst()->m_timerFunction = f;
}
void setSharedTimerFireTime(double fireTime)
{
- if (!qApp)
+ if (!QCoreApplication::instance())
return;
- qreal fireTimeMs = (fireTime - currentTime()) * 1000;
- SharedTimerQt::inst()->start(qMax(0, int(fireTimeMs)));
+ SharedTimerQt::inst()->start(fireTime);
}
void stopSharedTimer()
{
+ if (!QCoreApplication::instance())
+ return;
+
SharedTimerQt::inst()->stop();
}
diff --git a/WebCore/platform/qt/TemporaryLinkStubs.cpp b/WebCore/platform/qt/TemporaryLinkStubs.cpp
index f262684..ff0b27d 100644
--- a/WebCore/platform/qt/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/qt/TemporaryLinkStubs.cpp
@@ -74,7 +74,7 @@
using namespace WebCore;
-#if !defined(Q_WS_X11) && !defined(Q_WS_WIN)
+#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; }
@@ -83,7 +83,11 @@ int PluginPackage::compareFileVersion(const PlatformModuleVersion&) const { notI
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(); }
@@ -92,14 +96,23 @@ 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() const { 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(); }
+bool PluginDatabase::isPreferredPluginDirectory(const String& directory) { notImplemented(); return false; }
+#endif
+
namespace WebCore {
void getSupportedKeySizes(Vector<String>&) { notImplemented(); }
diff --git a/WebCore/platform/qt/WebCoreResources.qrc b/WebCore/platform/qt/WebCoreResources.qrc
deleted file mode 100644
index e42cd7f..0000000
--- a/WebCore/platform/qt/WebCoreResources.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource prefix="/webcore/resources">
- <file>html4-adjustments-qt.css</file>
-</qresource>
-</RCC> \ No newline at end of file
diff --git a/WebCore/platform/qt/WheelEventQt.cpp b/WebCore/platform/qt/WheelEventQt.cpp
index 135f15a..cc8acd2 100644
--- a/WebCore/platform/qt/WheelEventQt.cpp
+++ b/WebCore/platform/qt/WheelEventQt.cpp
@@ -35,7 +35,11 @@ PlatformWheelEvent::PlatformWheelEvent(QWheelEvent* e)
#else
: m_position(e->pos())
, m_globalPosition(e->globalPos())
+#ifdef QT_MAC_USE_COCOA
+ , m_granularity(ScrollByPixelWheelEvent)
+#else
, m_granularity(ScrollByLineWheelEvent)
+#endif
, m_isAccepted(false)
, m_shiftKey(e->modifiers() & Qt::ShiftModifier)
, m_ctrlKey(e->modifiers() & Qt::ControlModifier)
diff --git a/WebCore/platform/qt/WidgetQt.cpp b/WebCore/platform/qt/WidgetQt.cpp
index 68cf383..9f1a1e8 100644
--- a/WebCore/platform/qt/WidgetQt.cpp
+++ b/WebCore/platform/qt/WidgetQt.cpp
@@ -69,9 +69,9 @@ IntRect Widget::frameRect() const
void Widget::setFrameRect(const IntRect& rect)
{
- if (platformWidget())
- platformWidget()->setGeometry(convertToContainingWindow(IntRect(0, 0, rect.width(), rect.height())));
m_frame = rect;
+
+ frameRectsChanged();
}
void Widget::setFocus()
diff --git a/WebCore/platform/qt/html4-adjustments-qt.css b/WebCore/platform/qt/html4-adjustments-qt.css
deleted file mode 100644
index 129c164..0000000
--- a/WebCore/platform/qt/html4-adjustments-qt.css
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * QtWebKit specific style sheet.
- *
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-audio {
- height: 34px;
- width: 400px;
-}
-
-audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
- left: auto;
- right: 5px;
- width: 12px;
- height: 12px;
- padding: 6px;
- margin: 5px 0px;
-}
-
-audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
- left: 5px;
- width: 9px;
- height: 12px;
- padding: 6px 12px 6px 11px;
- margin: 5px 0px;
-}
-
-audio::-webkit-media-controls-time-display, video::-webkit-media-controls-time-display {
- /* Since MediaControlElements are always created with a renderer we have to hide
- the controls we don't use, so they don't mess up activation and event handling */
- left: 0px;
- top: 0px;
- width: 0px;
- height: 0px;
-
- display: none;
-}
-
-audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
- left: 42px;
- right: 34px;
- height: 12px;
- padding: 6px 8px;
- margin: 5px 0px;
-}
-
-audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button {
- /* Since MediaControlElements are always created with a renderer we have to hide
- the controls we don't use, so they don't mess up activation and event handling */
- left: 0px;
- top: 0px;
- width: 0px;
- height: 0px;
-
- display: none;
-}
-
-audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button {
- /* Since MediaControlElements are always created with a renderer we have to hide
- the controls we don't use, so they don't mess up activation and event handling */
- left: 0px;
- top: 0px;
- width: 0px;
- height: 0px;
-
- display: none;
-}
-
-audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button {
- /* Since MediaControlElements are always created with a renderer we have to hide
- the controls we don't use, so they don't mess up activation and event handling */
- left: 0px;
- top: 0px;
- width: 0px;
- height: 0px;
-
- display: none;
-}
-
diff --git a/WebCore/platform/text/AtomicString.cpp b/WebCore/platform/text/AtomicString.cpp
index dc573e1..5f9abfd 100644
--- a/WebCore/platform/text/AtomicString.cpp
+++ b/WebCore/platform/text/AtomicString.cpp
@@ -28,35 +28,21 @@
#include "StaticConstructors.h"
#include "StringHash.h"
-#include <kjs/identifier.h>
+#include "ThreadGlobalData.h"
#include <wtf/Threading.h>
#include <wtf/HashSet.h>
-#if ENABLE(WORKERS)
-#include <wtf/ThreadSpecific.h>
-using namespace WTF;
-#endif
-
#if USE(JSC)
+#include <runtime/Identifier.h>
using JSC::Identifier;
using JSC::UString;
#endif
namespace WebCore {
-#if ENABLE(WORKERS)
-static ThreadSpecific<HashSet<StringImpl*> >* staticStringTable;
-#else
-static HashSet<StringImpl*>* staticStringTable;
-#endif
-
-static inline HashSet<StringImpl*>* stringTable()
+static inline HashSet<StringImpl*>& stringTable()
{
-#if ENABLE(WORKERS)
- return *staticStringTable;
-#else
- return staticStringTable;
-#endif
+ return threadGlobalData().atomicStringTable();
}
struct CStringTranslator {
@@ -99,7 +85,7 @@ PassRefPtr<StringImpl> AtomicString::add(const char* c)
return 0;
if (!*c)
return StringImpl::empty();
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<const char*, CStringTranslator>(c);
+ pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<const char*, CStringTranslator>(c);
if (!addResult.second)
return *addResult.first;
return adoptRef(*addResult.first);
@@ -191,10 +177,11 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s, int length)
return StringImpl::empty();
UCharBuffer buf = { s, length };
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<UCharBuffer, UCharBufferTranslator>(buf);
- if (!addResult.second)
- return *addResult.first;
- return adoptRef(*addResult.first);
+ pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf);
+
+ // If the string is newly-translated, then we need to adopt it.
+ // The boolean in the pair tells us if that is so.
+ return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
}
PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
@@ -210,10 +197,11 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
return StringImpl::empty();
UCharBuffer buf = {s, length};
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<UCharBuffer, UCharBufferTranslator>(buf);
- if (!addResult.second)
- return *addResult.first;
- return adoptRef(*addResult.first);
+ pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf);
+
+ // If the string is newly-translated, then we need to adopt it.
+ // The boolean in the pair tells us if that is so.
+ return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
}
PassRefPtr<StringImpl> AtomicString::add(StringImpl* r)
@@ -224,7 +212,7 @@ PassRefPtr<StringImpl> AtomicString::add(StringImpl* r)
if (r->length() == 0)
return StringImpl::empty();
- StringImpl* result = *stringTable()->add(r).first;
+ StringImpl* result = *stringTable().add(r).first;
if (result == r)
r->m_inTable = true;
return result;
@@ -232,7 +220,7 @@ PassRefPtr<StringImpl> AtomicString::add(StringImpl* r)
void AtomicString::remove(StringImpl* r)
{
- stringTable()->remove(r);
+ stringTable().remove(r);
}
#if USE(JSC)
@@ -247,7 +235,7 @@ PassRefPtr<StringImpl> AtomicString::add(const JSC::Identifier& identifier)
return StringImpl::empty();
HashAndCharacters buffer = { string->computedHash(), string->data(), length };
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
+ pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
if (!addResult.second)
return *addResult.first;
return adoptRef(*addResult.first);
@@ -264,12 +252,11 @@ PassRefPtr<StringImpl> AtomicString::add(const JSC::UString& ustring)
return StringImpl::empty();
HashAndCharacters buffer = { string->hash(), string->data(), length };
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
+ pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
if (!addResult.second)
return *addResult.first;
return adoptRef(*addResult.first);
}
-#endif
AtomicStringImpl* AtomicString::find(const JSC::Identifier& identifier)
{
@@ -282,8 +269,8 @@ AtomicStringImpl* AtomicString::find(const JSC::Identifier& identifier)
return static_cast<AtomicStringImpl*>(StringImpl::empty());
HashAndCharacters buffer = { string->computedHash(), string->data(), length };
- HashSet<StringImpl*>::iterator iterator = stringTable()->find<HashAndCharacters, HashAndCharactersTranslator>(buffer);
- if (iterator == stringTable()->end())
+ HashSet<StringImpl*>::iterator iterator = stringTable().find<HashAndCharacters, HashAndCharactersTranslator>(buffer);
+ if (iterator == stringTable().end())
return 0;
return static_cast<AtomicStringImpl*>(*iterator);
}
@@ -292,6 +279,7 @@ AtomicString::operator UString() const
{
return m_string;
}
+#endif
DEFINE_GLOBAL(AtomicString, nullAtom)
DEFINE_GLOBAL(AtomicString, emptyAtom, "")
@@ -306,12 +294,6 @@ void AtomicString::init()
// Initialization is not thread safe, so this function must be called from the main thread first.
ASSERT(isMainThread());
-#if ENABLE(WORKERS)
- staticStringTable = new ThreadSpecific<HashSet<StringImpl*> >;
-#else
- staticStringTable = new HashSet<StringImpl*>;
-#endif
-
// Use placement new to initialize the globals.
new ((void*)&nullAtom) AtomicString;
new ((void*)&emptyAtom) AtomicString("");
diff --git a/WebCore/platform/text/AtomicString.h b/WebCore/platform/text/AtomicString.h
index ad034d9..f4efab9 100644
--- a/WebCore/platform/text/AtomicString.h
+++ b/WebCore/platform/text/AtomicString.h
@@ -89,14 +89,14 @@ public:
static void remove(StringImpl*);
+#if PLATFORM(CF) || (PLATFORM(QT) && PLATFORM(DARWIN))
+ AtomicString(CFStringRef s) : m_string(add(String(s).impl())) { }
+ CFStringRef createCFString() const { return m_string.createCFString(); }
+#endif
#ifdef __OBJC__
AtomicString(NSString* s) : m_string(add(String(s).impl())) { }
operator NSString*() const { return m_string; }
#endif
-#if PLATFORM(SYMBIAN)
- AtomicString(const TDesC& s) : m_string(add(String(s).impl())) { }
- operator TPtrC() const { return m_string; }
-#endif
#if PLATFORM(QT)
AtomicString(const QString& s) : m_string(add(String(s).impl())) { }
operator QString() const { return m_string; }
diff --git a/WebCore/platform/text/PlatformString.h b/WebCore/platform/text/PlatformString.h
index 73a44bd..35d3079 100644
--- a/WebCore/platform/text/PlatformString.h
+++ b/WebCore/platform/text/PlatformString.h
@@ -30,11 +30,12 @@
#include <wtf/PassRefPtr.h>
#if USE(JSC)
-#include <kjs/identifier.h>
+#include <runtime/Identifier.h>
#else
-// kjs/identifier.h includes HashMap.h. We explicitly include it in the case of
-// non-JSC builds to keep things consistent.
+// runtime/Identifier.h includes HashMap.h and HashSet.h. We explicitly include
+// them in the case of non-JSC builds to keep things consistent.
#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
#endif
#if PLATFORM(CF) || (PLATFORM(QT) && PLATFORM(DARWIN))
@@ -98,6 +99,8 @@ public:
int find(UChar c, int start = 0) const
{ return m_impl ? m_impl->find(c, start) : -1; }
+ int find(CharacterMatchFunctionPtr matchFunction, int start = 0) const
+ { return m_impl ? m_impl->find(matchFunction, start) : -1; }
int find(const char* str, int start = 0, bool caseSensitive = true) const
{ return m_impl ? m_impl->find(str, start, caseSensitive) : -1; }
int find(const String& str, int start = 0, bool caseSensitive = true) const
@@ -138,10 +141,14 @@ public:
String stripWhiteSpace() const;
String simplifyWhiteSpace() const;
-
+
+ String removeCharacters(CharacterMatchFunctionPtr) const;
+
// Return the string with case folded for case insensitive comparison.
String foldCase() const;
+ static String number(short);
+ static String number(unsigned short);
static String number(int);
static String number(unsigned);
static String number(long);
@@ -176,6 +183,12 @@ public:
// to ever prefer copy() over plain old assignment.
String copy() const;
+ // Makes a deep copy like copy() but only for a substring.
+ // (This ensures that you always get something suitable for a thread while subtring
+ // may not. For example, in the empty string case, StringImpl::substring returns
+ // empty() which is not safe for another thread.)
+ String substringCopy(unsigned pos, unsigned len = UINT_MAX) const;
+
bool isNull() const { return !m_impl; }
bool isEmpty() const;
@@ -200,12 +213,6 @@ public:
operator QString() const;
#endif
-#if PLATFORM(SYMBIAN)
- String(const TDesC&);
- operator TPtrC() const { return des(); }
- TPtrC des() const { if (!m_impl) return KNullDesC(); return m_impl->des(); }
-#endif
-
#if PLATFORM(WX)
String(const wxString&);
operator wxString() const;
@@ -296,6 +303,17 @@ inline int find(const UChar* characters, size_t length, UChar character, int sta
return -1;
}
+inline int find(const UChar* characters, size_t length, CharacterMatchFunctionPtr matchFunction, int startPosition)
+{
+ if (startPosition >= static_cast<int>(length))
+ return -1;
+ for (size_t i = startPosition; i < length; ++i) {
+ if (matchFunction(characters[i]))
+ return static_cast<int>(i);
+ }
+ return -1;
+}
+
inline int reverseFind(const UChar* characters, size_t length, UChar character, int startPosition)
{
if (startPosition >= static_cast<int>(length) || !length)
diff --git a/WebCore/platform/text/RegularExpression.cpp b/WebCore/platform/text/RegularExpression.cpp
index 1b933ff..6329b3b 100644
--- a/WebCore/platform/text/RegularExpression.cpp
+++ b/WebCore/platform/text/RegularExpression.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008 Collabora Ltd.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,86 +27,58 @@
#include "config.h"
#include "RegularExpression.h"
-#include "PlatformString.h"
#include "Logging.h"
-#include <wtf/RefCounted.h>
#include <pcre/pcre.h>
-#include <sys/types.h>
namespace WebCore {
-const size_t maxSubstrings = 10;
-const size_t maxOffsets = 3 * maxSubstrings;
-
class RegularExpression::Private : public RefCounted<Private> {
public:
- static PassRefPtr<Private> create() { return adoptRef(new Private); }
- static PassRefPtr<Private> create(const String& pattern, bool caseSensitive) { return adoptRef(new Private(pattern, caseSensitive)); }
-
+ static PassRefPtr<Private> create(const String& pattern, TextCaseSensitivity);
~Private();
- void compile(bool caseSensitive);
+ JSRegExp* regexp() const { return m_regexp; }
+ int lastMatchLength;
- String pattern;
- JSRegExp* regex;
-
- String lastMatchString;
- int lastMatchOffsets[maxOffsets];
- int lastMatchCount;
- int lastMatchPos;
- int lastMatchLength;
-
private:
- Private();
- Private(const String& pattern, bool caseSensitive);
-};
-
-RegularExpression::Private::Private()
- : pattern("")
-{
- compile(true);
-}
+ Private(const String& pattern, TextCaseSensitivity);
+ static JSRegExp* compile(const String& pattern, TextCaseSensitivity);
-RegularExpression::Private::Private(const String& p, bool caseSensitive)
- : pattern(p)
- , lastMatchPos(-1)
- , lastMatchLength(-1)
-{
- compile(caseSensitive);
-}
+ JSRegExp* m_regexp;
+};
-void RegularExpression::Private::compile(bool caseSensitive)
+inline JSRegExp* RegularExpression::Private::compile(const String& pattern, TextCaseSensitivity caseSensitivity)
{
const char* errorMessage;
- regex = jsRegExpCompile(pattern.characters(), pattern.length(),
- caseSensitive ? JSRegExpDoNotIgnoreCase : JSRegExpIgnoreCase, JSRegExpSingleLine,
+ JSRegExp* regexp = jsRegExpCompile(pattern.characters(), pattern.length(),
+ caseSensitivity == TextCaseSensitive ? JSRegExpDoNotIgnoreCase : JSRegExpIgnoreCase, JSRegExpSingleLine,
0, &errorMessage);
- if (!regex)
+ if (!regexp)
LOG_ERROR("RegularExpression: pcre_compile failed with '%s'", errorMessage);
+ return regexp;
}
-RegularExpression::Private::~Private()
+inline RegularExpression::Private::Private(const String& pattern, TextCaseSensitivity caseSensitivity)
+ : lastMatchLength(-1)
+ , m_regexp(compile(pattern, caseSensitivity))
{
- jsRegExpFree(regex);
}
-
-RegularExpression::RegularExpression()
- : d(Private::create())
+inline PassRefPtr<RegularExpression::Private> RegularExpression::Private::create(const String& pattern, TextCaseSensitivity caseSensitivity)
{
+ return adoptRef(new Private(pattern, caseSensitivity));
}
-RegularExpression::RegularExpression(const String& pattern, bool caseSensitive)
- : d(Private::create(pattern, caseSensitive))
+RegularExpression::Private::~Private()
{
+ jsRegExpFree(m_regexp);
}
-RegularExpression::RegularExpression(const char* pattern)
- : d(Private::create(pattern, true))
+RegularExpression::RegularExpression(const String& pattern, TextCaseSensitivity caseSensitivity)
+ : d(Private::create(pattern, caseSensitivity))
{
}
-
RegularExpression::RegularExpression(const RegularExpression& re)
: d(re.d)
{
@@ -118,52 +90,41 @@ RegularExpression::~RegularExpression()
RegularExpression& RegularExpression::operator=(const RegularExpression& re)
{
- RegularExpression tmp(re);
- tmp.d.swap(d);
+ d = re.d;
return *this;
}
-String RegularExpression::pattern() const
-{
- return d->pattern;
-}
-
int RegularExpression::match(const String& str, int startFrom, int* matchLength) const
{
+ if (!d->regexp())
+ return -1;
+
if (str.isNull())
return -1;
- d->lastMatchString = str;
// First 2 offsets are start and end offsets; 3rd entry is used internally by pcre
- d->lastMatchCount = jsRegExpExecute(d->regex, d->lastMatchString.characters(),
- d->lastMatchString.length(), startFrom, d->lastMatchOffsets, maxOffsets);
- if (d->lastMatchCount < 0) {
- if (d->lastMatchCount != JSRegExpErrorNoMatch)
- LOG_ERROR("RegularExpression: pcre_exec() failed with result %d", d->lastMatchCount);
- d->lastMatchPos = -1;
+ static const size_t maxOffsets = 3;
+ int offsets[maxOffsets];
+ int result = jsRegExpExecute(d->regexp(), str.characters(), str.length(), startFrom, offsets, maxOffsets);
+ if (result < 0) {
+ if (result != JSRegExpErrorNoMatch)
+ LOG_ERROR("RegularExpression: pcre_exec() failed with result %d", result);
d->lastMatchLength = -1;
- d->lastMatchString = String();
return -1;
}
-
+
// 1 means 1 match; 0 means more than one match. First match is recorded in offsets.
- d->lastMatchPos = d->lastMatchOffsets[0];
- d->lastMatchLength = d->lastMatchOffsets[1] - d->lastMatchOffsets[0];
+ d->lastMatchLength = offsets[1] - offsets[0];
if (matchLength)
*matchLength = d->lastMatchLength;
- return d->lastMatchPos;
-}
-
-int RegularExpression::search(const String& str, int startFrom) const
-{
- if (startFrom < 0)
- startFrom = str.length() - startFrom;
- return match(str, startFrom, 0);
+ return offsets[0];
}
int RegularExpression::searchRev(const String& str) const
{
- // FIXME: Total hack for now. Search forward, return the last, greedy match
+ // FIXME: This could be faster if it actually searched backwards.
+ // Instead, it just searches forwards, multiple times until it finds the last match.
+
int start = 0;
int pos;
int lastPos = -1;
@@ -180,17 +141,10 @@ int RegularExpression::searchRev(const String& str) const
start = pos + 1;
}
} while (pos != -1);
- d->lastMatchPos = lastPos;
d->lastMatchLength = lastMatchLength;
return lastPos;
}
-int RegularExpression::pos(int n)
-{
- ASSERT(n == 0);
- return d->lastMatchPos;
-}
-
int RegularExpression::matchedLength() const
{
return d->lastMatchLength;
diff --git a/WebCore/platform/text/RegularExpression.h b/WebCore/platform/text/RegularExpression.h
index 5d1991e..3254067 100644
--- a/WebCore/platform/text/RegularExpression.h
+++ b/WebCore/platform/text/RegularExpression.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 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
@@ -26,29 +26,21 @@
#ifndef RegularExpression_h
#define RegularExpression_h
-#include <wtf/RefPtr.h>
+#include "PlatformString.h"
namespace WebCore {
-class String;
-
class RegularExpression {
public:
- RegularExpression();
- RegularExpression(const String&, bool caseSensitive = false);
- RegularExpression(const char*);
+ RegularExpression(const String&, TextCaseSensitivity);
~RegularExpression();
RegularExpression(const RegularExpression&);
RegularExpression& operator=(const RegularExpression&);
- String pattern() const;
int match(const String&, int startFrom = 0, int* matchLength = 0) const;
-
- int search(const String&, int startFrom = 0) const;
int searchRev(const String&) const;
- int pos(int n = 0);
int matchedLength() const;
private:
diff --git a/WebCore/platform/text/String.cpp b/WebCore/platform/text/String.cpp
index 44500e1..638e45f 100644
--- a/WebCore/platform/text/String.cpp
+++ b/WebCore/platform/text/String.cpp
@@ -25,7 +25,7 @@
#include "FloatConversion.h"
#include "StringBuffer.h"
#include "TextEncoding.h"
-#include <kjs/dtoa.h>
+#include <wtf/dtoa.h>
#include <limits>
#include <stdarg.h>
#include <wtf/ASCIICType.h>
@@ -248,6 +248,13 @@ String String::substring(unsigned pos, unsigned len) const
return m_impl->substring(pos, len);
}
+String String::substringCopy(unsigned pos, unsigned len) const
+{
+ if (!m_impl)
+ return String();
+ return m_impl->substringCopy(pos, len);
+}
+
String String::lower() const
{
if (!m_impl)
@@ -276,6 +283,13 @@ String String::simplifyWhiteSpace() const
return m_impl->simplifyWhiteSpace();
}
+String String::removeCharacters(CharacterMatchFunctionPtr findMatch) const
+{
+ if (!m_impl)
+ return String();
+ return m_impl->removeCharacters(findMatch);
+}
+
String String::foldCase() const
{
if (!m_impl)
@@ -364,6 +378,16 @@ String String::format(const char *format, ...)
#endif
}
+String String::number(short n)
+{
+ return String::format("%hd", n);
+}
+
+String String::number(unsigned short n)
+{
+ return String::format("%hu", n);
+}
+
String String::number(int n)
{
return String::format("%d", n);
@@ -791,7 +815,7 @@ double charactersToDouble(const UChar* data, size_t length, bool* ok)
bytes[i] = data[i] < 0x7F ? data[i] : '?';
bytes[length] = '\0';
char* end;
- double val = JSC::strtod(bytes.data(), &end);
+ double val = WTF::strtod(bytes.data(), &end);
if (ok)
*ok = (end == 0 || *end == '\0');
return val;
@@ -823,7 +847,9 @@ PassRefPtr<SharedBuffer> utf8Buffer(const String& string)
} // namespace WebCore
#ifndef NDEBUG
-// For debugging only -- leaks memory
+// For use in the debugger - leaks memory
+WebCore::String* string(const char*);
+
WebCore::String* string(const char* s)
{
return new WebCore::String(s);
diff --git a/WebCore/platform/text/StringHash.h b/WebCore/platform/text/StringHash.h
index c6e08a6..336dce3 100644
--- a/WebCore/platform/text/StringHash.h
+++ b/WebCore/platform/text/StringHash.h
@@ -21,8 +21,9 @@
#ifndef StringHash_h
#define StringHash_h
-#include "AtomicStringImpl.h"
+#include "AtomicString.h"
#include "PlatformString.h"
+#include <wtf/HashFunctions.h>
#include <wtf/HashTraits.h>
#include <wtf/unicode/Unicode.h>
@@ -76,9 +77,6 @@ namespace WebCore {
};
class CaseFoldingHash {
- private:
- // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
- static const unsigned PHI = 0x9e3779b9U;
public:
// Paul Hsieh's SuperFastHash
// http://www.azillionmonkeys.com/qed/hash.html
@@ -86,7 +84,7 @@ namespace WebCore {
{
unsigned l = length;
const UChar* s = data;
- uint32_t hash = PHI;
+ uint32_t hash = WTF::stringHashingStartValue;
uint32_t tmp;
int rem = l & 1;
@@ -136,7 +134,7 @@ namespace WebCore {
unsigned l = length;
const char* s = str;
- uint32_t hash = PHI;
+ uint32_t hash = WTF::stringHashingStartValue;
uint32_t tmp;
int rem = l & 1;
@@ -199,10 +197,18 @@ namespace WebCore {
{
return hash(key.impl());
}
+ static unsigned hash(const AtomicString& key)
+ {
+ return hash(key.impl());
+ }
static bool equal(const String& a, const String& b)
{
return equal(a.impl(), b.impl());
}
+ static bool equal(const AtomicString& a, const AtomicString& b)
+ {
+ return (a == b) || equal(a.impl(), b.impl());
+ }
static const bool safeToCompareToEmptyOrDeleted = false;
};
diff --git a/WebCore/platform/text/StringImpl.cpp b/WebCore/platform/text/StringImpl.cpp
index 911c0dc..0556f8e 100644
--- a/WebCore/platform/text/StringImpl.cpp
+++ b/WebCore/platform/text/StringImpl.cpp
@@ -33,8 +33,10 @@
#include "StringHash.h"
#include "TextBreakIterator.h"
#include "TextEncoding.h"
-#include <kjs/dtoa.h>
+#include "ThreadGlobalData.h"
+#include <wtf/dtoa.h>
#include <wtf/Assertions.h>
+#include <wtf/Threading.h>
#include <wtf/unicode/Unicode.h>
using namespace WTF;
@@ -164,8 +166,7 @@ StringImpl::~StringImpl()
StringImpl* StringImpl::empty()
{
- static StringImpl* e = new StringImpl;
- return e;
+ return threadGlobalData().emptyString();
}
bool StringImpl::containsOnlyWhitespace()
@@ -188,6 +189,17 @@ PassRefPtr<StringImpl> StringImpl::substring(unsigned pos, unsigned len)
return create(m_data + pos, len);
}
+PassRefPtr<StringImpl> StringImpl::substringCopy(unsigned pos, unsigned len)
+{
+ if (pos >= m_length)
+ pos = m_length;
+ if (len > m_length - pos)
+ len = m_length - pos;
+ if (!len)
+ return adoptRef(new StringImpl);
+ return substring(pos, len);
+}
+
UChar32 StringImpl::characterStartingAt(unsigned i)
{
if (U16_IS_SINGLE(m_data[i]))
@@ -334,6 +346,38 @@ PassRefPtr<StringImpl> StringImpl::stripWhiteSpace()
return create(m_data + start, end + 1 - start);
}
+PassRefPtr<StringImpl> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch)
+{
+ const UChar* from = m_data;
+ const UChar* fromend = from + m_length;
+
+ // Assume the common case will not remove any characters
+ while (from != fromend && !findMatch(*from))
+ from++;
+ if (from == fromend)
+ return this;
+
+ StringBuffer data(m_length);
+ UChar* to = data.characters();
+ unsigned outc = from - m_data;
+
+ if (outc)
+ memcpy(to, m_data, outc * sizeof(UChar));
+
+ while (true) {
+ while (from != fromend && findMatch(*from))
+ from++;
+ while (from != fromend && !findMatch(*from))
+ to[outc++] = *from++;
+ if (from == fromend)
+ break;
+ }
+
+ data.shrink(outc);
+
+ return adopt(data);
+}
+
PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace()
{
StringBuffer data(m_length);
@@ -510,6 +554,11 @@ int StringImpl::find(UChar c, int start)
return WebCore::find(m_data, m_length, c, start);
}
+int StringImpl::find(CharacterMatchFunctionPtr matchFunction, int start)
+{
+ return WebCore::find(m_data, m_length, matchFunction, start);
+}
+
int StringImpl::find(StringImpl* str, int index, bool caseSensitive)
{
/*
diff --git a/WebCore/platform/text/StringImpl.h b/WebCore/platform/text/StringImpl.h
index 57f64c8..281aa37 100644
--- a/WebCore/platform/text/StringImpl.h
+++ b/WebCore/platform/text/StringImpl.h
@@ -47,12 +47,17 @@ struct HashAndCharactersTranslator;
struct StringHash;
struct UCharBufferTranslator;
+enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive };
+
+typedef bool (*CharacterMatchFunctionPtr)(UChar);
+
class StringImpl : public RefCounted<StringImpl> {
friend class AtomicString;
friend struct CStringTranslator;
friend struct HashAndCharactersTranslator;
friend struct UCharBufferTranslator;
private:
+ friend class ThreadGlobalData;
StringImpl();
StringImpl(const UChar*, unsigned length);
StringImpl(const char*, unsigned length);
@@ -94,6 +99,12 @@ public:
// Since StringImpl objects are immutable, there's no other reason to make a copy.
PassRefPtr<StringImpl> copy();
+ // Makes a deep copy like copy() but only for a substring.
+ // (This ensures that you always get something suitable for a thread while subtring
+ // may not. For example, in the empty string case, substring returns empty() which
+ // is not safe for another thread.)
+ PassRefPtr<StringImpl> substringCopy(unsigned pos, unsigned len = UINT_MAX);
+
PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX);
UChar operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; }
@@ -124,14 +135,17 @@ public:
PassRefPtr<StringImpl> stripWhiteSpace();
PassRefPtr<StringImpl> simplifyWhiteSpace();
+ PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr);
+
int find(const char*, int index = 0, bool caseSensitive = true);
int find(UChar, int index = 0);
+ int find(CharacterMatchFunctionPtr, int index = 0);
int find(StringImpl*, int index, bool caseSensitive = true);
int reverseFind(UChar, int index);
int reverseFind(StringImpl*, int index, bool caseSensitive = true);
- bool startsWith(StringImpl* m_data, bool caseSensitive = true) { return find(m_data, 0, caseSensitive) == 0; }
+ bool startsWith(StringImpl* m_data, bool caseSensitive = true) { return reverseFind(m_data, 0, caseSensitive) == 0; }
bool endsWith(StringImpl*, bool caseSensitive = true);
PassRefPtr<StringImpl> replace(UChar, UChar);
diff --git a/WebCore/platform/text/TextCodecICU.cpp b/WebCore/platform/text/TextCodecICU.cpp
index 0a324a2..72d45ad 100644
--- a/WebCore/platform/text/TextCodecICU.cpp
+++ b/WebCore/platform/text/TextCodecICU.cpp
@@ -30,10 +30,12 @@
#include "CharacterNames.h"
#include "CString.h"
#include "PlatformString.h"
+#include "ThreadGlobalData.h"
#include <unicode/ucnv.h>
#include <unicode/ucnv_cb.h>
#include <wtf/Assertions.h>
#include <wtf/StringExtras.h>
+#include <wtf/Threading.h>
using std::auto_ptr;
using std::min;
@@ -42,7 +44,16 @@ namespace WebCore {
const size_t ConversionBufferSize = 16384;
-static UConverter* cachedConverterICU;
+ICUConverterWrapper::~ICUConverterWrapper()
+{
+ if (converter)
+ ucnv_close(converter);
+}
+
+static UConverter*& cachedConverterICU()
+{
+ return threadGlobalData().cachedConverterICU().converter;
+}
static auto_ptr<TextCodec> newTextCodecICU(const TextEncoding& encoding, const void*)
{
@@ -95,12 +106,12 @@ void TextCodecICU::registerExtendedEncodingNames(EncodingNameRegistrar registrar
standardName = "GBK";
// Similarly, EUC-KR encodings all map to an extended version.
else if (strcmp(standardName, "KSC_5601") == 0 || strcmp(standardName, "EUC-KR") == 0 || strcmp(standardName, "cp1363") == 0)
- standardName = "windows-949-2000";
+ standardName = "windows-949";
// And so on.
else if (strcasecmp(standardName, "iso-8859-9") == 0) // This name is returned in different case by ICU 3.2 and 3.6.
standardName = "windows-1254";
else if (strcmp(standardName, "TIS-620") == 0)
- standardName = "windows-874-2000";
+ standardName = "windows-874";
registrar(standardName, standardName);
@@ -132,19 +143,23 @@ void TextCodecICU::registerExtendedEncodingNames(EncodingNameRegistrar registrar
registrar("xmacukrainian", "x-mac-cyrillic");
#endif
registrar("cnbig5", "Big5");
- registrar("cngb", "EUC-CN");
+ registrar("xxbig5", "Big5");
+ registrar("cngb", "GBK");
+ registrar("csgb231280", "GBK");
+ registrar("xeuccn", "GBK");
+ registrar("xgbk", "GBK");
registrar("csISO88598I", "ISO_8859-8-I");
- registrar("csgb231280", "EUC-CN");
- registrar("dos874", "cp874");
registrar("koi", "KOI8-R");
registrar("logical", "ISO-8859-8-I");
registrar("unicode11utf8", "UTF-8");
registrar("unicode20utf8", "UTF-8");
+ registrar("xunicode20utf8", "UTF-8");
registrar("visual", "ISO-8859-8");
registrar("winarabic", "windows-1256");
registrar("winbaltic", "windows-1257");
registrar("wincyrillic", "windows-1251");
- registrar("iso885911", "windows874-2000");
+ registrar("iso885911", "windows-874");
+ registrar("dos874", "windows-874");
registrar("wingreek", "windows-1253");
registrar("winhebrew", "windows-1255");
registrar("winlatin2", "windows-1250");
@@ -153,15 +168,8 @@ void TextCodecICU::registerExtendedEncodingNames(EncodingNameRegistrar registrar
registrar("xcp1250", "windows-1250");
registrar("xcp1251", "windows-1251");
registrar("xeuc", "EUC-JP");
- registrar("xeuccn", "EUC-CN");
- registrar("xgbk", "EUC-CN");
- registrar("xunicode20utf8", "UTF-8");
- registrar("xwindows949", "windows-949-2000");
- registrar("xxbig5", "Big5");
-
- // This alias is present in modern versions of ICU, but it has no standard name,
- // so we give one to it manually. It is not present in ICU 3.2.
- registrar("windows874", "windows874-2000");
+ registrar("xwindows949", "windows-949");
+ registrar("xuhc", "windows-949");
// These aliases are present in modern versions of ICU, but use different codecs, and have no standard names.
// They are not present in ICU 3.2.
@@ -205,9 +213,10 @@ TextCodecICU::~TextCodecICU()
void TextCodecICU::releaseICUConverter() const
{
if (m_converterICU) {
- if (cachedConverterICU)
- ucnv_close(cachedConverterICU);
- cachedConverterICU = m_converterICU;
+ UConverter*& cachedConverter = cachedConverterICU();
+ if (cachedConverter)
+ ucnv_close(cachedConverter);
+ cachedConverter = m_converterICU;
m_converterICU = 0;
}
}
@@ -221,12 +230,13 @@ void TextCodecICU::createICUConverter() const
UErrorCode err;
- if (cachedConverterICU) {
+ UConverter*& cachedConverter = cachedConverterICU();
+ if (cachedConverter) {
err = U_ZERO_ERROR;
- const char* cachedName = ucnv_getName(cachedConverterICU, &err);
+ const char* cachedName = ucnv_getName(cachedConverter, &err);
if (U_SUCCESS(err) && m_encoding == cachedName) {
- m_converterICU = cachedConverterICU;
- cachedConverterICU = 0;
+ m_converterICU = cachedConverter;
+ cachedConverter = 0;
return;
}
}
@@ -422,7 +432,7 @@ CString TextCodecICU::encode(const UChar* characters, size_t length, Unencodable
// until then, we change the backslash into a yen sign.
// Encoding will change the yen sign back into a backslash.
String copy(characters, length);
- copy.replace('\\', m_encoding.backslashAsCurrencySymbol());
+ copy = m_encoding.displayString(copy.impl());
const UChar* source = copy.characters();
const UChar* sourceLimit = source + copy.length();
diff --git a/WebCore/platform/text/TextCodecICU.h b/WebCore/platform/text/TextCodecICU.h
index 9c9a4a7b..f07758f 100644
--- a/WebCore/platform/text/TextCodecICU.h
+++ b/WebCore/platform/text/TextCodecICU.h
@@ -64,6 +64,16 @@ namespace WebCore {
mutable bool m_needsGBKFallbacks;
};
+ struct ICUConverterWrapper {
+ ICUConverterWrapper()
+ : converter(0)
+ {
+ }
+ ~ICUConverterWrapper();
+
+ UConverter* converter;
+ };
+
} // namespace WebCore
#endif // TextCodecICU_h
diff --git a/WebCore/platform/text/TextCodecUTF16.cpp b/WebCore/platform/text/TextCodecUTF16.cpp
index 88e4e73..a4d0d28 100644
--- a/WebCore/platform/text/TextCodecUTF16.cpp
+++ b/WebCore/platform/text/TextCodecUTF16.cpp
@@ -65,7 +65,7 @@ void TextCodecUTF16::registerCodecs(TextCodecRegistrar registrar)
registrar("UTF-16BE", newStreamingTextDecoderUTF16BE, 0);
}
-String TextCodecUTF16::decode(const char* bytes, size_t length, bool, bool stopOnError, bool& sawError)
+String TextCodecUTF16::decode(const char* bytes, size_t length, bool, bool, bool&)
{
if (!length)
return String();
@@ -89,18 +89,19 @@ String TextCodecUTF16::decode(const char* bytes, size_t length, bool, bool stopO
numChars -= 1;
}
- if (m_littleEndian)
+ if (m_littleEndian) {
for (size_t i = 0; i < numChars; ++i) {
UChar c = p[0] | (p[1] << 8);
p += 2;
*q++ = c;
}
- else
+ } else {
for (size_t i = 0; i < numChars; ++i) {
UChar c = (p[0] << 8) | p[1];
p += 2;
*q++ = c;
}
+ }
if (numBytes & 1) {
ASSERT(!m_haveBufferedByte);
diff --git a/WebCore/platform/text/TextEncoding.cpp b/WebCore/platform/text/TextEncoding.cpp
index 9026049..063d96b 100644
--- a/WebCore/platform/text/TextEncoding.cpp
+++ b/WebCore/platform/text/TextEncoding.cpp
@@ -39,6 +39,7 @@
#endif
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
+#include <wtf/StdLibExtras.h>
namespace WebCore {
@@ -49,13 +50,21 @@ static void addEncodingName(HashSet<const char*>& set, const char* name)
set.add(atomicName);
}
+static const TextEncoding& UTF7Encoding()
+{
+ static TextEncoding globalUTF7Encoding("UTF-7");
+ return globalUTF7Encoding;
+}
+
TextEncoding::TextEncoding(const char* name)
: m_name(atomicCanonicalTextEncodingName(name))
+ , m_backslashAsCurrencySymbol(backslashAsCurrencySymbol())
{
}
TextEncoding::TextEncoding(const String& name)
: m_name(atomicCanonicalTextEncodingName(name.characters(), name.length()))
+ , m_backslashAsCurrencySymbol(backslashAsCurrencySymbol())
{
}
@@ -122,7 +131,7 @@ bool TextEncoding::isJapanese() const
if (noExtendedTextEncodingNameUsed())
return false;
- static HashSet<const char*> set;
+ DEFINE_STATIC_LOCAL(HashSet<const char*>, set, ());
if (set.isEmpty()) {
addEncodingName(set, "x-mac-japanese");
addEncodingName(set, "cp932");
@@ -154,9 +163,29 @@ UChar TextEncoding::backslashAsCurrencySymbol() const
return (m_name == a || m_name == b) ? 0x00A5 : '\\';
}
-const TextEncoding& TextEncoding::closest8BitEquivalent() const
+bool TextEncoding::isNonByteBasedEncoding() const
+{
+ return *this == UTF16LittleEndianEncoding()
+ || *this == UTF16BigEndianEncoding()
+ || *this == UTF32BigEndianEncoding()
+ || *this == UTF32LittleEndianEncoding();
+}
+
+const TextEncoding& TextEncoding::closestByteBasedEquivalent() const
{
- if (*this == UTF16BigEndianEncoding() || *this == UTF16LittleEndianEncoding())
+ if (isNonByteBasedEncoding())
+ return UTF8Encoding();
+ return *this;
+}
+
+// HTML5 specifies that UTF-8 be used in form submission when a form is
+// is a part of a document in UTF-16 probably because UTF-16 is not a
+// byte-based encoding and can contain 0x00. By extension, the same
+// should be done for UTF-32. In case of UTF-7, it is a byte-based encoding,
+// but it's fraught with problems and we'd rather steer clear of it.
+const TextEncoding& TextEncoding::encodingForFormSubmission() const
+{
+ if (isNonByteBasedEncoding() || *this == UTF7Encoding())
return UTF8Encoding();
return *this;
}
@@ -197,7 +226,6 @@ const TextEncoding& UTF32LittleEndianEncoding()
return globalUTF32LittleEndianEncoding;
}
-
const TextEncoding& UTF8Encoding()
{
static TextEncoding globalUTF8Encoding("UTF-8");
diff --git a/WebCore/platform/text/TextEncoding.h b/WebCore/platform/text/TextEncoding.h
index 0a0ab8c..b2bb816 100644
--- a/WebCore/platform/text/TextEncoding.h
+++ b/WebCore/platform/text/TextEncoding.h
@@ -44,8 +44,23 @@ namespace WebCore {
const char* name() const { return m_name; }
bool usesVisualOrdering() const;
bool isJapanese() const;
- UChar backslashAsCurrencySymbol() const;
- const TextEncoding& closest8BitEquivalent() const;
+
+ PassRefPtr<StringImpl> displayString(PassRefPtr<StringImpl> str) const {
+ if (m_backslashAsCurrencySymbol == '\\' || !str)
+ return str;
+ return str->replace('\\', m_backslashAsCurrencySymbol);
+ }
+ void displayBuffer(UChar* characters, unsigned len) const {
+ if (m_backslashAsCurrencySymbol == '\\')
+ return;
+ for (unsigned i = 0; i < len; ++i) {
+ if (characters[i] == '\\')
+ characters[i] = m_backslashAsCurrencySymbol;
+ }
+ }
+
+ const TextEncoding& closestByteBasedEquivalent() const;
+ const TextEncoding& encodingForFormSubmission() const;
String decode(const char* str, size_t length) const
{
@@ -56,7 +71,11 @@ namespace WebCore {
CString encode(const UChar*, size_t length, UnencodableHandling) const;
private:
+ UChar backslashAsCurrencySymbol() const;
+
const char* m_name;
+ UChar m_backslashAsCurrencySymbol;
+ bool isNonByteBasedEncoding() const;
};
inline bool operator==(const TextEncoding& a, const TextEncoding& b) { return a.name() == b.name(); }
diff --git a/WebCore/platform/text/TextEncodingRegistry.cpp b/WebCore/platform/text/TextEncodingRegistry.cpp
index 3f1f078..2d89fac 100644
--- a/WebCore/platform/text/TextEncodingRegistry.cpp
+++ b/WebCore/platform/text/TextEncodingRegistry.cpp
@@ -32,8 +32,11 @@
#include "TextCodecUTF16.h"
#include <wtf/ASCIICType.h>
#include <wtf/Assertions.h>
+#include <wtf/HashFunctions.h>
#include <wtf/HashMap.h>
+#include <wtf/StdLibExtras.h>
#include <wtf/StringExtras.h>
+#include <wtf/Threading.h>
#if USE(ICU_UNICODE)
#include "TextCodecICU.h"
@@ -57,10 +60,6 @@ const size_t maxEncodingNameLength = 63;
// it will properly skip those characters too.
struct TextEncodingNameHash {
- // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
- // or anything like that.
- static const unsigned PHI = 0x9e3779b9U;
-
static bool equal(const char* s1, const char* s2)
{
char c1;
@@ -83,7 +82,7 @@ struct TextEncodingNameHash {
// http://burtleburtle.net/bob/hash/doobs.html
static unsigned hash(const char* s)
{
- unsigned h = PHI;
+ unsigned h = WTF::stringHashingStartValue;
for (;;) {
char c;
do {
@@ -113,6 +112,15 @@ struct TextCodecFactory {
typedef HashMap<const char*, const char*, TextEncodingNameHash> TextEncodingNameMap;
typedef HashMap<const char*, TextCodecFactory> TextCodecMap;
+static Mutex& encodingRegistryMutex()
+{
+ // We don't have to use AtomicallyInitializedStatic here because
+ // this function is called on the main thread for any page before
+ // it is used in worker threads.
+ DEFINE_STATIC_LOCAL(Mutex, mutex, ());
+ return mutex;
+}
+
static TextEncodingNameMap* textEncodingNameMap;
static TextCodecMap* textCodecMap;
static bool didExtendTextCodecMaps;
@@ -154,13 +162,17 @@ static void addToTextEncodingNameMap(const char* alias, const char* name)
static void addToTextCodecMap(const char* name, NewTextCodecFunction function, const void* additionalData)
{
- TextEncoding encoding(name);
- ASSERT(encoding.isValid());
- textCodecMap->add(encoding.name(), TextCodecFactory(function, additionalData));
+ const char* atomicName = textEncodingNameMap->get(name);
+ ASSERT(atomicName);
+ textCodecMap->add(atomicName, TextCodecFactory(function, additionalData));
}
static void buildBaseTextCodecMaps()
{
+ ASSERT(isMainThread());
+ ASSERT(!textCodecMap);
+ ASSERT(!textEncodingNameMap);
+
textCodecMap = new TextCodecMap;
textEncodingNameMap = new TextEncodingNameMap;
@@ -199,6 +211,8 @@ static void extendTextCodecMaps()
std::auto_ptr<TextCodec> newTextCodec(const TextEncoding& encoding)
{
+ MutexLocker lock(encodingRegistryMutex());
+
ASSERT(textCodecMap);
TextCodecFactory factory = textCodecMap->get(encoding.name());
ASSERT(factory.function);
@@ -211,6 +225,9 @@ const char* atomicCanonicalTextEncodingName(const char* name)
return 0;
if (!textEncodingNameMap)
buildBaseTextCodecMaps();
+
+ MutexLocker lock(encodingRegistryMutex());
+
if (const char* atomicName = textEncodingNameMap->get(name))
return atomicName;
if (didExtendTextCodecMaps)
@@ -238,6 +255,7 @@ const char* atomicCanonicalTextEncodingName(const UChar* characters, size_t leng
bool noExtendedTextEncodingNameUsed()
{
+ // If the calling thread did not use extended encoding names, it is fine for it to use a stale false value.
return !didExtendTextCodecMaps;
}
diff --git a/WebCore/platform/text/TextStream.cpp b/WebCore/platform/text/TextStream.cpp
index 5b7a0c7..eb4bae7 100644
--- a/WebCore/platform/text/TextStream.cpp
+++ b/WebCore/platform/text/TextStream.cpp
@@ -33,6 +33,11 @@ namespace WebCore {
static const size_t printBufferSize = 100; // large enough for any integer or floating point value in string format, including trailing null character
+TextStream& TextStream::operator<<(bool b)
+{
+ return *this << (b ? "1" : "0");
+}
+
TextStream& TextStream::operator<<(int i)
{
char buffer[printBufferSize];
diff --git a/WebCore/platform/text/TextStream.h b/WebCore/platform/text/TextStream.h
index 6fb3f4b..71034f3 100644
--- a/WebCore/platform/text/TextStream.h
+++ b/WebCore/platform/text/TextStream.h
@@ -35,6 +35,7 @@ class String;
class TextStream {
public:
+ TextStream& operator<<(bool);
TextStream& operator<<(int);
TextStream& operator<<(unsigned);
TextStream& operator<<(long);
diff --git a/WebCore/platform/gtk/SystemTimeGtk.cpp b/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp
index 9d26d41..09096d7 100644
--- a/WebCore/platform/gtk/SystemTimeGtk.cpp
+++ b/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -13,20 +14,19 @@
*
* 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.
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
*/
#include "config.h"
-#include <glib.h>
+#include "TextBreakIteratorInternalICU.h"
namespace WebCore {
-double currentTime()
+const char* currentTextBreakLocaleID()
{
- GTimeVal now;
- g_get_current_time(&now);
- return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0);
+ return "en_us";
}
-}
+} // namespace WebCore
diff --git a/WebCore/platform/text/mac/ShapeArabic.c b/WebCore/platform/text/mac/ShapeArabic.c
index 6dbc008..1e0d91b 100644
--- a/WebCore/platform/text/mac/ShapeArabic.c
+++ b/WebCore/platform/text/mac/ShapeArabic.c
@@ -347,8 +347,7 @@ isTashkeelChar(UChar ch) {
*/
static int32_t
shapeUnicode(UChar *dest, int32_t sourceLength,
- int32_t destSize,uint32_t options,
- UErrorCode *pErrorCode,
+ int32_t destSize,
int tashkeelFlag) {
int32_t i, iend;
@@ -528,11 +527,11 @@ int32_t shapeArabic(const UChar *source, int32_t sourceLength, UChar *dest, int3
switch(options&U_SHAPE_LETTERS_MASK) {
case U_SHAPE_LETTERS_SHAPE :
/* Call the shaping function with tashkeel flag == 1 */
- destLength = shapeUnicode(dest,sourceLength,destCapacity,options,pErrorCode,1);
+ destLength = shapeUnicode(dest,sourceLength,destCapacity,1);
break;
case U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED :
/* Call the shaping function with tashkeel flag == 0 */
- destLength = shapeUnicode(dest,sourceLength,destCapacity,options,pErrorCode,0);
+ destLength = shapeUnicode(dest,sourceLength,destCapacity,0);
break;
case U_SHAPE_LETTERS_UNSHAPE :
ASSERT_NOT_REACHED();
diff --git a/WebCore/platform/text/mac/StringImplMac.mm b/WebCore/platform/text/mac/StringImplMac.mm
index 2180b94..3e0731c 100644
--- a/WebCore/platform/text/mac/StringImplMac.mm
+++ b/WebCore/platform/text/mac/StringImplMac.mm
@@ -21,6 +21,8 @@
#include "config.h"
#include "StringImpl.h"
+#include <Foundation/Foundation.h>
+
namespace WebCore {
StringImpl::operator NSString *()
diff --git a/WebCore/platform/text/mac/TextCodecMac.cpp b/WebCore/platform/text/mac/TextCodecMac.cpp
index ac1f0fb..3baf21f 100644
--- a/WebCore/platform/text/mac/TextCodecMac.cpp
+++ b/WebCore/platform/text/mac/TextCodecMac.cpp
@@ -31,7 +31,9 @@
#include "CharacterNames.h"
#include "CharsetData.h"
#include "PlatformString.h"
+#include "ThreadGlobalData.h"
#include <wtf/Assertions.h>
+#include <wtf/Threading.h>
using std::auto_ptr;
using std::min;
@@ -43,8 +45,10 @@ namespace WebCore {
const size_t ConversionBufferSize = 16384;
-static TECObjectRef cachedConverterTEC;
-static TECTextEncodingID cachedConverterEncoding = invalidEncoding;
+static TECConverterWrapper& cachedConverterTEC()
+{
+ return threadGlobalData().cachedConverterTEC();
+}
void TextCodecMac::registerEncodingNames(EncodingNameRegistrar registrar)
{
@@ -91,22 +95,26 @@ TextCodecMac::~TextCodecMac()
void TextCodecMac::releaseTECConverter() const
{
if (m_converterTEC) {
- if (cachedConverterTEC != 0)
- TECDisposeConverter(cachedConverterTEC);
- cachedConverterTEC = m_converterTEC;
- cachedConverterEncoding = m_encoding;
+ TECConverterWrapper& cachedConverter = cachedConverterTEC();
+ if (cachedConverter.converter)
+ TECDisposeConverter(cachedConverter.converter);
+ cachedConverter.converter = m_converterTEC;
+ cachedConverter.encoding = m_encoding;
m_converterTEC = 0;
}
}
OSStatus TextCodecMac::createTECConverter() const
{
- bool cachedEncodingEqual = cachedConverterEncoding == m_encoding;
- cachedConverterEncoding = invalidEncoding;
+ TECConverterWrapper& cachedConverter = cachedConverterTEC();
+
+ bool cachedEncodingEqual = cachedConverter.encoding == m_encoding;
+ cachedConverter.encoding = invalidEncoding;
+
+ if (cachedEncodingEqual && cachedConverter.converter) {
+ m_converterTEC = cachedConverter.converter;
+ cachedConverter.converter = 0;
- if (cachedEncodingEqual && cachedConverterTEC) {
- m_converterTEC = cachedConverterTEC;
- cachedConverterTEC = 0;
TECClearConverterContextInfo(m_converterTEC);
} else {
OSStatus status = TECCreateConverter(&m_converterTEC, m_encoding,
@@ -116,7 +124,7 @@ OSStatus TextCodecMac::createTECConverter() const
TECSetBasicOptions(m_converterTEC, kUnicodeForceASCIIRangeMask);
}
-
+
return noErr;
}
diff --git a/WebCore/platform/text/mac/TextCodecMac.h b/WebCore/platform/text/mac/TextCodecMac.h
index aee4a97..3e7a237 100644
--- a/WebCore/platform/text/mac/TextCodecMac.h
+++ b/WebCore/platform/text/mac/TextCodecMac.h
@@ -60,6 +60,14 @@ namespace WebCore {
mutable TECObjectRef m_converterTEC;
};
+ struct TECConverterWrapper {
+ TECConverterWrapper() : converter(0), encoding(invalidEncoding) { }
+ ~TECConverterWrapper() { if (converter) TECDisposeConverter(converter); }
+
+ TECObjectRef converter;
+ TECTextEncodingID encoding;
+ };
+
} // namespace WebCore
#endif // TextCodecMac_h
diff --git a/WebCore/platform/win/COMPtr.h b/WebCore/platform/win/COMPtr.h
index 784495a..692706f 100644
--- a/WebCore/platform/win/COMPtr.h
+++ b/WebCore/platform/win/COMPtr.h
@@ -26,7 +26,9 @@
#ifndef COMPtr_h
#define COMPtr_h
+#ifndef NOMINMAX
#define NOMINMAX
+#endif
#include <guiddef.h>
#include <unknwn.h>
diff --git a/WebCore/platform/win/ClipboardWin.cpp b/WebCore/platform/win/ClipboardWin.cpp
index 129d881..7a88c3a 100644
--- a/WebCore/platform/win/ClipboardWin.cpp
+++ b/WebCore/platform/win/ClipboardWin.cpp
@@ -333,10 +333,15 @@ static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String&
fgd->fgd[0].dwFlags = FD_FILESIZE;
fgd->fgd[0].nFileSizeLow = image->image()->data()->size();
- String extension(".");
- extension += WebCore::MIMETypeRegistry::getPreferredExtensionForMIMEType(image->response().mimeType());
const String& preferredTitle = title.isEmpty() ? image->response().suggestedFilename() : title;
- fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, extension.length() ? (TCHAR*)extension.charactersWithNullTermination() : 0, false);
+ String extension = image->image()->filenameExtension();
+ if (extension.isEmpty()) {
+ // Do not continue processing in the rare and unusual case where a decoded image is not able
+ // to provide a filename extension. Something tricky (like a bait-n-switch) is going on
+ return 0;
+ }
+ extension.insert(".", 0);
+ fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, (TCHAR*)extension.charactersWithNullTermination(), false);
if (fsPath.length() <= 0) {
GlobalUnlock(memObj);
diff --git a/WebCore/platform/win/ContextMenuItemWin.cpp b/WebCore/platform/win/ContextMenuItemWin.cpp
index bd10c91..648d593 100644
--- a/WebCore/platform/win/ContextMenuItemWin.cpp
+++ b/WebCore/platform/win/ContextMenuItemWin.cpp
@@ -102,8 +102,7 @@ LPMENUITEMINFO ContextMenuItem::releasePlatformDescription()
ContextMenuItemType ContextMenuItem::type() const
{
ContextMenuItemType type = ActionType;
-
- if ((m_platformDescription->fType & MFT_STRING) && m_platformDescription->hSubMenu)
+ if (((m_platformDescription->fType & ~MFT_OWNERDRAW) == MFT_STRING) && m_platformDescription->hSubMenu)
type = SubmenuType;
else if (m_platformDescription->fType & MFT_SEPARATOR)
type = SeparatorType;
@@ -187,7 +186,7 @@ void ContextMenuItem::setEnabled(bool enabled)
bool ContextMenuItem::enabled() const
{
- return m_platformDescription->fState & MFS_ENABLED;
+ return !(m_platformDescription->fState & MFS_DISABLED);
}
}
diff --git a/WebCore/platform/win/DragImageCGWin.cpp b/WebCore/platform/win/DragImageCGWin.cpp
index 7788572..77b358b 100644
--- a/WebCore/platform/win/DragImageCGWin.cpp
+++ b/WebCore/platform/win/DragImageCGWin.cpp
@@ -37,6 +37,11 @@
namespace WebCore {
+void deallocContext(CGContextRef target)
+{
+ CGContextRelease(target);
+}
+
HBITMAP allocImage(HDC dc, IntSize size, CGContextRef *targetRef)
{
HBITMAP hbmp;
diff --git a/WebCore/platform/win/DragImageCairoWin.cpp b/WebCore/platform/win/DragImageCairoWin.cpp
index 5fff64f..1b8fb06 100644
--- a/WebCore/platform/win/DragImageCairoWin.cpp
+++ b/WebCore/platform/win/DragImageCairoWin.cpp
@@ -29,25 +29,170 @@
#include "CachedImage.h"
#include "GraphicsContext.h"
#include "Image.h"
-#include "NotImplemented.h"
#include "RetainPtr.h"
+#include <cairo-win32.h>
+#include "GraphicsContextPlatformPrivateCairo.h"
+
#include <windows.h>
+extern "C" {
+typedef struct _cairo* CairoContextRef;
+}
+
namespace WebCore {
+void deallocContext(CairoContextRef target)
+{
+ cairo_destroy(target);
+}
+
+HBITMAP allocImage(HDC dc, IntSize size, CairoContextRef* targetRef)
+{
+ BITMAPINFO bmpInfo = {0};
+ bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmpInfo.bmiHeader.biWidth = size.width();
+ bmpInfo.bmiHeader.biHeight = size.height(); // Must be positive!
+ bmpInfo.bmiHeader.biPlanes = 1;
+ bmpInfo.bmiHeader.biBitCount = 32;
+ bmpInfo.bmiHeader.biCompression = BI_RGB;
+ bmpInfo.bmiHeader.biClrUsed = 0; // unused
+ bmpInfo.bmiHeader.biClrImportant = 0;
+
+ LPVOID bits;
+ HBITMAP hbmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, &bits, 0, 0);
+
+ // At this point, we have a Cairo surface that points to a Windows DIB. The DIB interprets
+ // with the opposite meaning of positive Y axis, so everything we draw into this cairo
+ // context is going to be upside down.
+ if (!targetRef)
+ return hbmp;
+
+ cairo_surface_t* bitmapContext = cairo_image_surface_create_for_data((unsigned char*)bits,
+ CAIRO_FORMAT_ARGB32,
+ bmpInfo.bmiHeader.biWidth,
+ bmpInfo.bmiHeader.biHeight,
+ bmpInfo.bmiHeader.biWidth * 4);
+
+ if (!bitmapContext) {
+ DeleteObject(hbmp);
+ return 0;
+ }
+
+ *targetRef = cairo_create (bitmapContext);
+ cairo_surface_destroy (bitmapContext);
+
+ // At this point, we have a Cairo surface that points to a Windows DIB. The DIB interprets
+ // with the opposite meaning of positive Y axis, so everything we draw into this cairo
+ // context is going to be upside down.
+ //
+ // So, we must invert the CTM for the context so that drawing commands will be flipped
+ // before they get written to the internal buffer.
+ cairo_matrix_t matrix;
+ cairo_matrix_init(&matrix, 1.0, 0.0, 0.0, -1.0, 0.0, size.height());
+ cairo_set_matrix(*targetRef, &matrix);
+
+ return hbmp;
+}
+
+static cairo_surface_t* createCairoContextFromBitmap(HBITMAP bitmap)
+{
+ BITMAP info;
+ GetObject(bitmap, sizeof(info), &info);
+ ASSERT(info.bmBitsPixel == 32);
+
+ // At this point, we have a Cairo surface that points to a Windows BITMAP. The BITMAP
+ // has the opposite meaning of positive Y axis, so everything we draw into this cairo
+ // context is going to be upside down.
+ return cairo_image_surface_create_for_data((unsigned char*)info.bmBits,
+ CAIRO_FORMAT_ARGB32,
+ info.bmWidth,
+ info.bmHeight,
+ info.bmWidthBytes);
+}
+
DragImageRef scaleDragImage(DragImageRef image, FloatSize scale)
{
- notImplemented();
+ // FIXME: due to the way drag images are done on windows we need
+ // to preprocess the alpha channel <rdar://problem/5015946>
+ if (!image)
+ return 0;
+
+ IntSize srcSize = dragImageSize(image);
+ IntSize dstSize(static_cast<int>(srcSize.width() * scale.width()), static_cast<int>(srcSize.height() * scale.height()));
+
+ HBITMAP hbmp = 0;
+ HDC dc = GetDC(0);
+ HDC dstDC = CreateCompatibleDC(dc);
+
+ if (!dstDC)
+ goto exit;
+
+ CairoContextRef targetContext;
+ hbmp = allocImage(dstDC, dstSize, &targetContext);
+ if (!hbmp)
+ goto exit;
+
+ cairo_surface_t* srcImage = createCairoContextFromBitmap(image);
+
+ // 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(targetContext, 0, dstSize.height());
+ cairo_scale(targetContext, scale.width(), -scale.height());
+ cairo_set_source_surface (targetContext, srcImage, 0.0, 0.0);
- return image;
+ // Now we can paint and get the correct result
+ cairo_paint(targetContext);
+
+ cairo_surface_destroy (srcImage);
+ cairo_destroy(targetContext);
+ ::DeleteObject(image);
+ image = 0;
+
+exit:
+ if (!hbmp)
+ hbmp = image;
+ if (dstDC)
+ DeleteDC(dstDC);
+ ReleaseDC(0, dc);
+ return hbmp;
}
DragImageRef createDragImageFromImage(Image* img)
{
- notImplemented();
+ HBITMAP hbmp = 0;
+ HDC dc = GetDC(0);
+ HDC workingDC = CreateCompatibleDC(dc);
+ if (!workingDC)
+ goto exit;
+
+ CairoContextRef drawContext = 0;
+ hbmp = allocImage(workingDC, img->size(), &drawContext);
+ if (!hbmp)
+ goto exit;
+
+ if (!drawContext) {
+ ::DeleteObject(hbmp);
+ hbmp = 0;
+ }
+
+ cairo_set_source_rgb (drawContext, 1.0, 0.0, 1.0);
+ cairo_fill_preserve (drawContext);
+
+ cairo_surface_t* srcImage = img->nativeImageForCurrentFrame();
+
+ // Draw the image.
+ cairo_set_source_surface(drawContext, srcImage, 0.0, 0.0);
+ cairo_paint(drawContext);
+
+ cairo_destroy (drawContext);
- return 0;
+exit:
+ if (workingDC)
+ DeleteDC(workingDC);
+ ReleaseDC(0, dc);
+ return hbmp;
}
}
diff --git a/WebCore/platform/win/LoggingWin.cpp b/WebCore/platform/win/LoggingWin.cpp
new file mode 100644
index 0000000..bb0e4f4
--- /dev/null
+++ b/WebCore/platform/win/LoggingWin.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Logging.h"
+
+#include "PlatformString.h"
+#include <wtf/OwnArrayPtr.h>
+
+namespace WebCore {
+
+static inline void initializeWithUserDefault(WTFLogChannel& channel)
+{
+ DWORD length = GetEnvironmentVariableA(channel.defaultName, 0, 0);
+ if (!length)
+ return;
+
+ OwnArrayPtr<char> buffer(new char[length]);
+
+ if (!GetEnvironmentVariableA(channel.defaultName, buffer.get(), length))
+ return;
+
+ String variableValue(buffer.get());
+
+ static const String& hexadecimalPrefix = *new String("0x");
+ if (variableValue.length() < 3 || !variableValue.startsWith(hexadecimalPrefix, false)) {
+ LOG_ERROR("Unable to parse hex value for %s (%s), logging is off", channel.defaultName, buffer.get());
+ return;
+ }
+
+ String unprefixedValue = variableValue.substring(2);
+
+ // Now parse the unprefixed string as a hexadecimal number.
+ bool parsedSuccessfully = false;
+ unsigned logLevel = unprefixedValue.toUIntStrict(&parsedSuccessfully, 16);
+
+ if (!parsedSuccessfully) {
+ LOG_ERROR("Unable to parse hex value for %s (%s), logging is off", channel.defaultName, buffer.get());
+ return;
+ }
+
+ if ((logLevel & channel.mask) == channel.mask)
+ channel.state = WTFLogChannelOn;
+ else
+ channel.state = WTFLogChannelOff;
+}
+
+void InitializeLoggingChannelsIfNecessary()
+{
+ static bool haveInitializedLoggingChannels = false;
+ if (haveInitializedLoggingChannels)
+ return;
+ haveInitializedLoggingChannels = true;
+
+ initializeWithUserDefault(LogNotYetImplemented);
+ initializeWithUserDefault(LogFrames);
+ initializeWithUserDefault(LogLoading);
+ initializeWithUserDefault(LogPopupBlocking);
+ initializeWithUserDefault(LogEvents);
+ initializeWithUserDefault(LogEditing);
+ initializeWithUserDefault(LogTextConversion);
+ initializeWithUserDefault(LogIconDatabase);
+ initializeWithUserDefault(LogSQLDatabase);
+ initializeWithUserDefault(LogSpellingAndGrammar);
+ initializeWithUserDefault(LogBackForward);
+ initializeWithUserDefault(LogHistory);
+ initializeWithUserDefault(LogPageCache);
+ initializeWithUserDefault(LogPlatformLeaks);
+ initializeWithUserDefault(LogNetwork);
+ initializeWithUserDefault(LogFTP);
+ initializeWithUserDefault(LogThreading);
+ initializeWithUserDefault(LogStorageAPI);
+ initializeWithUserDefault(LogMedia);
+ initializeWithUserDefault(LogPlugin);
+ initializeWithUserDefault(LogArchives);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/win/MIMETypeRegistryWin.cpp b/WebCore/platform/win/MIMETypeRegistryWin.cpp
index 06c6f36..6885402 100644
--- a/WebCore/platform/win/MIMETypeRegistryWin.cpp
+++ b/WebCore/platform/win/MIMETypeRegistryWin.cpp
@@ -32,16 +32,6 @@
namespace WebCore
{
-String getMIMETypeForUTI(const String & uti)
-{
- String mimeType;
- // FIXME: This is an ugly hack: public.type -> image/type mimetype
- if (int dotLocation = uti.reverseFind('.')) {
- mimeType = String("image/")+uti.substring(dotLocation + 1);
- }
- return mimeType;
-}
-
static String mimeTypeForExtension(const String& extension)
{
String ext = "." + extension;
@@ -59,14 +49,6 @@ static String mimeTypeForExtension(const String& extension)
String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type)
{
- String mimeType;
-
- int semiColonPos = type.find(';');
- if (semiColonPos < 0)
- mimeType = type;
- else
- mimeType = type.substring(0, semiColonPos);
-
String path = "MIME\\Database\\Content Type\\" + type;
WCHAR extStr[MAX_PATH];
DWORD extStrLen = sizeof(extStr);
@@ -109,6 +91,8 @@ String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
mimetypeMap.add("ico", "image/ico");
mimetypeMap.add("cur", "image/ico");
mimetypeMap.add("bmp", "image/bmp");
+ mimetypeMap.add("wml", "text/vnd.wap.wml");
+ mimetypeMap.add("wmlc", "application/vnd.wap.wmlc");
}
String result = mimetypeMap.get(ext);
if (result.isEmpty()) {
diff --git a/WebCore/platform/win/PopupMenuWin.cpp b/WebCore/platform/win/PopupMenuWin.cpp
index 64b8a59..59ea563 100644
--- a/WebCore/platform/win/PopupMenuWin.cpp
+++ b/WebCore/platform/win/PopupMenuWin.cpp
@@ -50,8 +50,6 @@ static const int defaultAnimationDuration = 200;
// Maximum height of a popup window
static const int maxPopupHeight = 320;
-static const int popupWindowAlphaPercent = 95;
-
const int optionSpacingMiddle = 1;
const int popupWindowBorderWidth = 1;
@@ -99,7 +97,7 @@ void PopupMenu::show(const IntRect& r, FrameView* v, int index)
if (!m_popup) {
registerPopup();
- DWORD exStyle = WS_EX_LAYERED | WS_EX_LTRREADING;
+ DWORD exStyle = WS_EX_LTRREADING;
// Even though we already know our size and location at this point, we pass (0,0,0,0) as our size/location here.
// We need to wait until after the call to ::SetWindowLongPtr to set our size so that in our WM_SIZE handler we can get access to the PopupMenu object
@@ -112,7 +110,6 @@ void PopupMenu::show(const IntRect& r, FrameView* v, int index)
return;
::SetWindowLongPtr(m_popup, 0, (LONG_PTR)this);
- ::SetLayeredWindowAttributes(m_popup, 0, (255 * popupWindowAlphaPercent) / 100, LWA_ALPHA);
}
if (!m_scrollbar)
@@ -526,13 +523,12 @@ void PopupMenu::paint(const IntRect& damageRect, HDC hdc)
itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
itemFont.update(m_popupClient->fontSelector());
}
- context.setFont(itemFont);
// Draw the item text
if (itemStyle.isVisible()) {
int textX = max(0, client()->clientPaddingLeft() - client()->clientInsetLeft());
int textY = itemRect.y() + itemFont.ascent() + (itemRect.height() - itemFont.height()) / 2;
- context.drawBidiText(textRun, IntPoint(textX, textY));
+ context.drawBidiText(itemFont, textRun, IntPoint(textX, textY));
}
}
diff --git a/WebCore/platform/win/SharedTimerWin.cpp b/WebCore/platform/win/SharedTimerWin.cpp
index b611659..da27a53 100644
--- a/WebCore/platform/win/SharedTimerWin.cpp
+++ b/WebCore/platform/win/SharedTimerWin.cpp
@@ -27,9 +27,9 @@
#include "SharedTimer.h"
#include "Page.h"
-#include "SystemTime.h"
#include "Widget.h"
#include <wtf/Assertions.h>
+#include <wtf/CurrentTime.h>
// Note: wx headers set defines that affect the configuration of windows.h
// so we must include the wx header first to get unicode versions of functions,
@@ -41,6 +41,10 @@
#include <windows.h>
#include <mmsystem.h>
+#if PLATFORM(WIN)
+#include "PluginView.h"
+#endif
+
// These aren't in winuser.h with the MSVS 2003 Platform SDK,
// so use default values in that case.
#ifndef USER_TIMER_MINIMUM
@@ -55,10 +59,6 @@
#define QS_RAWINPUT 0x0400
#endif
-#if PLATFORM(WIN)
-#include "PluginView.h"
-#endif
-
namespace WebCore {
static UINT timerID;
@@ -68,7 +68,6 @@ static HWND timerWindowHandle = 0;
static UINT timerFiredMessage = 0;
static HANDLE timerQueue;
static HANDLE timer;
-static Mutex timerMutex;
static bool highResTimerActive;
static bool processingCustomTimerMessage = false;
static LONG pendingTimers;
@@ -139,17 +138,8 @@ void setSharedTimerFiredFunction(void (*f)())
sharedTimerFiredFunction = f;
}
-static void clearTimer()
-{
- MutexLocker locker(timerMutex);
- if (timerQueue && timer)
- DeleteTimerQueueTimer(timerQueue, timer, 0);
- timer = 0;
-}
-
static void NTAPI queueTimerProc(PVOID, BOOLEAN)
{
- clearTimer();
if (InterlockedIncrement(&pendingTimers) == 1)
PostMessage(timerWindowHandle, timerFiredMessage, 0, 0);
}
@@ -196,11 +186,9 @@ void setSharedTimerFireTime(double fireTime)
// Otherwise, delay the PostMessage via a CreateTimerQueueTimer
if (!timerQueue)
timerQueue = CreateTimerQueue();
- MutexLocker locker(timerMutex);
if (timer)
- timerSet = ChangeTimerQueueTimer(timerQueue, timer, intervalInMS, 0);
- else
- timerSet = CreateTimerQueueTimer(&timer, timerQueue, queueTimerProc, 0, intervalInMS, 0, WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE);
+ DeleteTimerQueueTimer(timerQueue, timer, 0);
+ timerSet = CreateTimerQueueTimer(&timer, timerQueue, queueTimerProc, 0, intervalInMS, 0, WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE);
}
}
@@ -209,13 +197,19 @@ void setSharedTimerFireTime(double fireTime)
KillTimer(timerWindowHandle, timerID);
timerID = 0;
}
- } else
+ } else {
timerID = SetTimer(timerWindowHandle, sharedTimerID, intervalInMS, 0);
+ timer = 0;
+ }
}
void stopSharedTimer()
{
- clearTimer();
+ if (timerQueue && timer) {
+ DeleteTimerQueueTimer(timerQueue, timer, 0);
+ timer = 0;
+ }
+
if (timerID) {
KillTimer(timerWindowHandle, timerID);
timerID = 0;
diff --git a/WebCore/platform/win/SystemTimeWin.cpp b/WebCore/platform/win/SystemTimeWin.cpp
index 473e8de..88ea145 100644
--- a/WebCore/platform/win/SystemTimeWin.cpp
+++ b/WebCore/platform/win/SystemTimeWin.cpp
@@ -26,30 +26,23 @@
#include "config.h"
#include "SystemTime.h"
-#include <DateMath.h>
#include <windows.h>
-#if COMPILER(MINGW)
+#if COMPILER(MINGW) || (PLATFORM(QT) && COMPILER(MSVC))
#include <float.h>
#define FLOAT_MAX FLT_MAX
#endif
namespace WebCore {
-double currentTime()
-{
- // Call through to our high-resolution JSC time code, since calls like GetSystemTimeAsFileTime and ftime are only accurate within 15ms.
- // This resolution can be improved with timeBeginPeriod/timeEndPeriod on Vista, but these calls don't
- // improve the resolution of date/time getters (GetSystemTimeAsFileTime, ftime, etc.) on XP.
- return JSC::getCurrentUTCTimeWithMicroseconds() * 0.001;
-}
-
float userIdleTime()
{
+#if !PLATFORM(WIN_CE)
LASTINPUTINFO lastInputInfo = {0};
lastInputInfo.cbSize = sizeof(LASTINPUTINFO);
if (::GetLastInputInfo(&lastInputInfo))
return (GetTickCount() - lastInputInfo.dwTime) * 0.001; // ::GetTickCount returns ms of uptime valid for up to 49.7 days.
+#endif
return FLT_MAX; // return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed.
}
diff --git a/WebCore/platform/win/TemporaryLinkStubs.cpp b/WebCore/platform/win/TemporaryLinkStubs.cpp
index 80c8df0..71eed00 100644
--- a/WebCore/platform/win/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/win/TemporaryLinkStubs.cpp
@@ -33,5 +33,7 @@ namespace WebCore {
// <keygen>
String signedPublicKeyAndChallengeString(unsigned, const String&, const KURL&) { notImplemented(); return String(); }
void getSupportedKeySizes(Vector<String>&) { notImplemented(); }
-
+#if PLATFORM(CAIRO)
+void populateFontDatabase() { /* Not needed for GDI fonts */ }
+#endif
} // namespace WebCore
diff --git a/WebCore/platform/win/WebCoreTextRenderer.cpp b/WebCore/platform/win/WebCoreTextRenderer.cpp
index 75ce003..affeb9d 100644
--- a/WebCore/platform/win/WebCoreTextRenderer.cpp
+++ b/WebCore/platform/win/WebCoreTextRenderer.cpp
@@ -52,10 +52,8 @@ static void doDrawTextAtPoint(GraphicsContext& context, const String& text, cons
context.setFillColor(color);
if (isOneLeftToRightRun(run))
font.drawText(&context, run, point);
- else {
- context.setFont(font);
- context.drawBidiText(run, point);
- }
+ else
+ context.drawBidiText(font, run, point);
if (underlinedIndex >= 0) {
ASSERT(underlinedIndex < static_cast<int>(text.length()));
diff --git a/WebCore/platform/wx/ContextMenuItemWx.cpp b/WebCore/platform/wx/ContextMenuItemWx.cpp
new file mode 100644
index 0000000..51ebe13
--- /dev/null
+++ b/WebCore/platform/wx/ContextMenuItemWx.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include "config.h"
+
+#include "ContextMenuItem.h"
+#include "ContextMenu.h"
+#include "PlatformMenuDescription.h"
+
+using namespace WebCore;
+
+ContextMenuItem::ContextMenuItem(ContextMenu* subMenu)
+{
+ m_platformDescription.type = SubmenuType;
+ m_platformDescription.action = ContextMenuItemTagNoAction;
+ if (subMenu)
+ setSubMenu(subMenu);
+ else
+ m_platformDescription.subMenu = 0;
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action,
+ const String& title, ContextMenu* subMenu)
+{
+ m_platformDescription.type = type;
+ m_platformDescription.action = action;
+ m_platformDescription.title = title;
+ if (subMenu)
+ setSubMenu(subMenu);
+ else
+ m_platformDescription.subMenu = 0;
+}
+
+ContextMenuItem::~ContextMenuItem()
+{
+}
+
+PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
+{
+ return m_platformDescription;
+}
+
+ContextMenuItemType ContextMenuItem::type() const
+{
+ return m_platformDescription.type;
+}
+
+void ContextMenuItem::setType(ContextMenuItemType type)
+{
+ m_platformDescription.type = type;
+}
+
+ContextMenuAction ContextMenuItem::action() const
+{
+ return m_platformDescription.action;
+}
+
+void ContextMenuItem::setAction(ContextMenuAction action)
+{
+ m_platformDescription.action = action;
+}
+
+String ContextMenuItem::title() const
+{
+ return m_platformDescription.title;
+}
+
+void ContextMenuItem::setTitle(const String& title)
+{
+ m_platformDescription.title = title;
+}
+
+void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
+{
+ m_platformDescription.subMenu = subMenu->releasePlatformDescription();
+}
+
+void ContextMenuItem::setChecked(bool shouldCheck)
+{
+ m_platformDescription.checked = shouldCheck;
+}
+
+void ContextMenuItem::setEnabled(bool shouldEnable)
+{
+ m_platformDescription.enabled = shouldEnable;
+}
diff --git a/WebCore/platform/wx/ContextMenuWx.cpp b/WebCore/platform/wx/ContextMenuWx.cpp
new file mode 100644
index 0000000..6f1bc9c
--- /dev/null
+++ b/WebCore/platform/wx/ContextMenuWx.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include "config.h"
+
+#include "ContextMenu.h"
+#include "ContextMenuItem.h"
+#include "PlatformMenuDescription.h"
+#include "wx/menu.h"
+
+using namespace WebCore;
+
+typedef WTF::HashMap<int, ContextMenuAction> ItemActionMap;
+static ItemActionMap s_itemActions;
+
+ContextMenuItem* ContextMenu::itemWithId(int id)
+{
+ return new ContextMenuItem(ActionType, s_itemActions.get(id), "");
+}
+
+ContextMenu::ContextMenu(const HitTestResult& result) : m_hitTestResult(result)
+{
+ m_platformDescription = new wxMenu(0);
+}
+
+ContextMenu::~ContextMenu()
+{
+ if (m_platformDescription)
+ delete m_platformDescription;
+}
+
+void ContextMenu::appendItem(ContextMenuItem& item)
+{
+ if (!m_platformDescription)
+ return;
+
+ checkOrEnableIfNeeded(item);
+
+ PlatformMenuItemDescription itemDescription = item.releasePlatformDescription();
+ wxItemKind menuKindWx = ( itemDescription.type == CheckableActionType ) ? wxITEM_CHECK : wxITEM_NORMAL;
+ wxString titleWx(itemDescription.title);
+ int idWx = wxID_ANY;
+ wxMenuItem * itemWx;
+
+ ItemActionMap::const_iterator end = s_itemActions.end();
+ for (ItemActionMap::const_iterator it = s_itemActions.begin(); it != end; ++it) {
+ if (it->second == itemDescription.action)
+ idWx = it->first;
+ }
+
+ if (itemDescription.subMenu) {
+ itemWx = new wxMenuItem(m_platformDescription, idWx, titleWx, wxEmptyString, wxITEM_NORMAL, itemDescription.subMenu);
+ } else if (itemDescription.type != SeparatorType) {
+ itemWx = new wxMenuItem(m_platformDescription, idWx, titleWx, wxT(""), menuKindWx);
+ } else {
+ itemWx = new wxMenuItem(m_platformDescription);
+ }
+
+ s_itemActions.add(itemWx->GetId(), item.action());
+
+ m_platformDescription->Append(itemWx);
+ m_platformDescription->Enable(itemWx->GetId(), itemDescription.enabled);
+
+ if (menuKindWx == wxITEM_CHECK)
+ m_platformDescription->Check(itemWx->GetId(), itemDescription.checked);
+}
+
+void ContextMenu::setPlatformDescription(PlatformMenuDescription menu)
+{
+ if (!menu)
+ return;
+
+ if (m_platformDescription)
+ delete m_platformDescription;
+
+ m_platformDescription = menu;
+}
+
+PlatformMenuDescription ContextMenu::platformDescription() const
+{
+ return m_platformDescription;
+}
+
+PlatformMenuDescription ContextMenu::releasePlatformDescription()
+{
+ PlatformMenuDescription description = m_platformDescription;
+ m_platformDescription = 0;
+
+ return description;
+}
diff --git a/WebCore/platform/wx/LocalizedStringsWx.cpp b/WebCore/platform/wx/LocalizedStringsWx.cpp
index a315181..5bede52 100644
--- a/WebCore/platform/wx/LocalizedStringsWx.cpp
+++ b/WebCore/platform/wx/LocalizedStringsWx.cpp
@@ -68,177 +68,182 @@ String fileButtonNoFileSelectedLabel()
String contextMenuItemTagOpenLinkInNewWindow()
{
- return String();
+ return String("Open Link in New Window");
}
String contextMenuItemTagDownloadLinkToDisk()
{
- return String();
+ return String("Download Link to Disk");
}
String contextMenuItemTagCopyLinkToClipboard()
{
- return String();
+ return String("Copy Link to Clipboard");
}
String contextMenuItemTagOpenImageInNewWindow()
{
- return String();
+ return String("Open Image in New Window");
}
String contextMenuItemTagDownloadImageToDisk()
{
- return String();
+ return String("Download Image to Disk");
}
String contextMenuItemTagCopyImageToClipboard()
{
- return String();
+ return String("Copy Image to Clipboard");
}
String contextMenuItemTagOpenFrameInNewWindow()
{
- return String();
+ return String("Open Frame in New Window");
}
String contextMenuItemTagCopy()
{
- return String();
+ return String("Copy");
}
String contextMenuItemTagGoBack()
{
- return String();
+ return String("Go Back");
}
String contextMenuItemTagGoForward()
{
- return String();
+ return String("Go Forward");
}
String contextMenuItemTagStop()
{
- return String();
+ return String("Stop");
}
String contextMenuItemTagReload()
{
- return String();
+ return String("Reload");
}
String contextMenuItemTagCut()
{
- return String();
+ return String("Cut");
}
String contextMenuItemTagPaste()
{
- return String();
+ return String("Paste");
}
String contextMenuItemTagNoGuessesFound()
{
- return String();
+ return String("No Guesses Found");
}
String contextMenuItemTagIgnoreSpelling()
{
- return String();
+ return String("Ignore Spelling");
}
String contextMenuItemTagLearnSpelling()
{
- return String();
+ return String("Learn Spelling");
}
String contextMenuItemTagSearchWeb()
{
- return String();
+ return String("Search Web");
}
String contextMenuItemTagLookUpInDictionary()
{
- return String();
+ return String("Look Up in Dictionary");
}
String contextMenuItemTagOpenLink()
{
- return String();
+ return String("Open Link");
}
String contextMenuItemTagIgnoreGrammar()
{
- return String();
+ return String("Ignore Grammar");
}
String contextMenuItemTagSpellingMenu()
{
- return String();
+ return String("Spelling");
}
String contextMenuItemTagShowSpellingPanel(bool show)
{
- return String();
+ return String("Show Spelling Panel");
}
String contextMenuItemTagCheckSpelling()
{
- return String();
+ return String("Check Spelling");
}
String contextMenuItemTagCheckSpellingWhileTyping()
{
- return String();
+ return String("Check Spelling While Typing");
}
String contextMenuItemTagCheckGrammarWithSpelling()
{
- return String();
+ return String("Check Grammar with Spelling");
}
String contextMenuItemTagFontMenu()
{
- return String();
+ return String("Font");
}
String contextMenuItemTagBold()
{
- return String();
+ return String("Bold");
}
String contextMenuItemTagItalic()
{
- return String();
+ return String("Italic");
}
String contextMenuItemTagUnderline()
{
- return String();
+ return String("Underline");
}
String contextMenuItemTagOutline()
{
- return String();
+ return String("Outline");
}
String contextMenuItemTagWritingDirectionMenu()
{
- return String();
+ return String("Writing Direction");
+}
+
+String contextMenuItemTagTextDirectionMenu()
+{
+ return String("Text Direction");
}
String contextMenuItemTagDefaultDirection()
{
- return String();
+ return String("Default Direction");
}
String contextMenuItemTagLeftToRight()
{
- return String();
+ return String("Left to Right");
}
String contextMenuItemTagRightToLeft()
{
- return String();
+ return String("Right to Left");
}
String searchMenuNoRecentSearchesText()
diff --git a/WebCore/platform/wx/MimeTypeRegistryWx.cpp b/WebCore/platform/wx/MimeTypeRegistryWx.cpp
index c025d02..601cd9f 100644
--- a/WebCore/platform/wx/MimeTypeRegistryWx.cpp
+++ b/WebCore/platform/wx/MimeTypeRegistryWx.cpp
@@ -38,6 +38,7 @@ static const ExtensionMap extensionMap [] = {
{ "bmp", "image/bmp" },
{ "css", "text/css" },
{ "gif", "image/gif" },
+ { "htm", "text/html" },
{ "html", "text/html" },
{ "ico", "image/x-icon" },
{ "jpeg", "image/jpeg" },
diff --git a/WebCore/platform/wx/MouseEventWx.cpp b/WebCore/platform/wx/MouseEventWx.cpp
index c9468a9..a02d7ba 100644
--- a/WebCore/platform/wx/MouseEventWx.cpp
+++ b/WebCore/platform/wx/MouseEventWx.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "Assertions.h"
#include "PlatformMouseEvent.h"
-#include "SystemTime.h"
+#include <wtf/CurrentTime.h>
#include <wx/defs.h>
#include <wx/event.h>
@@ -69,7 +69,7 @@ PlatformMouseEvent::PlatformMouseEvent(const wxMouseEvent& event, const wxPoint&
else
m_clickCount = event.ButtonDClick() ? 2 : 1;
- m_timestamp = WebCore::currentTime();
+ m_timestamp = WTF::currentTime();
}
}
diff --git a/WebCore/platform/wx/PasteboardWx.cpp b/WebCore/platform/wx/PasteboardWx.cpp
index 3b71e9a..67697de 100644
--- a/WebCore/platform/wx/PasteboardWx.cpp
+++ b/WebCore/platform/wx/PasteboardWx.cpp
@@ -31,6 +31,7 @@
#include "Frame.h"
#include "KURL.h"
#include "markup.h"
+#include "NotImplemented.h"
#include "PlatformString.h"
#include <wx/defs.h>
@@ -53,27 +54,39 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete,
{
if (wxTheClipboard->Open())
{
- String text = frame->selectedText();
- text.replace('\\', frame->backslashAsCurrencySymbol());
-
- wxTheClipboard->SetData( new wxTextDataObject(text) );
+ wxTheClipboard->SetData( new wxTextDataObject(frame->selectedText()) );
wxTheClipboard->Close();
}
}
bool Pasteboard::canSmartReplace()
{
+ notImplemented();
return false;
}
String Pasteboard::plainText(Frame* frame)
{
+ notImplemented();
return String();
}
PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
bool allowPlainText, bool& chosePlainText)
{
+ RefPtr<DocumentFragment> fragment = 0;
+ if (wxTheClipboard->Open()) {
+ if (allowPlainText && wxTheClipboard->IsSupported( wxDF_TEXT )) {
+ wxTextDataObject data;
+ wxTheClipboard->GetData( data );
+ chosePlainText = true;
+ fragment = createFragmentFromText(context.get(), data.GetText());
+ }
+ wxTheClipboard->Close();
+ }
+ if (fragment)
+ return fragment.release();
+
return 0;
}
@@ -93,6 +106,7 @@ void Pasteboard::clear()
void Pasteboard::writeImage(Node*, const KURL&, const String& title)
{
+ notImplemented();
}
}
diff --git a/WebCore/platform/wx/RenderThemeWx.cpp b/WebCore/platform/wx/RenderThemeWx.cpp
index 05ebeb9..9b6dea5 100644
--- a/WebCore/platform/wx/RenderThemeWx.cpp
+++ b/WebCore/platform/wx/RenderThemeWx.cpp
@@ -34,6 +34,7 @@
#include "WebKit/wx/WebView.h"
+#include <wx/dcgraph.h>
#include <wx/defs.h>
#include <wx/renderer.h>
#include <wx/dcclient.h>
@@ -130,7 +131,12 @@ bool RenderThemeWx::isControlStyled(const RenderStyle* style, const BorderData&
if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart)
return style->border() != border;
- return RenderTheme::isControlStyled(style, border, background, backgroundColor);
+ // Normally CSS can be used to set properties of form controls (such as adding a background bitmap).
+ // However, for this to work RenderThemeWx needs to adjust uncustomized elements (e.g. buttons) to reflect the
+ // changes made by CSS. Since we don't do that right now, the native parts of form elements appear in odd places.
+ // Until we have time to implement that support, we return false here, so that we ignore customizations
+ // and always use the native theme drawing to draw form controls.
+ return false;
}
void RenderThemeWx::adjustRepaintRect(const RenderObject* o, IntRect& r)
@@ -250,8 +256,12 @@ bool RenderThemeWx::paintButton(RenderObject* o, const RenderObject::PaintInfo&
wxRendererNative::Get().DrawPushButton(window, *dc, r, flags);
else if(part == RadioPart) {
if (isChecked(o))
- flags |= wxCONTROL_CHECKED;
+ flags |= wxCONTROL_CHECKED;
+#if wxCHECK_VERSION(2,9,0)
+ wxRendererNative::Get().DrawRadioButton(window, *dc, r, flags);
+#else
wxRenderer_DrawRadioButton(window, *dc, r, flags);
+#endif
}
else if(part == CheckboxPart) {
if (isChecked(o))
@@ -270,7 +280,12 @@ bool RenderThemeWx::paintTextField(RenderObject* o, const RenderObject::PaintInf
{
wxWindow* window = o->view()->frameView()->platformWidget();
wxDC* dc = static_cast<wxDC*>(i.context->platformContext());
+#if wxCHECK_VERSION(2,9,0)
+ wxRendererNative::Get().DrawTextCtrl(window, *dc, r, 0);
+#else
wxRenderer_DrawTextCtrl(window, *dc, r, 0);
+#endif
+
return false;
}
@@ -298,7 +313,11 @@ bool RenderThemeWx::paintMenuList(RenderObject* o, const RenderObject::PaintInfo
if (isPressed(o))
flags |= wxCONTROL_PRESSED;
+#if wxCHECK_VERSION(2,9,0)
+ wxRendererNative::Get().DrawChoice(window, *dc, r, flags);
+#else
wxRenderer_DrawChoice(window, *dc, r, flags);
+#endif
return false;
}
diff --git a/WebCore/platform/wx/ScrollViewWx.cpp b/WebCore/platform/wx/ScrollViewWx.cpp
index 3822cba..254ac9f 100644
--- a/WebCore/platform/wx/ScrollViewWx.cpp
+++ b/WebCore/platform/wx/ScrollViewWx.cpp
@@ -306,6 +306,16 @@ void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode
vertical = m_data->vScrollbarMode;
}
+void ScrollView::platformSetCanBlitOnScroll(bool canBlitOnScroll)
+{
+ m_canBlitOnScroll = canBlitOnScroll;
+}
+
+bool ScrollView::platformCanBlitOnScroll() const
+{
+ return m_canBlitOnScroll;
+}
+
// used for subframes support
void ScrollView::platformAddChild(Widget* widget)
{
diff --git a/WebCore/platform/wx/SharedTimerWx.cpp b/WebCore/platform/wx/SharedTimerWx.cpp
index 19747ce..d95457b 100644
--- a/WebCore/platform/wx/SharedTimerWx.cpp
+++ b/WebCore/platform/wx/SharedTimerWx.cpp
@@ -27,10 +27,10 @@
#include "SharedTimer.h"
#include "NotImplemented.h"
-#include "SystemTime.h"
#include "Widget.h"
#include <wtf/Assertions.h>
+#include <wtf/CurrentTime.h>
#include <stdio.h>
#include "wx/defs.h"
diff --git a/WebCore/platform/wx/wxcode/gtk/non-kerned-drawing.cpp b/WebCore/platform/wx/wxcode/gtk/non-kerned-drawing.cpp
index b86a9bc..ed8fb09 100644
--- a/WebCore/platform/wx/wxcode/gtk/non-kerned-drawing.cpp
+++ b/WebCore/platform/wx/wxcode/gtk/non-kerned-drawing.cpp
@@ -28,6 +28,7 @@
#include "GraphicsContext.h"
#include "SimpleFontData.h"
+#include <wx/dcgraph.h>
#include <wx/defs.h>
#include <wx/dcclient.h>
#include <wx/gdicmn.h>