summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics')
-rw-r--r--WebCore/platform/graphics/BitmapImage.h25
-rw-r--r--WebCore/platform/graphics/Color.h12
-rw-r--r--WebCore/platform/graphics/ColorSpace.h35
-rw-r--r--WebCore/platform/graphics/FloatPoint.h16
-rw-r--r--WebCore/platform/graphics/FloatRect.cpp10
-rw-r--r--WebCore/platform/graphics/FloatRect.h21
-rw-r--r--WebCore/platform/graphics/FloatSize.h5
-rw-r--r--WebCore/platform/graphics/FontCache.h13
-rw-r--r--WebCore/platform/graphics/FontDescription.h17
-rw-r--r--WebCore/platform/graphics/FontFastPath.cpp4
-rw-r--r--WebCore/platform/graphics/FontSmoothingMode.h35
-rw-r--r--WebCore/platform/graphics/GeneratedImage.cpp6
-rw-r--r--WebCore/platform/graphics/GeneratedImage.h4
-rw-r--r--WebCore/platform/graphics/GlyphPageTreeNode.cpp6
-rw-r--r--WebCore/platform/graphics/Gradient.cpp2
-rw-r--r--WebCore/platform/graphics/Gradient.h10
-rw-r--r--WebCore/platform/graphics/GraphicsContext.cpp143
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h121
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.h650
-rw-r--r--WebCore/platform/graphics/GraphicsContextPrivate.h30
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.cpp34
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.h42
-rw-r--r--WebCore/platform/graphics/GraphicsLayerClient.h10
-rw-r--r--WebCore/platform/graphics/Icon.h1
-rw-r--r--WebCore/platform/graphics/Image.cpp18
-rw-r--r--WebCore/platform/graphics/Image.h16
-rw-r--r--WebCore/platform/graphics/ImageBuffer.h12
-rw-r--r--WebCore/platform/graphics/ImageSource.cpp (renamed from WebCore/platform/graphics/cairo/ImageSourceCairo.cpp)152
-rw-r--r--WebCore/platform/graphics/ImageSource.h47
-rw-r--r--WebCore/platform/graphics/IntPoint.h9
-rw-r--r--WebCore/platform/graphics/IntRect.h17
-rw-r--r--WebCore/platform/graphics/IntSize.h15
-rw-r--r--WebCore/platform/graphics/MediaPlayer.cpp62
-rw-r--r--WebCore/platform/graphics/MediaPlayer.h45
-rw-r--r--WebCore/platform/graphics/MediaPlayerPrivate.h15
-rw-r--r--WebCore/platform/graphics/Path.h9
-rw-r--r--WebCore/platform/graphics/Pattern.h5
-rw-r--r--WebCore/platform/graphics/SimpleFontData.cpp4
-rw-r--r--WebCore/platform/graphics/SimpleFontData.h21
-rw-r--r--WebCore/platform/graphics/TextRenderingMode.h35
-rw-r--r--WebCore/platform/graphics/android/AndroidAnimation.cpp313
-rw-r--r--WebCore/platform/graphics/android/AndroidAnimation.h205
-rw-r--r--WebCore/platform/graphics/android/BitmapAllocatorAndroid.cpp32
-rw-r--r--WebCore/platform/graphics/android/BitmapAllocatorAndroid.h31
-rw-r--r--WebCore/platform/graphics/android/FontAndroid.cpp10
-rw-r--r--WebCore/platform/graphics/android/FontCacheAndroid.cpp36
-rw-r--r--WebCore/platform/graphics/android/FontCustomPlatformData.cpp2
-rw-r--r--WebCore/platform/graphics/android/FontCustomPlatformData.h3
-rw-r--r--WebCore/platform/graphics/android/FontDataAndroid.cpp35
-rw-r--r--WebCore/platform/graphics/android/FontPlatformData.h39
-rw-r--r--WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp40
-rw-r--r--WebCore/platform/graphics/android/GlyphMapAndroid.cpp36
-rw-r--r--WebCore/platform/graphics/android/GradientAndroid.cpp10
-rw-r--r--WebCore/platform/graphics/android/GraphicsContextAndroid.cpp98
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp851
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.h156
-rw-r--r--WebCore/platform/graphics/android/ImageAndroid.cpp22
-rw-r--r--WebCore/platform/graphics/android/ImageBufferAndroid.cpp6
-rw-r--r--WebCore/platform/graphics/android/ImageBufferData.h2
-rw-r--r--WebCore/platform/graphics/android/ImageSourceAndroid.cpp26
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp383
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h136
-rw-r--r--WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h7
-rw-r--r--WebCore/platform/graphics/android/PathAndroid.cpp2
-rw-r--r--WebCore/platform/graphics/android/PatternAndroid.cpp2
-rw-r--r--WebCore/platform/graphics/android/PlatformGraphicsContext.cpp2
-rw-r--r--WebCore/platform/graphics/android/PlatformGraphicsContext.h3
-rw-r--r--WebCore/platform/graphics/android/SharedBufferStream.cpp32
-rw-r--r--WebCore/platform/graphics/android/SharedBufferStream.h31
-rw-r--r--WebCore/platform/graphics/android/SkBitmapRef.h2
-rw-r--r--WebCore/platform/graphics/android/android_graphics.cpp4
-rw-r--r--WebCore/platform/graphics/android/android_graphics.h2
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp34
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp458
-rw-r--r--WebCore/platform/graphics/cairo/ImageBufferCairo.cpp73
-rw-r--r--WebCore/platform/graphics/cairo/ImageCairo.cpp39
-rw-r--r--WebCore/platform/graphics/cairo/PathCairo.cpp14
-rw-r--r--WebCore/platform/graphics/cg/ColorCG.cpp12
-rw-r--r--WebCore/platform/graphics/cg/GradientCG.cpp11
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp628
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h23
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp79
-rw-r--r--WebCore/platform/graphics/cg/ImageCG.cpp126
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp73
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.h4
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.cpp23
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.h2
-rw-r--r--WebCore/platform/graphics/cg/PathCG.cpp10
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp25
-rw-r--r--WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp135
-rw-r--r--WebCore/platform/graphics/chromium/FontLinux.cpp88
-rw-r--r--WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/IconChromiumLinux.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/IconChromiumMac.cpp5
-rw-r--r--WebCore/platform/graphics/chromium/IconChromiumWin.cpp19
-rw-r--r--WebCore/platform/graphics/chromium/TransparencyWin.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/UniscribeHelper.cpp14
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.cpp78
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.h2
-rw-r--r--WebCore/platform/graphics/filters/FEColorMatrix.cpp11
-rw-r--r--WebCore/platform/graphics/filters/FEComponentTransfer.cpp92
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.cpp72
-rw-r--r--WebCore/platform/graphics/filters/FEGaussianBlur.cpp144
-rw-r--r--WebCore/platform/graphics/filters/FEGaussianBlur.h57
-rw-r--r--WebCore/platform/graphics/filters/Filter.h15
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.cpp18
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.h27
-rw-r--r--WebCore/platform/graphics/filters/ImageBufferFilter.cpp43
-rw-r--r--WebCore/platform/graphics/filters/ImageBufferFilter.h57
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.cpp27
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.h2
-rw-r--r--WebCore/platform/graphics/filters/SourceGraphic.cpp4
-rw-r--r--WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp243
-rw-r--r--WebCore/platform/graphics/gtk/DataSourceGStreamer.h54
-rw-r--r--WebCore/platform/graphics/gtk/FontGtk.cpp2
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformData.h2
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp11
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp7
-rw-r--r--WebCore/platform/graphics/gtk/IconGtk.cpp26
-rw-r--r--WebCore/platform/graphics/gtk/ImageGtk.cpp73
-rw-r--r--WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp631
-rw-r--r--WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h38
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp16
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp14
-rw-r--r--WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp353
-rw-r--r--WebCore/platform/graphics/gtk/VideoSinkGStreamer.h10
-rw-r--r--WebCore/platform/graphics/haiku/ColorHaiku.cpp54
-rw-r--r--WebCore/platform/graphics/haiku/FloatPointHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/FloatRectHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/FontCacheHaiku.cpp79
-rw-r--r--WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp45
-rw-r--r--WebCore/platform/graphics/haiku/FontCustomPlatformData.h44
-rw-r--r--WebCore/platform/graphics/haiku/FontHaiku.cpp116
-rw-r--r--WebCore/platform/graphics/haiku/FontPlatformData.h81
-rw-r--r--WebCore/platform/graphics/haiku/GradientHaiku.cpp53
-rw-r--r--WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp541
-rw-r--r--WebCore/platform/graphics/haiku/IconHaiku.cpp51
-rw-r--r--WebCore/platform/graphics/haiku/ImageBufferData.h43
-rw-r--r--WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp97
-rw-r--r--WebCore/platform/graphics/haiku/ImageHaiku.cpp152
-rw-r--r--WebCore/platform/graphics/haiku/IntPointHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/IntRectHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/IntSizeHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/PathHaiku.cpp161
-rw-r--r--WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp110
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.h52
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.mm160
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextController.cpp (renamed from WebCore/platform/graphics/mac/CoreTextController.cpp)273
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextController.h162
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp341
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp144
-rw-r--r--WebCore/platform/graphics/mac/CoreTextController.h116
-rw-r--r--WebCore/platform/graphics/mac/FontComplexTextMac.cpp (renamed from WebCore/platform/graphics/mac/FontMacCoreText.cpp)38
-rw-r--r--WebCore/platform/graphics/mac/FontCustomPlatformData.cpp21
-rw-r--r--WebCore/platform/graphics/mac/FontMac.mm34
-rw-r--r--WebCore/platform/graphics/mac/FontMacATSUI.mm626
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp1365
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContextMac.mm15
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.h32
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm214
-rw-r--r--WebCore/platform/graphics/mac/IconMac.mm35
-rw-r--r--WebCore/platform/graphics/mac/ImageMac.mm9
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h9
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm70
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm31
-rw-r--r--WebCore/platform/graphics/mac/WebLayer.mm2
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp68
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeSanitizer.h57
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp47
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeUtilities.h5
-rw-r--r--WebCore/platform/graphics/qt/ColorQt.cpp5
-rw-r--r--WebCore/platform/graphics/qt/FontCacheQt.cpp245
-rw-r--r--WebCore/platform/graphics/qt/FontCustomPlatformData.cpp2
-rw-r--r--WebCore/platform/graphics/qt/FontFallbackListQt.cpp138
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformData.h120
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformDataQt.cpp116
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp5
-rw-r--r--WebCore/platform/graphics/qt/FontQt43.cpp354
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp464
-rw-r--r--WebCore/platform/graphics/qt/IconQt.cpp16
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp73
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp382
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.h54
-rw-r--r--WebCore/platform/graphics/qt/ImageQt.cpp50
-rw-r--r--WebCore/platform/graphics/qt/ImageSourceQt.cpp173
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp31
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h3
-rw-r--r--WebCore/platform/graphics/qt/SimpleFontDataQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/StillImageQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/StillImageQt.h4
-rw-r--r--WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h2
-rw-r--r--WebCore/platform/graphics/skia/GradientSkia.cpp28
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp143
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp87
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp23
-rw-r--r--WebCore/platform/graphics/skia/ImageSourceSkia.cpp238
-rw-r--r--WebCore/platform/graphics/skia/NativeImageSkia.cpp5
-rw-r--r--WebCore/platform/graphics/skia/PathSkia.cpp21
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.cpp88
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.h2
-rw-r--r--WebCore/platform/graphics/skia/SkiaUtils.cpp15
-rw-r--r--WebCore/platform/graphics/transforms/TransformOperations.h2
-rw-r--r--WebCore/platform/graphics/transforms/TransformationMatrix.h7
-rw-r--r--WebCore/platform/graphics/win/FontCGWin.cpp30
-rw-r--r--WebCore/platform/graphics/win/FontCacheWin.cpp15
-rw-r--r--WebCore/platform/graphics/win/FontDatabase.cpp92
-rw-r--r--WebCore/platform/graphics/win/FontPlatformData.h1
-rw-r--r--WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp6
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCGWin.cpp12
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp4
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.cpp721
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.h144
-rw-r--r--WebCore/platform/graphics/win/IconWin.cpp22
-rw-r--r--WebCore/platform/graphics/win/ImageCGWin.cpp35
-rw-r--r--WebCore/platform/graphics/win/ImageCairoWin.cpp31
-rw-r--r--WebCore/platform/graphics/win/IntPointWin.cpp1
-rw-r--r--WebCore/platform/graphics/win/IntRectWin.cpp2
-rw-r--r--WebCore/platform/graphics/win/IntSizeWin.cpp1
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp79
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h14
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.cpp59
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.h9
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp8
-rw-r--r--WebCore/platform/graphics/win/WKCACFContextFlusher.cpp88
-rw-r--r--WebCore/platform/graphics/win/WKCACFContextFlusher.h60
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.cpp359
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.h248
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp449
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayerRenderer.h106
-rw-r--r--WebCore/platform/graphics/wince/ColorWince.cpp38
-rw-r--r--WebCore/platform/graphics/wince/FontCustomPlatformData.cpp12
-rw-r--r--WebCore/platform/graphics/wince/FontCustomPlatformData.h6
-rw-r--r--WebCore/platform/graphics/wince/GradientWince.cpp52
-rw-r--r--WebCore/platform/graphics/wince/GraphicsContextWince.cpp25
-rw-r--r--WebCore/platform/graphics/wince/ImageBufferData.h34
-rw-r--r--WebCore/platform/graphics/wince/ImageBufferWince.cpp246
-rw-r--r--WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h129
-rw-r--r--WebCore/platform/graphics/wince/MediaPlayerProxy.cpp145
-rw-r--r--WebCore/platform/graphics/wince/MediaPlayerProxy.h70
-rw-r--r--WebCore/platform/graphics/wince/PathWince.cpp163
-rw-r--r--WebCore/platform/graphics/wince/PlatformPathWince.cpp810
-rw-r--r--WebCore/platform/graphics/wince/PlatformPathWince.h178
-rw-r--r--WebCore/platform/graphics/wince/WinceGraphicsExtras.h39
-rw-r--r--WebCore/platform/graphics/wx/FontPlatformDataWx.cpp2
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp140
-rw-r--r--WebCore/platform/graphics/wx/IconWx.cpp47
-rw-r--r--WebCore/platform/graphics/wx/ImageBufferWx.cpp15
-rw-r--r--WebCore/platform/graphics/wx/ImageSourceWx.cpp226
-rw-r--r--WebCore/platform/graphics/wx/ImageWx.cpp19
-rw-r--r--WebCore/platform/graphics/wx/IntSizeWx.cpp45
-rw-r--r--WebCore/platform/graphics/wx/SimpleFontDataWx.cpp1
252 files changed, 16880 insertions, 5188 deletions
diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h
index 807c11b..0031df6 100644
--- a/WebCore/platform/graphics/BitmapImage.h
+++ b/WebCore/platform/graphics/BitmapImage.h
@@ -45,6 +45,10 @@ class NSImage;
typedef struct HBITMAP__ *HBITMAP;
#endif
+#if PLATFORM(HAIKU)
+class BBitmap;
+#endif
+
namespace WebCore {
struct FrameData;
}
@@ -136,12 +140,15 @@ public:
virtual CGImageRef getCGImageRef();
#endif
+#if PLATFORM(WIN) || (PLATFORM(QT) && PLATFORM(WIN_OS))
+ static PassRefPtr<BitmapImage> create(HBITMAP);
+#endif
#if PLATFORM(WIN)
virtual bool getHBITMAP(HBITMAP);
virtual bool getHBITMAPOfSize(HBITMAP, LPSIZE);
#endif
-#if PLATFORM(SGL)
+#if PLATFORM(ANDROID)
virtual void setURL(const String& str);
#endif
@@ -162,13 +169,19 @@ protected:
BitmapImage(ImageObserver* = 0);
#if PLATFORM(WIN)
- virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator);
+ virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator);
#endif
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
-#if PLATFORM(WX) || PLATFORM(WINCE)
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
+
+#if PLATFORM(WX) || (PLATFORM(WINCE) && !PLATFORM(QT))
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
-#endif
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
+#endif
+
+#if PLATFORM(HAIKU)
+ virtual BBitmap* getBBitmap() const;
+#endif
+
size_t currentFrame() const { return m_currentFrame; }
size_t frameCount();
NativeImagePtr frameAtIndex(size_t);
diff --git a/WebCore/platform/graphics/Color.h b/WebCore/platform/graphics/Color.h
index 5baa56e..c348166 100644
--- a/WebCore/platform/graphics/Color.h
+++ b/WebCore/platform/graphics/Color.h
@@ -26,6 +26,7 @@
#ifndef Color_h
#define Color_h
+#include <wtf/FastAllocBase.h>
#include <wtf/Platform.h>
#if PLATFORM(CG)
@@ -47,6 +48,10 @@ typedef struct _GdkColor GdkColor;
class wxColour;
#endif
+#if PLATFORM(HAIKU)
+struct rgb_color;
+#endif
+
namespace WebCore {
class String;
@@ -64,7 +69,7 @@ RGBA32 makeRGBAFromCMYKA(float c, float m, float y, float k, float a);
int differenceSquared(const Color&, const Color&);
-class Color {
+class Color : public FastAllocBase {
public:
Color() : m_color(0), m_valid(false) { }
Color(RGBA32 col) : m_color(col), m_valid(true) { }
@@ -121,6 +126,11 @@ public:
Color(CGColorRef);
#endif
+#if PLATFORM(HAIKU)
+ Color(const rgb_color&);
+ operator rgb_color() const;
+#endif
+
static bool parseHexColor(const String& name, RGBA32& rgb);
static const RGBA32 black = 0xFF000000;
diff --git a/WebCore/platform/graphics/ColorSpace.h b/WebCore/platform/graphics/ColorSpace.h
new file mode 100644
index 0000000..1bad58c
--- /dev/null
+++ b/WebCore/platform/graphics/ColorSpace.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ColorSpace_h
+#define ColorSpace_h
+
+namespace WebCore {
+
+ enum ColorSpace { DeviceColorSpace, sRGBColorSpace };
+
+} // namespace WebCore
+
+#endif // ColorSpace_h
diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h
index 0c97c49..45a1e83 100644
--- a/WebCore/platform/graphics/FloatPoint.h
+++ b/WebCore/platform/graphics/FloatPoint.h
@@ -36,7 +36,7 @@
typedef struct CGPoint CGPoint;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
typedef struct CGPoint NSPoint;
#else
@@ -51,6 +51,10 @@ class QPointF;
QT_END_NAMESPACE
#endif
+#if PLATFORM(HAIKU)
+class BPoint;
+#endif
+
#if PLATFORM(SKIA)
struct SkPoint;
#endif
@@ -80,7 +84,8 @@ public:
operator CGPoint() const;
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
FloatPoint(const NSPoint&);
operator NSPoint() const;
#endif
@@ -90,7 +95,12 @@ public:
operator QPointF() const;
#endif
-#if (PLATFORM(SKIA) || PLATFORM(SGL))
+#if PLATFORM(HAIKU)
+ FloatPoint(const BPoint&);
+ operator BPoint() const;
+#endif
+
+#if PLATFORM(SKIA)
operator SkPoint() const;
FloatPoint(const SkPoint&);
#endif
diff --git a/WebCore/platform/graphics/FloatRect.cpp b/WebCore/platform/graphics/FloatRect.cpp
index 532f719..7a54f21 100644
--- a/WebCore/platform/graphics/FloatRect.cpp
+++ b/WebCore/platform/graphics/FloatRect.cpp
@@ -102,12 +102,12 @@ void FloatRect::unite(const FloatRect& other)
m_size.setHeight(b - t);
}
-void FloatRect::scale(float s)
+void FloatRect::scale(float sx, float sy)
{
- m_location.setX(x() * s);
- m_location.setY(y() * s);
- m_size.setWidth(width() * s);
- m_size.setHeight(height() * s);
+ m_location.setX(x() * sx);
+ m_location.setY(y() * sy);
+ m_size.setWidth(width() * sx);
+ m_size.setHeight(height() * sy);
}
IntRect enclosingIntRect(const FloatRect& rect)
diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h
index e906812..2dc854d 100644
--- a/WebCore/platform/graphics/FloatRect.h
+++ b/WebCore/platform/graphics/FloatRect.h
@@ -33,7 +33,7 @@
typedef struct CGRect CGRect;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
typedef struct CGRect NSRect;
#else
@@ -51,7 +51,11 @@ QT_END_NAMESPACE
class wxRect2DDouble;
#endif
-#if (PLATFORM(SKIA) || PLATFORM(SGL))
+#if PLATFORM(HAIKU)
+class BRect;
+#endif
+
+#if PLATFORM(SKIA)
struct SkRect;
#endif
@@ -116,14 +120,16 @@ public:
m_size.setHeight(m_size.height() + dy + dy);
}
void inflate(float d) { inflateX(d); inflateY(d); }
- void scale(float s);
+ void scale(float s) { scale(s, s); }
+ void scale(float sx, float sy);
#if PLATFORM(CG)
FloatRect(const CGRect&);
operator CGRect() const;
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
FloatRect(const NSRect&);
operator NSRect() const;
#endif
@@ -138,7 +144,12 @@ public:
operator wxRect2DDouble() const;
#endif
-#if (PLATFORM(SKIA) || PLATFORM(SGL))
+#if PLATFORM(HAIKU)
+ FloatRect(const BRect&);
+ operator BRect() const;
+#endif
+
+#if PLATFORM(SKIA)
FloatRect(const SkRect&);
operator SkRect() const;
#endif
diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h
index 6e792b6..5a84fd1 100644
--- a/WebCore/platform/graphics/FloatSize.h
+++ b/WebCore/platform/graphics/FloatSize.h
@@ -34,7 +34,7 @@
typedef struct CGSize CGSize;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
typedef struct CGSize NSSize;
#else
@@ -79,7 +79,8 @@ public:
operator CGSize() const;
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
explicit FloatSize(const NSSize &); // don't do this implicitly since it's lossy
operator NSSize() const;
#endif
diff --git a/WebCore/platform/graphics/FontCache.h b/WebCore/platform/graphics/FontCache.h
index 3c0f2d9..4a6222b 100644
--- a/WebCore/platform/graphics/FontCache.h
+++ b/WebCore/platform/graphics/FontCache.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007-2008 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -49,7 +50,7 @@ class FontDescription;
class FontSelector;
class SimpleFontData;
-class FontCache {
+class FontCache : public Noncopyable {
public:
friend FontCache* fontCache();
@@ -63,7 +64,15 @@ public:
// Also implemented by the platform.
void platformInit();
-#if PLATFORM(WIN)
+#if PLATFORM(WINCE) && !PLATFORM(QT)
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+ IMLangFontLink2* getFontLinkInterface();
+#else
+ IMLangFontLink* getFontLinkInterface();
+#endif
+ static void comInitialize();
+ static void comUninitialize();
+#elif PLATFORM(WIN)
IMLangFontLink2* getFontLinkInterface();
#endif
diff --git a/WebCore/platform/graphics/FontDescription.h b/WebCore/platform/graphics/FontDescription.h
index c893b8a..fc63db9 100644
--- a/WebCore/platform/graphics/FontDescription.h
+++ b/WebCore/platform/graphics/FontDescription.h
@@ -27,7 +27,9 @@
#include "FontFamily.h"
#include "FontRenderingMode.h"
+#include "FontSmoothingMode.h"
#include "FontTraitsMask.h"
+#include "TextRenderingMode.h"
namespace WebCore {
@@ -61,6 +63,8 @@ public:
, m_usePrinterFont(false)
, m_renderingMode(NormalRenderingMode)
, m_keywordSize(0)
+ , m_fontSmoothing(AutoSmoothing)
+ , m_textRendering(AutoTextRendering)
{
}
@@ -80,8 +84,12 @@ public:
FontWeight bolderWeight() const;
GenericFamilyType genericFamily() const { return static_cast<GenericFamilyType>(m_genericFamily); }
bool usePrinterFont() const { return m_usePrinterFont; }
+ // only use fixed default size when there is only one font family, and that family is "monospace"
+ bool useFixedDefaultSize() const { return genericFamily() == MonospaceFamily && !family().next() && family().family() == "-webkit-monospace"; }
FontRenderingMode renderingMode() const { return static_cast<FontRenderingMode>(m_renderingMode); }
unsigned keywordSize() const { return m_keywordSize; }
+ FontSmoothingMode fontSmoothing() const { return static_cast<FontSmoothingMode>(m_fontSmoothing); }
+ TextRenderingMode textRenderingMode() const { return static_cast<TextRenderingMode>(m_textRendering); }
FontTraitsMask traitsMask() const;
@@ -96,6 +104,8 @@ public:
void setUsePrinterFont(bool p) { m_usePrinterFont = p; }
void setRenderingMode(FontRenderingMode mode) { m_renderingMode = mode; }
void setKeywordSize(unsigned s) { m_keywordSize = s; }
+ void setFontSmoothing(FontSmoothingMode smoothing) { m_fontSmoothing = smoothing; }
+ void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; }
private:
FontFamily m_familyList; // The list of font families to be used.
@@ -117,6 +127,9 @@ private:
unsigned m_keywordSize : 4; // We cache whether or not a font is currently represented by a CSS keyword (e.g., medium). If so,
// then we can accurately translate across different generic families to adjust for different preference settings
// (e.g., 13px monospace vs. 16px everything else). Sizes are 1-8 (like the HTML size values for <font>).
+
+ unsigned m_fontSmoothing : 2; // FontSmoothingMode
+ unsigned m_textRendering : 2; // TextRenderingMode
};
inline bool FontDescription::operator==(const FontDescription& other) const
@@ -131,7 +144,9 @@ inline bool FontDescription::operator==(const FontDescription& other) const
&& m_genericFamily == other.m_genericFamily
&& m_usePrinterFont == other.m_usePrinterFont
&& m_renderingMode == other.m_renderingMode
- && m_keywordSize == other.m_keywordSize;
+ && m_keywordSize == other.m_keywordSize
+ && m_fontSmoothing == other.m_fontSmoothing
+ && m_textRendering == other.m_textRendering;
}
}
diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp
index b0e39db..5246593 100644
--- a/WebCore/platform/graphics/FontFastPath.cpp
+++ b/WebCore/platform/graphics/FontFastPath.cpp
@@ -251,6 +251,10 @@ bool Font::canUseGlyphCache(const TextRun& run) const
return false;
}
+ TextRenderingMode textMode = m_fontDescription.textRenderingMode();
+ if (textMode == OptimizeLegibility || textMode == GeometricPrecision)
+ return false;
+
return true;
}
diff --git a/WebCore/platform/graphics/FontSmoothingMode.h b/WebCore/platform/graphics/FontSmoothingMode.h
new file mode 100644
index 0000000..7c23394
--- /dev/null
+++ b/WebCore/platform/graphics/FontSmoothingMode.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FontSmoothingMode_h
+#define FontSmoothingMode_h
+
+namespace WebCore {
+
+ enum FontSmoothingMode { AutoSmoothing, NoSmoothing, Antialiased, SubpixelAntialiased };
+
+} // namespace WebCore
+
+#endif // FontSmoothingMode_h
diff --git a/WebCore/platform/graphics/GeneratedImage.cpp b/WebCore/platform/graphics/GeneratedImage.cpp
index bac9da0..eec7ffb 100644
--- a/WebCore/platform/graphics/GeneratedImage.cpp
+++ b/WebCore/platform/graphics/GeneratedImage.cpp
@@ -34,7 +34,7 @@ using namespace std;
namespace WebCore {
-void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp)
{
context->save();
context->setCompositeOperation(compositeOp);
@@ -48,7 +48,7 @@ void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, co
}
void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, const FloatRect& destRect)
{
// Create a BitmapImage and call drawPattern on it.
OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(m_size);
@@ -62,7 +62,7 @@ void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcR
Image* bitmap = imageBuffer->image();
// Now just call drawTiled on that image.
- bitmap->drawPattern(context, srcRect, patternTransform, phase, compositeOp, destRect);
+ bitmap->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect);
}
}
diff --git a/WebCore/platform/graphics/GeneratedImage.h b/WebCore/platform/graphics/GeneratedImage.h
index dea0c54..a4583e3 100644
--- a/WebCore/platform/graphics/GeneratedImage.h
+++ b/WebCore/platform/graphics/GeneratedImage.h
@@ -57,9 +57,9 @@ public:
virtual unsigned decodedSize() const { return 0; }
protected:
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
GeneratedImage(PassRefPtr<Generator> generator, const IntSize& size)
: m_generator(generator)
diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
index 6419e0c..9f53f0b 100644
--- a/WebCore/platform/graphics/GlyphPageTreeNode.cpp
+++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
@@ -202,8 +202,10 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu
GlyphPage* pageToFill = m_page.get();
for (unsigned i = 0; i < numRanges; i++) {
const FontDataRange& range = segmentedFontData->rangeAt(i);
- int from = max(0, range.from() - static_cast<int>(start));
- int to = 1 + min(range.to() - static_cast<int>(start), static_cast<int>(GlyphPage::size) - 1);
+ // all this casting is to ensure all the parameters to min and max have the same type,
+ // to avoid ambiguous template parameter errors on Windows
+ int from = max(0, static_cast<int>(range.from()) - static_cast<int>(start));
+ int to = 1 + min(static_cast<int>(range.to()) - static_cast<int>(start), static_cast<int>(GlyphPage::size) - 1);
if (from < static_cast<int>(GlyphPage::size) && to > 0) {
if (haveGlyphs && !scratchPage) {
scratchPage = GlyphPage::create(this);
diff --git a/WebCore/platform/graphics/Gradient.cpp b/WebCore/platform/graphics/Gradient.cpp
index 77a0d21..204a2b6 100644
--- a/WebCore/platform/graphics/Gradient.cpp
+++ b/WebCore/platform/graphics/Gradient.cpp
@@ -161,7 +161,7 @@ void Gradient::setGradientSpaceTransform(const TransformationMatrix& gradientSpa
setPlatformGradientSpaceTransform(gradientSpaceTransformation);
}
-#if !PLATFORM(SKIA)
+#if !(PLATFORM(SKIA) && !PLATFORM(ANDROID))
void Gradient::setPlatformGradientSpaceTransform(const TransformationMatrix&)
{
}
diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h
index 7f01251..011a2cd 100644
--- a/WebCore/platform/graphics/Gradient.h
+++ b/WebCore/platform/graphics/Gradient.h
@@ -46,13 +46,15 @@ typedef QGradient* PlatformGradient;
#elif PLATFORM(CAIRO)
typedef struct _cairo_pattern cairo_pattern_t;
typedef cairo_pattern_t* PlatformGradient;
-#elif PLATFORM(ANDROID) && PLATFORM(SGL)
+#elif PLATFORM(SKIA)
+#if PLATFORM(ANDROID)
#include "SkShader.h"
typedef class PlatformGradientRec* PlatformGradient;
-#elif PLATFORM(SKIA)
+#else
class SkShader;
typedef class SkShader* PlatformGradient;
typedef class SkShader* PlatformPattern;
+#endif
#else
typedef void* PlatformGradient;
#endif
@@ -86,13 +88,11 @@ namespace WebCore {
struct ColorStop;
const Vector<ColorStop>& getStops() const;
#else
-
-#if PLATFORM(ANDROID) && PLATFORM(SGL)
+#if PLATFORM(ANDROID)
SkShader* getShader(SkShader::TileMode);
#endif
PlatformGradient platformGradient();
#endif
-
struct ColorStop {
float stop;
float red;
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index a4e8408..e80004f 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -27,9 +27,9 @@
#include "GraphicsContext.h"
#include "BidiResolver.h"
+#include "Font.h"
#include "Generator.h"
#include "GraphicsContextPrivate.h"
-#include "Font.h"
using namespace std;
@@ -89,7 +89,7 @@ void GraphicsContext::save()
return;
m_common->stack.append(m_common->state);
-
+
savePlatformState();
}
@@ -104,7 +104,7 @@ void GraphicsContext::restore()
}
m_common->state = m_common->stack.last();
m_common->stack.removeLast();
-
+
restorePlatformState();
}
@@ -120,24 +120,21 @@ void GraphicsContext::setStrokeStyle(const StrokeStyle& style)
setPlatformStrokeStyle(style);
}
-void GraphicsContext::setStrokeColor(const Color& color)
+void GraphicsContext::setStrokeColor(const Color& color, ColorSpace colorSpace)
{
- m_common->state.strokeColorSpace = SolidColorSpace;
m_common->state.strokeColor = color;
- setPlatformStrokeColor(color);
-}
-
-ColorSpace GraphicsContext::strokeColorSpace() const
-{
- return m_common->state.strokeColorSpace;
+ m_common->state.strokeColorSpace = colorSpace;
+ m_common->state.strokeGradient.clear();
+ m_common->state.strokePattern.clear();
+ setPlatformStrokeColor(color, colorSpace);
}
-void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color)
+void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace)
{
m_common->state.shadowSize = size;
m_common->state.shadowBlur = blur;
m_common->state.shadowColor = color;
- setPlatformShadow(size, blur, color);
+ setPlatformShadow(size, blur, color, colorSpace);
}
void GraphicsContext::clearShadow()
@@ -172,6 +169,11 @@ Color GraphicsContext::strokeColor() const
return m_common->state.strokeColor;
}
+ColorSpace GraphicsContext::strokeColorSpace() const
+{
+ return m_common->state.strokeColorSpace;
+}
+
WindRule GraphicsContext::fillRule() const
{
return m_common->state.fillRule;
@@ -182,11 +184,13 @@ void GraphicsContext::setFillRule(WindRule fillRule)
m_common->state.fillRule = fillRule;
}
-void GraphicsContext::setFillColor(const Color& color)
+void GraphicsContext::setFillColor(const Color& color, ColorSpace colorSpace)
{
- m_common->state.fillColorSpace = SolidColorSpace;
m_common->state.fillColor = color;
- setPlatformFillColor(color);
+ m_common->state.fillColorSpace = colorSpace;
+ m_common->state.fillGradient.clear();
+ m_common->state.fillPattern.clear();
+ setPlatformFillColor(color, colorSpace);
}
Color GraphicsContext::fillColor() const
@@ -194,6 +198,11 @@ Color GraphicsContext::fillColor() const
return m_common->state.fillColor;
}
+ColorSpace GraphicsContext::fillColorSpace() const
+{
+ return m_common->state.fillColorSpace;
+}
+
void GraphicsContext::setShouldAntialias(bool b)
{
m_common->state.shouldAntialias = b;
@@ -209,10 +218,10 @@ void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
{
ASSERT(pattern);
if (!pattern) {
- setStrokeColor(Color::black);
+ setStrokeColor(Color::black, DeviceColorSpace);
return;
}
- m_common->state.strokeColorSpace = PatternColorSpace;
+ m_common->state.strokeGradient.clear();
m_common->state.strokePattern = pattern;
setPlatformStrokePattern(m_common->state.strokePattern.get());
}
@@ -221,10 +230,10 @@ void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
{
ASSERT(pattern);
if (!pattern) {
- setFillColor(Color::black);
+ setFillColor(Color::black, DeviceColorSpace);
return;
}
- m_common->state.fillColorSpace = PatternColorSpace;
+ m_common->state.fillGradient.clear();
m_common->state.fillPattern = pattern;
setPlatformFillPattern(m_common->state.fillPattern.get());
}
@@ -233,11 +242,11 @@ void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
{
ASSERT(gradient);
if (!gradient) {
- setStrokeColor(Color::black);
+ setStrokeColor(Color::black, DeviceColorSpace);
return;
}
- m_common->state.strokeColorSpace = GradientColorSpace;
m_common->state.strokeGradient = gradient;
+ m_common->state.strokePattern.clear();
setPlatformStrokeGradient(m_common->state.strokeGradient.get());
}
@@ -245,11 +254,11 @@ void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
{
ASSERT(gradient);
if (!gradient) {
- setFillColor(Color::black);
+ setFillColor(Color::black, DeviceColorSpace);
return;
}
- m_common->state.fillColorSpace = GradientColorSpace;
m_common->state.fillGradient = gradient;
+ m_common->state.fillPattern.clear();
setPlatformFillGradient(m_common->state.fillGradient.get());
}
@@ -258,11 +267,6 @@ Gradient* GraphicsContext::fillGradient() const
return m_common->state.fillGradient.get();
}
-ColorSpace GraphicsContext::fillColorSpace() const
-{
- return m_common->state.fillColorSpace;
-}
-
Gradient* GraphicsContext::strokeGradient() const
{
return m_common->state.strokeGradient.get();
@@ -304,24 +308,24 @@ bool GraphicsContext::paintingDisabled() const
return m_common->state.paintingDisabled;
}
-void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperator op)
-{
- drawImage(image, p, IntRect(0, 0, -1, -1), op);
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
+{
+ drawImage(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
}
-void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
{
- drawImage(image, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
+ drawImage(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
}
-void GraphicsContext::drawImage(Image* image, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
{
- drawImage(image, IntRect(dest, srcRect.size()), srcRect, op);
+ drawImage(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
}
-void GraphicsContext::drawImage(Image* image, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
{
- drawImage(image, FloatRect(dest), srcRect, op, useLowQualityScale);
+ drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
}
#if !PLATFORM(WINCE) || PLATFORM(QT)
@@ -329,7 +333,7 @@ void GraphicsContext::drawText(const Font& font, const TextRun& run, const IntPo
{
if (paintingDisabled())
return;
-
+
font.drawText(this, run, point, from, to);
}
#endif
@@ -370,12 +374,12 @@ void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const F
bidiResolver.deleteRuns();
}
-void GraphicsContext::drawHighlightForText(const Font& font, 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, ColorSpace colorSpace, 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, colorSpace);
}
void GraphicsContext::initFocusRing(int width, int offset)
@@ -383,7 +387,7 @@ void GraphicsContext::initFocusRing(int width, int offset)
if (paintingDisabled())
return;
clearFocusRing();
-
+
m_common->m_focusRingWidth = width;
m_common->m_focusRingOffset = offset;
}
@@ -396,12 +400,12 @@ void GraphicsContext::clearFocusRing()
IntRect GraphicsContext::focusRingBoundingRect()
{
IntRect result = IntRect(0, 0, 0, 0);
-
+
const Vector<IntRect>& rects = focusRingRects();
unsigned rectCount = rects.size();
for (unsigned i = 0; i < rectCount; i++)
result.unite(rects[i]);
-
+
return result;
}
@@ -427,7 +431,7 @@ const Vector<IntRect>& GraphicsContext::focusRingRects() const
return m_common->m_focusRingRects;
}
-void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
{
if (paintingDisabled() || !image)
return;
@@ -436,7 +440,7 @@ void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const Float
float tsh = src.height();
float tw = dest.width();
float th = dest.height();
-
+
if (tsw == -1)
tsw = image->width();
if (tsh == -1)
@@ -451,29 +455,29 @@ void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const Float
save();
setImageInterpolationQuality(InterpolationNone);
}
- image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op);
+ image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), styleColorSpace, op);
if (useLowQualityScale)
restore();
}
-void GraphicsContext::drawTiledImage(Image* image, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op)
+void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op)
{
if (paintingDisabled() || !image)
return;
- image->drawTiled(this, rect, srcPoint, tileSize, op);
+ image->drawTiled(this, rect, srcPoint, tileSize, styleColorSpace, op);
}
-void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op)
+void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op)
{
if (paintingDisabled() || !image)
return;
if (hRule == Image::StretchTile && vRule == Image::StretchTile)
// Just do a scale.
- return drawImage(image, dest, srcRect, op);
+ return drawImage(image, styleColorSpace, dest, srcRect, op);
- image->drawTiled(this, dest, srcRect, hRule, vRule, op);
+ image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op);
}
void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
@@ -514,7 +518,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, Generator& generator)
generator.fill(this, rect);
}
-#if !PLATFORM(SKIA)
+#if !(PLATFORM(SKIA) && !PLATFORM(ANDROID))
void GraphicsContext::setPlatformFillGradient(Gradient*)
{
}
@@ -532,7 +536,7 @@ void GraphicsContext::setPlatformStrokePattern(Pattern*)
}
#endif
-#if !PLATFORM(CG) && !PLATFORM(SKIA)
+#if !PLATFORM(CG) && !(PLATFORM(SKIA) && !PLATFORM(ANDROID))
// Implement this if you want to go ahead and push the drawing mode into your native context
// immediately.
void GraphicsContext::setPlatformTextDrawingMode(int mode)
@@ -540,10 +544,39 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode)
}
#endif
-#if !PLATFORM(QT) && !PLATFORM(CAIRO) && !PLATFORM(SKIA)
+#if !PLATFORM(QT) && !PLATFORM(CAIRO) && !(PLATFORM(SKIA) && !PLATFORM(ANDROID)) && !PLATFORM(HAIKU)
void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle&)
{
}
#endif
+void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle& penStyle)
+{
+ // 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, WebKit 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.
+ if (penStyle == DottedStroke || penStyle == DashedStroke) {
+ if (p1.x() == p2.x()) {
+ p1.setY(p1.y() + strokeWidth);
+ p2.setY(p2.y() - strokeWidth);
+ } else {
+ p1.setX(p1.x() + strokeWidth);
+ p2.setX(p2.x() - strokeWidth);
+ }
+ }
+
+ if (static_cast<int>(strokeWidth) % 2) { //odd
+ if (p1.x() == p2.x()) {
+ // We're a vertical line. Adjust our x.
+ p1.setX(p1.x() + 0.5f);
+ p2.setX(p2.x() + 0.5f);
+ } else {
+ // We're a horizontal line. Adjust our y.
+ p1.setY(p1.y() + 0.5f);
+ p2.setY(p2.y() + 0.5f);
+ }
+ }
+}
+
}
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index b52344d..ecf2101 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008-2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,6 +27,7 @@
#ifndef GraphicsContext_h
#define GraphicsContext_h
+#include "ColorSpace.h"
#include "DashArray.h"
#include "FloatRect.h"
#include "Image.h"
@@ -45,18 +46,12 @@ QT_BEGIN_NAMESPACE
class QPainter;
QT_END_NAMESPACE
typedef QPainter PlatformGraphicsContext;
-#elif PLATFORM(SGL)
-namespace WebCore {
-class PlatformGraphicsContext;
-}
-class SkPaint;
-struct SkPoint;
#elif PLATFORM(WX)
class wxGCDC;
class wxWindowDC;
-// wxGraphicsContext allows us to support Path, etc.
-// but on some platforms, e.g. Linux, it requires fairly
+// wxGraphicsContext allows us to support Path, etc.
+// but on some platforms, e.g. Linux, it requires fairly
// new software.
#if USE(WXGC)
// On OS X, wxGCDC is just a typedef for wxDC, so use wxDC explicitly to make
@@ -71,7 +66,19 @@ class wxWindowDC;
typedef wxWindowDC PlatformGraphicsContext;
#endif
#elif PLATFORM(SKIA)
+#if PLATFORM(ANDROID)
+namespace WebCore {
+class PlatformGraphicsContext;
+}
+class SkPaint;
+struct SkPoint;
+#else
typedef class PlatformContextSkia PlatformGraphicsContext;
+#endif
+#elif PLATFORM(HAIKU)
+class BView;
+typedef BView PlatformGraphicsContext;
+struct pattern;
#elif PLATFORM(WINCE)
typedef struct HDC__ PlatformGraphicsContext;
#else
@@ -107,24 +114,24 @@ namespace WebCore {
const int cMisspellingLinePatternWidth = 4;
const int cMisspellingLinePatternGapWidth = 1;
- class TransformationMatrix;
class Font;
class Generator;
class Gradient;
- class GraphicsContextPrivate;
class GraphicsContextPlatformPrivate;
+ class GraphicsContextPrivate;
class ImageBuffer;
class KURL;
class Path;
class Pattern;
class TextRun;
+ class TransformationMatrix;
// These bits can be ORed together for a total of 8 possible text drawing modes.
const int cTextInvisible = 0;
const int cTextFill = 1;
const int cTextStroke = 2;
const int cTextClip = 4;
-
+
enum StrokeStyle {
NoStroke,
SolidStroke,
@@ -132,18 +139,6 @@ namespace WebCore {
DashedStroke
};
-// FIXME: This is a place-holder until we decide to add
-// real color space support to WebCore. At that time, ColorSpace will be a
-// class and instances will be held off of Colors. There will be
-// special singleton Gradient and Pattern color spaces to mark when
-// a fill or stroke is using a gradient or pattern instead of a solid color.
-// https://bugs.webkit.org/show_bug.cgi?id=20558
- enum ColorSpace {
- SolidColorSpace,
- PatternColorSpace,
- GradientColorSpace
- };
-
enum InterpolationQuality {
InterpolationDefault,
InterpolationNone,
@@ -156,19 +151,18 @@ namespace WebCore {
public:
GraphicsContext(PlatformGraphicsContext*);
~GraphicsContext();
-
+
#if !PLATFORM(WINCE) || PLATFORM(QT)
PlatformGraphicsContext* platformContext() const;
#endif
-
+
float strokeThickness() const;
void setStrokeThickness(float);
StrokeStyle strokeStyle() const;
void setStrokeStyle(const StrokeStyle& style);
Color strokeColor() const;
- void setStrokeColor(const Color&);
-
ColorSpace strokeColorSpace() const;
+ void setStrokeColor(const Color&, ColorSpace);
void setStrokePattern(PassRefPtr<Pattern>);
Pattern* strokePattern() const;
@@ -179,7 +173,8 @@ namespace WebCore {
WindRule fillRule() const;
void setFillRule(WindRule);
Color fillColor() const;
- void setFillColor(const Color&);
+ ColorSpace fillColorSpace() const;
+ void setFillColor(const Color&, ColorSpace);
void setFillPattern(PassRefPtr<Pattern>);
Pattern* fillPattern() const;
@@ -187,8 +182,6 @@ namespace WebCore {
void setFillGradient(PassRefPtr<Gradient>);
Gradient* fillGradient() const;
- ColorSpace fillColorSpace() const;
-
void setShadowsIgnoreTransforms(bool);
void setShouldAntialias(bool);
@@ -199,11 +192,9 @@ namespace WebCore {
void applyFillPattern();
#endif
-#if PLATFORM(SGL)
- /* these should be pused to apple. needed for CanvasStyle.cpp */
- void setCMYKAFillColor(float c, float m, float y, float k, float a);
- void setCMYKAStrokeColor(float c, float m, float y, float k, float a);
-
+#if PLATFORM(ANDROID)
+ // initialize a paint for bitmaps
+ void setupBitmapPaint(SkPaint*);
// initialize a paint for filling
void setupFillPaint(SkPaint*);
// initialize a paint for stroking
@@ -215,7 +206,7 @@ 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;
@@ -248,24 +239,24 @@ namespace WebCore {
void strokeArc(const IntRect&, int startAngle, int angleSpan);
void fillRect(const FloatRect&);
- void fillRect(const FloatRect&, const Color&);
+ void fillRect(const FloatRect&, const Color&, ColorSpace);
void fillRect(const FloatRect&, Generator&);
- void fillRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color&);
+ void fillRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color&, ColorSpace);
void clearRect(const FloatRect&);
void strokeRect(const FloatRect&);
void strokeRect(const FloatRect&, float lineWidth);
- void drawImage(Image*, const IntPoint&, CompositeOperator = CompositeSourceOver);
- void drawImage(Image*, const IntRect&, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
- void drawImage(Image*, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver);
- void drawImage(Image*, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
- void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntPoint&, CompositeOperator = CompositeSourceOver);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntRect&, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ void drawImage(Image*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
- void drawTiledImage(Image*, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
+ void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
CompositeOperator = CompositeSourceOver);
- void drawTiledImage(Image*, const IntRect& destRect, const IntRect& srcRect,
+ void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect,
Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
CompositeOperator = CompositeSourceOver);
@@ -286,23 +277,23 @@ namespace WebCore {
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);
+ void drawHighlightForText(const Font&, const TextRun&, const IntPoint&, int h, const Color& backgroundColor, ColorSpace, int from = 0, int to = -1);
FloatRect roundToDevicePixels(const FloatRect&);
-
+
void drawLineForText(const IntPoint&, int width, bool printing);
void drawLineForMisspellingOrBadGrammar(const IntPoint&, int width, bool grammar);
-
+
bool paintingDisabled() const;
void setPaintingDisabled(bool);
-
+
bool updatingControlTints() const;
void setUpdatingControlTints(bool);
void beginTransparencyLayer(float opacity);
void endTransparencyLayer();
- void setShadow(const IntSize&, int blur, const Color&);
+ void setShadow(const IntSize&, int blur, const Color&, ColorSpace);
bool getShadow(IntSize&, int&, Color&) const;
void clearShadow();
@@ -320,6 +311,8 @@ namespace WebCore {
void setAlpha(float);
#if PLATFORM(CAIRO)
float getAlpha();
+ void createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float kernelSize);
+ static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, int shadowBlur);
#endif
void setCompositeOperation(CompositeOperator);
@@ -328,13 +321,18 @@ namespace WebCore {
void addPath(const Path&);
void clip(const Path&);
+
+ // This clip function is used only by <canvas> code. It allows
+ // implementations to handle clipping on the canvas differently since
+ // the disipline is different.
+ void canvasClip(const Path&);
void clipOut(const Path&);
void scale(const FloatSize&);
void rotate(float angleInRadians);
void translate(float x, float y);
IntPoint origin();
-
+
void setURLForRect(const KURL&, const IntRect&);
void concatCTM(const TransformationMatrix&);
@@ -398,12 +396,16 @@ namespace WebCore {
void drawWindowsBitmap(WindowsBitmap*, const IntPoint&);
#endif
-#if PLATFORM(QT) && defined(Q_WS_WIN)
+#if (PLATFORM(QT) && defined(Q_WS_WIN)) || (PLATFORM(WX) && PLATFORM(WIN_OS))
HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true);
void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true);
bool shouldIncludeChildWindows() const { return false; }
#endif
+#if PLATFORM(WX)
+ bool inTransparencyLayer() const { return false; }
+#endif
+
#if PLATFORM(QT)
bool inTransparencyLayer() const;
PlatformPath* currentPath();
@@ -416,6 +418,10 @@ namespace WebCore {
GdkEventExpose* gdkExposeEvent() const;
#endif
+#if PLATFORM(HAIKU)
+ pattern getHaikuStrokeStyle();
+#endif
+
private:
void savePlatformState();
void restorePlatformState();
@@ -423,21 +429,23 @@ namespace WebCore {
void setPlatformTextDrawingMode(int);
void setPlatformFont(const Font& font);
- void setPlatformStrokeColor(const Color&);
+ void setPlatformStrokeColor(const Color&, ColorSpace);
void setPlatformStrokeStyle(const StrokeStyle&);
void setPlatformStrokeThickness(float);
void setPlatformStrokeGradient(Gradient*);
void setPlatformStrokePattern(Pattern*);
- void setPlatformFillColor(const Color&);
+ void setPlatformFillColor(const Color&, ColorSpace);
void setPlatformFillGradient(Gradient*);
void setPlatformFillPattern(Pattern*);
void setPlatformShouldAntialias(bool b);
- void setPlatformShadow(const IntSize&, int blur, const Color&);
+ void setPlatformShadow(const IntSize&, int blur, const Color&, ColorSpace);
void clearPlatformShadow();
+ static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle&);
+
int focusRingWidth() const;
int focusRingOffset() const;
const Vector<IntRect>& focusRingRects() const;
@@ -452,4 +460,3 @@ namespace WebCore {
} // namespace WebCore
#endif // GraphicsContext_h
-
diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h
new file mode 100644
index 0000000..aad8dd4
--- /dev/null
+++ b/WebCore/platform/graphics/GraphicsContext3D.h
@@ -0,0 +1,650 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 GraphicsContext3D_h
+#define GraphicsContext3D_h
+
+#include "PlatformString.h"
+
+#include <wtf/ListHashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+
+// FIXME: Find a better way to avoid the name confliction for NO_ERROR.
+#if PLATFORM(CHROMIUM) && PLATFORM(WIN_OS)
+#undef NO_ERROR
+#endif
+
+#if PLATFORM(MAC)
+#include <OpenGL/OpenGL.h>
+
+typedef void* PlatformGraphicsContext3D;
+const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0;
+typedef GLuint Platform3DObject;
+const Platform3DObject NullPlatform3DObject = 0;
+#else
+typedef void* PlatformGraphicsContext3D;
+const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0;
+typedef int Platform3DObject;
+const Platform3DObject NullPlatform3DObject = 0;
+#endif
+
+namespace WebCore {
+ class WebGLActiveInfo;
+ class WebGLArray;
+ class WebGLBuffer;
+ class WebGLUnsignedByteArray;
+ class WebGLFloatArray;
+ class WebGLFramebuffer;
+ class WebGLIntArray;
+ class WebGLProgram;
+ class WebGLRenderbuffer;
+ class WebGLRenderingContext;
+ class WebGLShader;
+ class WebGLTexture;
+ class Image;
+ class HTMLVideoElement;
+ class ImageData;
+ class WebKitCSSMatrix;
+
+ struct ActiveInfo {
+ String name;
+ unsigned type;
+ int size;
+ };
+
+ // FIXME: ideally this would be used on all platforms.
+#if PLATFORM(CHROMIUM)
+ class GraphicsContext3DInternal;
+#endif
+
+ class GraphicsContext3D : public Noncopyable {
+ public:
+ enum WebGLEnumType {
+ DEPTH_BUFFER_BIT = 0x00000100,
+ STENCIL_BUFFER_BIT = 0x00000400,
+ COLOR_BUFFER_BIT = 0x00004000,
+ POINTS = 0x0000,
+ LINES = 0x0001,
+ LINE_LOOP = 0x0002,
+ LINE_STRIP = 0x0003,
+ TRIANGLES = 0x0004,
+ TRIANGLE_STRIP = 0x0005,
+ TRIANGLE_FAN = 0x0006,
+ ZERO = 0,
+ ONE = 1,
+ SRC_COLOR = 0x0300,
+ ONE_MINUS_SRC_COLOR = 0x0301,
+ SRC_ALPHA = 0x0302,
+ ONE_MINUS_SRC_ALPHA = 0x0303,
+ DST_ALPHA = 0x0304,
+ ONE_MINUS_DST_ALPHA = 0x0305,
+ DST_COLOR = 0x0306,
+ ONE_MINUS_DST_COLOR = 0x0307,
+ SRC_ALPHA_SATURATE = 0x0308,
+ FUNC_ADD = 0x8006,
+ BLEND_EQUATION = 0x8009,
+ BLEND_EQUATION_RGB = 0x8009,
+ BLEND_EQUATION_ALPHA = 0x883D,
+ FUNC_SUBTRACT = 0x800A,
+ FUNC_REVERSE_SUBTRACT = 0x800B,
+ BLEND_DST_RGB = 0x80C8,
+ BLEND_SRC_RGB = 0x80C9,
+ BLEND_DST_ALPHA = 0x80CA,
+ BLEND_SRC_ALPHA = 0x80CB,
+ CONSTANT_COLOR = 0x8001,
+ ONE_MINUS_CONSTANT_COLOR = 0x8002,
+ CONSTANT_ALPHA = 0x8003,
+ ONE_MINUS_CONSTANT_ALPHA = 0x8004,
+ BLEND_COLOR = 0x8005,
+ ARRAY_BUFFER = 0x8892,
+ ELEMENT_ARRAY_BUFFER = 0x8893,
+ ARRAY_BUFFER_BINDING = 0x8894,
+ ELEMENT_ARRAY_BUFFER_BINDING = 0x8895,
+ STREAM_DRAW = 0x88E0,
+ STATIC_DRAW = 0x88E4,
+ DYNAMIC_DRAW = 0x88E8,
+ BUFFER_SIZE = 0x8764,
+ BUFFER_USAGE = 0x8765,
+ CURRENT_VERTEX_ATTRIB = 0x8626,
+ FRONT = 0x0404,
+ BACK = 0x0405,
+ FRONT_AND_BACK = 0x0408,
+ TEXTURE_2D = 0x0DE1,
+ CULL_FACE = 0x0B44,
+ BLEND = 0x0BE2,
+ DITHER = 0x0BD0,
+ STENCIL_TEST = 0x0B90,
+ DEPTH_TEST = 0x0B71,
+ SCISSOR_TEST = 0x0C11,
+ POLYGON_OFFSET_FILL = 0x8037,
+ SAMPLE_ALPHA_TO_COVERAGE = 0x809E,
+ SAMPLE_COVERAGE = 0x80A0,
+ NO_ERROR = 0,
+ INVALID_ENUM = 0x0500,
+ INVALID_VALUE = 0x0501,
+ INVALID_OPERATION = 0x0502,
+ OUT_OF_MEMORY = 0x0505,
+ CW = 0x0900,
+ CCW = 0x0901,
+ LINE_WIDTH = 0x0B21,
+ ALIASED_POINT_SIZE_RANGE = 0x846D,
+ ALIASED_LINE_WIDTH_RANGE = 0x846E,
+ CULL_FACE_MODE = 0x0B45,
+ FRONT_FACE = 0x0B46,
+ DEPTH_RANGE = 0x0B70,
+ DEPTH_WRITEMASK = 0x0B72,
+ DEPTH_CLEAR_VALUE = 0x0B73,
+ DEPTH_FUNC = 0x0B74,
+ STENCIL_CLEAR_VALUE = 0x0B91,
+ STENCIL_FUNC = 0x0B92,
+ STENCIL_FAIL = 0x0B94,
+ STENCIL_PASS_DEPTH_FAIL = 0x0B95,
+ STENCIL_PASS_DEPTH_PASS = 0x0B96,
+ STENCIL_REF = 0x0B97,
+ STENCIL_VALUE_MASK = 0x0B93,
+ STENCIL_WRITEMASK = 0x0B98,
+ STENCIL_BACK_FUNC = 0x8800,
+ STENCIL_BACK_FAIL = 0x8801,
+ STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802,
+ STENCIL_BACK_PASS_DEPTH_PASS = 0x8803,
+ STENCIL_BACK_REF = 0x8CA3,
+ STENCIL_BACK_VALUE_MASK = 0x8CA4,
+ STENCIL_BACK_WRITEMASK = 0x8CA5,
+ VIEWPORT = 0x0BA2,
+ SCISSOR_BOX = 0x0C10,
+ COLOR_CLEAR_VALUE = 0x0C22,
+ COLOR_WRITEMASK = 0x0C23,
+ UNPACK_ALIGNMENT = 0x0CF5,
+ PACK_ALIGNMENT = 0x0D05,
+ MAX_TEXTURE_SIZE = 0x0D33,
+ MAX_VIEWPORT_DIMS = 0x0D3A,
+ SUBPIXEL_BITS = 0x0D50,
+ RED_BITS = 0x0D52,
+ GREEN_BITS = 0x0D53,
+ BLUE_BITS = 0x0D54,
+ ALPHA_BITS = 0x0D55,
+ DEPTH_BITS = 0x0D56,
+ STENCIL_BITS = 0x0D57,
+ POLYGON_OFFSET_UNITS = 0x2A00,
+ POLYGON_OFFSET_FACTOR = 0x8038,
+ TEXTURE_BINDING_2D = 0x8069,
+ SAMPLE_BUFFERS = 0x80A8,
+ SAMPLES = 0x80A9,
+ SAMPLE_COVERAGE_VALUE = 0x80AA,
+ SAMPLE_COVERAGE_INVERT = 0x80AB,
+ NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2,
+ COMPRESSED_TEXTURE_FORMATS = 0x86A3,
+ DONT_CARE = 0x1100,
+ FASTEST = 0x1101,
+ NICEST = 0x1102,
+ GENERATE_MIPMAP_HINT = 0x8192,
+ BYTE = 0x1400,
+ UNSIGNED_BYTE = 0x1401,
+ SHORT = 0x1402,
+ UNSIGNED_SHORT = 0x1403,
+ INT = 0x1404,
+ UNSIGNED_INT = 0x1405,
+ FLOAT = 0x1406,
+ FIXED = 0x140C,
+ DEPTH_COMPONENT = 0x1902,
+ ALPHA = 0x1906,
+ RGB = 0x1907,
+ RGBA = 0x1908,
+ LUMINANCE = 0x1909,
+ LUMINANCE_ALPHA = 0x190A,
+ UNSIGNED_SHORT_4_4_4_4 = 0x8033,
+ UNSIGNED_SHORT_5_5_5_1 = 0x8034,
+ UNSIGNED_SHORT_5_6_5 = 0x8363,
+ FRAGMENT_SHADER = 0x8B30,
+ VERTEX_SHADER = 0x8B31,
+ MAX_VERTEX_ATTRIBS = 0x8869,
+ MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB,
+ MAX_VARYING_VECTORS = 0x8DFC,
+ MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D,
+ MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C,
+ MAX_TEXTURE_IMAGE_UNITS = 0x8872,
+ MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD,
+ SHADER_TYPE = 0x8B4F,
+ DELETE_STATUS = 0x8B80,
+ LINK_STATUS = 0x8B82,
+ VALIDATE_STATUS = 0x8B83,
+ ATTACHED_SHADERS = 0x8B85,
+ ACTIVE_UNIFORMS = 0x8B86,
+ ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87,
+ ACTIVE_ATTRIBUTES = 0x8B89,
+ ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A,
+ SHADING_LANGUAGE_VERSION = 0x8B8C,
+ CURRENT_PROGRAM = 0x8B8D,
+ NEVER = 0x0200,
+ LESS = 0x0201,
+ EQUAL = 0x0202,
+ LEQUAL = 0x0203,
+ GREATER = 0x0204,
+ NOTEQUAL = 0x0205,
+ GEQUAL = 0x0206,
+ ALWAYS = 0x0207,
+ KEEP = 0x1E00,
+ REPLACE = 0x1E01,
+ INCR = 0x1E02,
+ DECR = 0x1E03,
+ INVERT = 0x150A,
+ INCR_WRAP = 0x8507,
+ DECR_WRAP = 0x8508,
+ VENDOR = 0x1F00,
+ RENDERER = 0x1F01,
+ VERSION = 0x1F02,
+ EXTENSIONS = 0x1F03,
+ NEAREST = 0x2600,
+ LINEAR = 0x2601,
+ NEAREST_MIPMAP_NEAREST = 0x2700,
+ LINEAR_MIPMAP_NEAREST = 0x2701,
+ NEAREST_MIPMAP_LINEAR = 0x2702,
+ LINEAR_MIPMAP_LINEAR = 0x2703,
+ TEXTURE_MAG_FILTER = 0x2800,
+ TEXTURE_MIN_FILTER = 0x2801,
+ TEXTURE_WRAP_S = 0x2802,
+ TEXTURE_WRAP_T = 0x2803,
+ TEXTURE = 0x1702,
+ TEXTURE_CUBE_MAP = 0x8513,
+ TEXTURE_BINDING_CUBE_MAP = 0x8514,
+ TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515,
+ TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516,
+ TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517,
+ TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518,
+ TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519,
+ TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A,
+ MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C,
+ TEXTURE0 = 0x84C0,
+ TEXTURE1 = 0x84C1,
+ TEXTURE2 = 0x84C2,
+ TEXTURE3 = 0x84C3,
+ TEXTURE4 = 0x84C4,
+ TEXTURE5 = 0x84C5,
+ TEXTURE6 = 0x84C6,
+ TEXTURE7 = 0x84C7,
+ TEXTURE8 = 0x84C8,
+ TEXTURE9 = 0x84C9,
+ TEXTURE10 = 0x84CA,
+ TEXTURE11 = 0x84CB,
+ TEXTURE12 = 0x84CC,
+ TEXTURE13 = 0x84CD,
+ TEXTURE14 = 0x84CE,
+ TEXTURE15 = 0x84CF,
+ TEXTURE16 = 0x84D0,
+ TEXTURE17 = 0x84D1,
+ TEXTURE18 = 0x84D2,
+ TEXTURE19 = 0x84D3,
+ TEXTURE20 = 0x84D4,
+ TEXTURE21 = 0x84D5,
+ TEXTURE22 = 0x84D6,
+ TEXTURE23 = 0x84D7,
+ TEXTURE24 = 0x84D8,
+ TEXTURE25 = 0x84D9,
+ TEXTURE26 = 0x84DA,
+ TEXTURE27 = 0x84DB,
+ TEXTURE28 = 0x84DC,
+ TEXTURE29 = 0x84DD,
+ TEXTURE30 = 0x84DE,
+ TEXTURE31 = 0x84DF,
+ ACTIVE_TEXTURE = 0x84E0,
+ REPEAT = 0x2901,
+ CLAMP_TO_EDGE = 0x812F,
+ MIRRORED_REPEAT = 0x8370,
+ FLOAT_VEC2 = 0x8B50,
+ FLOAT_VEC3 = 0x8B51,
+ FLOAT_VEC4 = 0x8B52,
+ INT_VEC2 = 0x8B53,
+ INT_VEC3 = 0x8B54,
+ INT_VEC4 = 0x8B55,
+ BOOL = 0x8B56,
+ BOOL_VEC2 = 0x8B57,
+ BOOL_VEC3 = 0x8B58,
+ BOOL_VEC4 = 0x8B59,
+ FLOAT_MAT2 = 0x8B5A,
+ FLOAT_MAT3 = 0x8B5B,
+ FLOAT_MAT4 = 0x8B5C,
+ SAMPLER_2D = 0x8B5E,
+ SAMPLER_CUBE = 0x8B60,
+ VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622,
+ VERTEX_ATTRIB_ARRAY_SIZE = 0x8623,
+ VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624,
+ VERTEX_ATTRIB_ARRAY_TYPE = 0x8625,
+ VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A,
+ VERTEX_ATTRIB_ARRAY_POINTER = 0x8645,
+ VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F,
+ IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A,
+ IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B,
+ COMPILE_STATUS = 0x8B81,
+ INFO_LOG_LENGTH = 0x8B84,
+ SHADER_SOURCE_LENGTH = 0x8B88,
+ SHADER_COMPILER = 0x8DFA,
+ SHADER_BINARY_FORMATS = 0x8DF8,
+ NUM_SHADER_BINARY_FORMATS = 0x8DF9,
+ LOW_FLOAT = 0x8DF0,
+ MEDIUM_FLOAT = 0x8DF1,
+ HIGH_FLOAT = 0x8DF2,
+ LOW_INT = 0x8DF3,
+ MEDIUM_INT = 0x8DF4,
+ HIGH_INT = 0x8DF5,
+ FRAMEBUFFER = 0x8D40,
+ RENDERBUFFER = 0x8D41,
+ RGBA4 = 0x8056,
+ RGB5_A1 = 0x8057,
+ RGB565 = 0x8D62,
+ DEPTH_COMPONENT16 = 0x81A5,
+ STENCIL_INDEX = 0x1901,
+ STENCIL_INDEX8 = 0x8D48,
+ RENDERBUFFER_WIDTH = 0x8D42,
+ RENDERBUFFER_HEIGHT = 0x8D43,
+ RENDERBUFFER_INTERNAL_FORMAT = 0x8D44,
+ RENDERBUFFER_RED_SIZE = 0x8D50,
+ RENDERBUFFER_GREEN_SIZE = 0x8D51,
+ RENDERBUFFER_BLUE_SIZE = 0x8D52,
+ RENDERBUFFER_ALPHA_SIZE = 0x8D53,
+ RENDERBUFFER_DEPTH_SIZE = 0x8D54,
+ RENDERBUFFER_STENCIL_SIZE = 0x8D55,
+ FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0,
+ FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1,
+ FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2,
+ FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3,
+ COLOR_ATTACHMENT0 = 0x8CE0,
+ DEPTH_ATTACHMENT = 0x8D00,
+ STENCIL_ATTACHMENT = 0x8D20,
+ NONE = 0,
+ FRAMEBUFFER_COMPLETE = 0x8CD5,
+ FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6,
+ FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7,
+ FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9,
+ FRAMEBUFFER_UNSUPPORTED = 0x8CDD,
+ FRAMEBUFFER_BINDING = 0x8CA6,
+ RENDERBUFFER_BINDING = 0x8CA7,
+ MAX_RENDERBUFFER_SIZE = 0x84E8,
+ INVALID_FRAMEBUFFER_OPERATION = 0x0506
+ };
+
+ static PassOwnPtr<GraphicsContext3D> create();
+ virtual ~GraphicsContext3D();
+
+#if PLATFORM(MAC)
+ PlatformGraphicsContext3D platformGraphicsContext3D() const { return m_contextObj; }
+ Platform3DObject platformTexture() const { return m_texture; }
+#elif PLATFORM(CHROMIUM)
+ PlatformGraphicsContext3D platformGraphicsContext3D() const;
+ Platform3DObject platformTexture() const;
+#else
+ PlatformGraphicsContext3D platformGraphicsContext3D() const { return NullPlatformGraphicsContext3D; }
+ Platform3DObject platformTexture() const { return NullPlatform3DObject; }
+#endif
+ void makeContextCurrent();
+
+ // Helper to return the size in bytes of OpenGL data types
+ // like GL_FLOAT, GL_INT, etc.
+ int sizeInBytes(int type);
+
+ void activeTexture(unsigned long texture);
+ void attachShader(WebGLProgram* program, WebGLShader* shader);
+ void bindAttribLocation(WebGLProgram*, unsigned long index, const String& name);
+ void bindBuffer(unsigned long target, WebGLBuffer*);
+ void bindFramebuffer(unsigned long target, WebGLFramebuffer*);
+ void bindRenderbuffer(unsigned long target, WebGLRenderbuffer*);
+ void bindTexture(unsigned long target, WebGLTexture* texture);
+ void blendColor(double red, double green, double blue, double alpha);
+ void blendEquation(unsigned long mode);
+ void blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha);
+ void blendFunc(unsigned long sfactor, unsigned long dfactor);
+ void blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha);
+
+ void bufferData(unsigned long target, int size, unsigned long usage);
+ void bufferData(unsigned long target, WebGLArray* data, unsigned long usage);
+ void bufferSubData(unsigned long target, long offset, WebGLArray* data);
+
+ unsigned long checkFramebufferStatus(unsigned long target);
+ void clear(unsigned long mask);
+ void clearColor(double red, double green, double blue, double alpha);
+ void clearDepth(double depth);
+ void clearStencil(long s);
+ void colorMask(bool red, bool green, bool blue, bool alpha);
+ void compileShader(WebGLShader*);
+
+ //void compressedTexImage2D(unsigned long target, long level, unsigned long internalformat, unsigned long width, unsigned long height, long border, unsigned long imageSize, const void* data);
+ //void compressedTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, unsigned long width, unsigned long height, unsigned long format, unsigned long imageSize, const void* data);
+
+ void copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border);
+ void copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height);
+ void cullFace(unsigned long mode);
+ void depthFunc(unsigned long func);
+ void depthMask(bool flag);
+ void depthRange(double zNear, double zFar);
+ void detachShader(WebGLProgram*, WebGLShader*);
+ void disable(unsigned long cap);
+ void disableVertexAttribArray(unsigned long index);
+ void drawArrays(unsigned long mode, long first, long count);
+ void drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset);
+
+ void enable(unsigned long cap);
+ void enableVertexAttribArray(unsigned long index);
+ void finish();
+ void flush();
+ void framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer*);
+ void framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture*, long level);
+ void frontFace(unsigned long mode);
+ void generateMipmap(unsigned long target);
+
+ bool getActiveAttrib(WebGLProgram* program, unsigned long index, ActiveInfo&);
+ bool getActiveUniform(WebGLProgram* program, unsigned long index, ActiveInfo&);
+
+ int getAttribLocation(WebGLProgram*, const String& name);
+
+ void getBooleanv(unsigned long pname, unsigned char* value);
+
+ void getBufferParameteriv(unsigned long target, unsigned long pname, int* value);
+
+ unsigned long getError();
+
+ void getFloatv(unsigned long pname, float* value);
+
+ void getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname, int* value);
+
+ void getIntegerv(unsigned long pname, int* value);
+
+ void getProgramiv(WebGLProgram* program, unsigned long pname, int* value);
+
+ String getProgramInfoLog(WebGLProgram*);
+
+ void getRenderbufferParameteriv(unsigned long target, unsigned long pname, int* value);
+
+ void getShaderiv(WebGLShader*, unsigned long pname, int* value);
+
+ String getShaderInfoLog(WebGLShader*);
+
+ // TBD
+ // void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+
+ String getShaderSource(WebGLShader*);
+ String getString(unsigned long name);
+
+ void getTexParameterfv(unsigned long target, unsigned long pname, float* value);
+ void getTexParameteriv(unsigned long target, unsigned long pname, int* value);
+
+ void getUniformfv(WebGLProgram* program, long location, float* value);
+ void getUniformiv(WebGLProgram* program, long location, int* value);
+
+ long getUniformLocation(WebGLProgram*, const String& name);
+
+ void getVertexAttribfv(unsigned long index, unsigned long pname, float* value);
+ void getVertexAttribiv(unsigned long index, unsigned long pname, int* value);
+
+ long getVertexAttribOffset(unsigned long index, unsigned long pname);
+
+ void hint(unsigned long target, unsigned long mode);
+ bool isBuffer(WebGLBuffer*);
+ bool isEnabled(unsigned long cap);
+ bool isFramebuffer(WebGLFramebuffer*);
+ bool isProgram(WebGLProgram*);
+ bool isRenderbuffer(WebGLRenderbuffer*);
+ bool isShader(WebGLShader*);
+ bool isTexture(WebGLTexture*);
+ void lineWidth(double);
+ void linkProgram(WebGLProgram*);
+ void pixelStorei(unsigned long pname, long param);
+ void polygonOffset(double factor, double units);
+
+ PassRefPtr<WebGLArray> readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type);
+
+ void releaseShaderCompiler();
+ void renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height);
+ void sampleCoverage(double value, bool invert);
+ void scissor(long x, long y, unsigned long width, unsigned long height);
+ void shaderSource(WebGLShader*, const String& string);
+ void stencilFunc(unsigned long func, long ref, unsigned long mask);
+ void stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask);
+ void stencilMask(unsigned long mask);
+ void stencilMaskSeparate(unsigned long face, unsigned long mask);
+ void stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass);
+ void stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass);
+
+ // These next several functions return an error code (0 if no errors) rather than using an ExceptionCode.
+ // Currently they return -1 on any error.
+ int texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned width, unsigned height, unsigned border,
+ unsigned format, unsigned type, WebGLArray* pixels);
+ int texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned width, unsigned height, unsigned border,
+ unsigned format, unsigned type, ImageData* pixels);
+ int texImage2D(unsigned target, unsigned level, Image* image,
+ bool flipY, bool premultiplyAlpha);
+ int texImage2D(unsigned target, unsigned level, HTMLVideoElement* video,
+ bool flipY, bool premultiplyAlpha);
+
+ void texParameterf(unsigned target, unsigned pname, float param);
+ void texParameteri(unsigned target, unsigned pname, int param);
+
+ int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned width, unsigned height,
+ unsigned format, unsigned type, WebGLArray* pixels);
+ int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned width, unsigned height,
+ unsigned format, unsigned type, ImageData* pixels);
+ int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned width, unsigned height, Image* image,
+ bool flipY, bool premultiplyAlpha);
+ int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned width, unsigned height, HTMLVideoElement* video,
+ bool flipY, bool premultiplyAlpha);
+
+ void uniform1f(long location, float x);
+ void uniform1fv(long location, float* v, int size);
+ void uniform1i(long location, int x);
+ void uniform1iv(long location, int* v, int size);
+ void uniform2f(long location, float x, float y);
+ void uniform2fv(long location, float* v, int size);
+ void uniform2i(long location, int x, int y);
+ void uniform2iv(long location, int* v, int size);
+ void uniform3f(long location, float x, float y, float z);
+ void uniform3fv(long location, float* v, int size);
+ void uniform3i(long location, int x, int y, int z);
+ void uniform3iv(long location, int* v, int size);
+ void uniform4f(long location, float x, float y, float z, float w);
+ void uniform4fv(long location, float* v, int size);
+ void uniform4i(long location, int x, int y, int z, int w);
+ void uniform4iv(long location, int* v, int size);
+ void uniformMatrix2fv(long location, bool transpose, float* value, int size);
+ void uniformMatrix3fv(long location, bool transpose, float* value, int size);
+ void uniformMatrix4fv(long location, bool transpose, float* value, int size);
+
+ void useProgram(WebGLProgram*);
+ void validateProgram(WebGLProgram*);
+
+ void vertexAttrib1f(unsigned long indx, float x);
+ void vertexAttrib1fv(unsigned long indx, float* values);
+ void vertexAttrib2f(unsigned long indx, float x, float y);
+ void vertexAttrib2fv(unsigned long indx, float* values);
+ void vertexAttrib3f(unsigned long indx, float x, float y, float z);
+ void vertexAttrib3fv(unsigned long indx, float* values);
+ void vertexAttrib4f(unsigned long indx, float x, float y, float z, float w);
+ void vertexAttrib4fv(unsigned long indx, float* values);
+ void vertexAttribPointer(unsigned long indx, int size, int type, bool normalized,
+ unsigned long stride, unsigned long offset);
+
+ void viewport(long x, long y, unsigned long width, unsigned long height);
+
+ void reshape(int width, int height);
+
+ // Helpers for notification about paint events
+ void beginPaint(WebGLRenderingContext* context);
+ void endPaint();
+
+ // Support for buffer creation and deletion
+ unsigned createBuffer();
+ unsigned createFramebuffer();
+ unsigned createProgram();
+ unsigned createRenderbuffer();
+ unsigned createShader(unsigned long);
+ unsigned createTexture();
+
+ void deleteBuffer(unsigned);
+ void deleteFramebuffer(unsigned);
+ void deleteProgram(unsigned);
+ void deleteRenderbuffer(unsigned);
+ void deleteShader(unsigned);
+ void deleteTexture(unsigned);
+
+ // Synthesizes an OpenGL error which will be returned from a
+ // later call to getError. This is used to emulate OpenGL ES
+ // 2.0 behavior on the desktop and to enforce additional error
+ // checking mandated by WebGL.
+ //
+ // Per the behavior of glGetError, this stores at most one
+ // instance of any given error, and returns them from calls to
+ // getError in the order they were added.
+ void synthesizeGLError(unsigned long error);
+
+ private:
+ GraphicsContext3D();
+
+ int m_currentWidth, m_currentHeight;
+
+#if PLATFORM(MAC)
+ Vector<Vector<float> > m_vertexArray;
+
+ CGLContextObj m_contextObj;
+ GLuint m_texture;
+ GLuint m_fbo;
+ GLuint m_depthBuffer;
+ // Errors raised by synthesizeGLError().
+ ListHashSet<unsigned long> m_syntheticErrors;
+#endif
+
+ // FIXME: ideally this would be used on all platforms.
+#if PLATFORM(CHROMIUM)
+ friend class GraphicsContext3DInternal;
+ OwnPtr<GraphicsContext3DInternal> m_internal;
+#endif
+ };
+
+} // namespace WebCore
+
+#endif // GraphicsContext3D_h
diff --git a/WebCore/platform/graphics/GraphicsContextPrivate.h b/WebCore/platform/graphics/GraphicsContextPrivate.h
index 98baab1..c532162 100644
--- a/WebCore/platform/graphics/GraphicsContextPrivate.h
+++ b/WebCore/platform/graphics/GraphicsContextPrivate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 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,10 +26,10 @@
#ifndef GraphicsContextPrivate_h
#define GraphicsContextPrivate_h
-#include "TransformationMatrix.h"
#include "Gradient.h"
#include "GraphicsContext.h"
#include "Pattern.h"
+#include "TransformationMatrix.h"
namespace WebCore {
@@ -38,18 +38,18 @@ namespace WebCore {
: textDrawingMode(cTextFill)
, strokeStyle(SolidStroke)
, strokeThickness(0)
-#if PLATFORM(CAIRO)
- , globalAlpha(1.0f)
-#endif
- , strokeColorSpace(SolidColorSpace)
, strokeColor(Color::black)
+ , strokeColorSpace(DeviceColorSpace)
, fillRule(RULE_NONZERO)
- , fillColorSpace(SolidColorSpace)
, fillColor(Color::black)
+ , fillColorSpace(DeviceColorSpace)
, shouldAntialias(true)
, paintingDisabled(false)
, shadowBlur(0)
, shadowsIgnoreTransforms(false)
+#if PLATFORM(CAIRO)
+ , globalAlpha(1.0f)
+#endif
{
}
@@ -57,19 +57,14 @@ namespace WebCore {
StrokeStyle strokeStyle;
float strokeThickness;
-#if PLATFORM(CAIRO)
- float globalAlpha;
-#elif PLATFORM(QT)
- TransformationMatrix pathTransform;
-#endif
- ColorSpace strokeColorSpace;
Color strokeColor;
+ ColorSpace strokeColorSpace;
RefPtr<Gradient> strokeGradient;
RefPtr<Pattern> strokePattern;
WindRule fillRule;
- ColorSpace fillColorSpace;
Color fillColor;
+ ColorSpace fillColorSpace;
RefPtr<Gradient> fillGradient;
RefPtr<Pattern> fillPattern;
@@ -82,9 +77,14 @@ namespace WebCore {
Color shadowColor;
bool shadowsIgnoreTransforms;
+#if PLATFORM(CAIRO)
+ float globalAlpha;
+#elif PLATFORM(QT)
+ TransformationMatrix pathTransform;
+#endif
};
- class GraphicsContextPrivate {
+ class GraphicsContextPrivate : public Noncopyable {
public:
GraphicsContextPrivate()
: m_focusRingWidth(0)
diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp
index 7d43832..e215097 100644
--- a/WebCore/platform/graphics/GraphicsLayer.cpp
+++ b/WebCore/platform/graphics/GraphicsLayer.cpp
@@ -59,9 +59,7 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
: m_client(client)
, m_anchorPoint(0.5f, 0.5f, 0)
, m_opacity(1)
-#ifndef NDEBUG
, m_zPosition(0)
-#endif
, m_backgroundColorSet(false)
, m_contentsOpaque(false)
, m_preserves3D(false)
@@ -69,13 +67,12 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
, m_usingTiledLayer(false)
, m_masksToBounds(false)
, m_drawsContent(false)
- , m_paintingPhase(GraphicsLayerPaintAllMask)
+ , m_paintingPhase(GraphicsLayerPaintAll)
, m_geometryOrientation(CompositingCoordinatesTopDown)
, m_contentsOrientation(CompositingCoordinatesTopDown)
, m_parent(0)
-#ifndef NDEBUG
+ , m_maskLayer(0)
, m_repaintCount(0)
-#endif
{
}
@@ -85,6 +82,31 @@ GraphicsLayer::~GraphicsLayer()
removeFromParent();
}
+bool GraphicsLayer::hasAncestor(GraphicsLayer* ancestor) const
+{
+ for (GraphicsLayer* curr = parent(); curr; curr = curr->parent()) {
+ if (curr == ancestor)
+ return true;
+ }
+
+ return false;
+}
+
+bool GraphicsLayer::setChildren(const Vector<GraphicsLayer*>& newChildren)
+{
+ // If the contents of the arrays are the same, nothing to do.
+ if (newChildren == m_children)
+ return false;
+
+ removeAllChildren();
+
+ size_t listSize = newChildren.size();
+ for (size_t i = 0; i < listSize; ++i)
+ addChild(newChildren[i]);
+
+ return true;
+}
+
void GraphicsLayer::addChild(GraphicsLayer* childLayer)
{
ASSERT(childLayer != this);
@@ -218,7 +240,6 @@ void GraphicsLayer::resumeAnimations()
{
}
-#ifndef NDEBUG
void GraphicsLayer::updateDebugIndicators()
{
if (GraphicsLayer::showDebugBorders()) {
@@ -240,7 +261,6 @@ void GraphicsLayer::setZPosition(float position)
{
m_zPosition = position;
}
-#endif
float GraphicsLayer::accumulatedOpacity() const
{
diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h
index 4d7668a..0456bad 100644
--- a/WebCore/platform/graphics/GraphicsLayer.h
+++ b/WebCore/platform/graphics/GraphicsLayer.h
@@ -33,11 +33,15 @@
#include "FloatPoint.h"
#include "FloatPoint3D.h"
#include "FloatSize.h"
+#if ENABLE(3D_CANVAS)
+#include "GraphicsContext3D.h"
+#endif
#include "GraphicsLayerClient.h"
#include "IntRect.h"
#include "TransformationMatrix.h"
#include "TransformOperations.h"
#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
#if PLATFORM(MAC)
#ifdef __OBJC__
@@ -49,6 +53,12 @@ typedef CALayer* NativeLayer;
typedef void* PlatformLayer;
typedef void* NativeLayer;
#endif
+#elif PLATFORM(WIN)
+namespace WebCore {
+class WKCACFLayer;
+typedef WKCACFLayer PlatformLayer;
+typedef void* NativeLayer;
+}
#else
typedef void* PlatformLayer;
typedef void* NativeLayer;
@@ -152,7 +162,7 @@ protected:
class GraphicsLayer {
public:
- static GraphicsLayer* createGraphicsLayer(GraphicsLayerClient*);
+ static PassOwnPtr<GraphicsLayer> create(GraphicsLayerClient*);
virtual ~GraphicsLayer();
@@ -168,7 +178,12 @@ public:
GraphicsLayer* parent() const { return m_parent; };
void setParent(GraphicsLayer* layer) { m_parent = layer; } // Internal use only.
+ // Returns true if the layer has the given layer as an ancestor (excluding self).
+ bool hasAncestor(GraphicsLayer*) const;
+
const Vector<GraphicsLayer*>& children() const { return m_children; }
+ // Returns true if the child list changed.
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
// Add child layers. If the child is already parented, it will be removed from its old parent.
virtual void addChild(GraphicsLayer*);
@@ -180,6 +195,9 @@ public:
void removeAllChildren();
virtual void removeFromParent();
+ GraphicsLayer* maskLayer() const { return m_maskLayer; }
+ virtual void setMaskLayer(GraphicsLayer* layer) { m_maskLayer = layer; }
+
// Offset is origin of the renderer minus origin of the graphics layer (so either zero or negative).
IntSize offsetFromRenderer() const { return m_offsetFromRenderer; }
void setOffsetFromRenderer(const IntSize& offset) { m_offsetFromRenderer = offset; }
@@ -229,8 +247,8 @@ public:
virtual void setOpacity(float opacity) { m_opacity = opacity; }
// Some GraphicsLayers paint only the foreground or the background content
- GraphicsLayerPaintingPhase drawingPhase() const { return m_paintingPhase; }
- void setDrawingPhase(GraphicsLayerPaintingPhase phase) { m_paintingPhase = phase; }
+ GraphicsLayerPaintingPhase paintingPhase() const { return m_paintingPhase; }
+ void setPaintingPhase(GraphicsLayerPaintingPhase phase) { m_paintingPhase = phase; }
virtual void setNeedsDisplay() = 0;
// mark the given rect (in layer coords) as needing dispay. Never goes deep.
@@ -255,6 +273,10 @@ public:
virtual void setContentsToVideo(PlatformLayer*) { }
virtual void setContentsBackgroundColor(const Color&) { }
+#if ENABLE(3D_CANVAS)
+ virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*) { }
+ virtual void setGraphicsContext3DNeedsDisplay() { }
+#endif
// Callback from the underlying graphics system to draw layer contents.
void paintGraphicsLayerContents(GraphicsContext&, const IntRect& clip);
@@ -262,10 +284,8 @@ public:
void dumpLayer(TextStream&, int indent = 0) const;
-#ifndef NDEBUG
int repaintCount() const { return m_repaintCount; }
int incrementRepaintCount() { return ++m_repaintCount; }
-#endif
// Report whether the underlying compositing system uses a top-down
// or a bottom-up coordinate system.
@@ -280,9 +300,8 @@ public:
virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation) { m_contentsOrientation = orientation; }
CompositingCoordinatesOrientation contentsOrientation() const { return m_contentsOrientation; }
-#ifndef NDEBUG
- static bool showDebugBorders();
- static bool showRepaintCounter();
+ bool showDebugBorders() { return m_client ? m_client->showDebugBorders() : false; }
+ bool showRepaintCounter() { return m_client ? m_client->showRepaintCounter() : false; }
void updateDebugIndicators();
@@ -291,7 +310,6 @@ public:
// z-position is the z-equivalent of position(). It's only used for debugging purposes.
virtual float zPosition() const { return m_zPosition; }
virtual void setZPosition(float);
-#endif
virtual void distributeOpacity(float);
virtual float accumulatedOpacity() const;
@@ -328,9 +346,7 @@ protected:
Color m_backgroundColor;
float m_opacity;
-#ifndef NDEBUG
float m_zPosition;
-#endif
bool m_backgroundColorSet : 1;
bool m_contentsOpaque : 1;
@@ -347,11 +363,11 @@ protected:
Vector<GraphicsLayer*> m_children;
GraphicsLayer* m_parent;
+ GraphicsLayer* m_maskLayer; // Reference to mask layer. We don't own this.
+
IntRect m_contentsRect;
-#ifndef NDEBUG
int m_repaintCount;
-#endif
};
diff --git a/WebCore/platform/graphics/GraphicsLayerClient.h b/WebCore/platform/graphics/GraphicsLayerClient.h
index 8c0b7ed..afb297d 100644
--- a/WebCore/platform/graphics/GraphicsLayerClient.h
+++ b/WebCore/platform/graphics/GraphicsLayerClient.h
@@ -37,9 +37,10 @@ class IntRect;
class FloatPoint;
enum GraphicsLayerPaintingPhase {
- GraphicsLayerPaintBackgroundMask = (1 << 0),
- GraphicsLayerPaintForegroundMask = (1 << 1),
- GraphicsLayerPaintAllMask = (GraphicsLayerPaintBackgroundMask | GraphicsLayerPaintForegroundMask)
+ GraphicsLayerPaintBackground = (1 << 0),
+ GraphicsLayerPaintForeground = (1 << 1),
+ GraphicsLayerPaintMask = (1 << 2),
+ GraphicsLayerPaintAll = (GraphicsLayerPaintBackground | GraphicsLayerPaintForeground | GraphicsLayerPaintMask)
};
enum AnimatedPropertyID {
@@ -61,6 +62,9 @@ public:
virtual void notifySyncRequired(const GraphicsLayer*) = 0;
virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) = 0;
+
+ virtual bool showDebugBorders() const = 0;
+ virtual bool showRepaintCounter() const = 0;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/Icon.h b/WebCore/platform/graphics/Icon.h
index 444c67c..d7d694a 100644
--- a/WebCore/platform/graphics/Icon.h
+++ b/WebCore/platform/graphics/Icon.h
@@ -51,7 +51,6 @@ class String;
class Icon : public RefCounted<Icon> {
public:
- static PassRefPtr<Icon> createIconForFile(const String& filename);
static PassRefPtr<Icon> createIconForFiles(const Vector<String>& filenames);
~Icon();
diff --git a/WebCore/platform/graphics/Image.cpp b/WebCore/platform/graphics/Image.cpp
index 80b5457..611216a 100644
--- a/WebCore/platform/graphics/Image.cpp
+++ b/WebCore/platform/graphics/Image.cpp
@@ -75,14 +75,14 @@ bool Image::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
return dataChanged(allDataReceived);
}
-void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op)
+void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, ColorSpace styleColorSpace, CompositeOperator op)
{
if (color.alpha() <= 0)
return;
ctxt->save();
ctxt->setCompositeOperation(!color.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
- ctxt->fillRect(dstRect, color);
+ ctxt->fillRect(dstRect, color, styleColorSpace);
ctxt->restore();
}
@@ -104,10 +104,10 @@ static inline FloatSize calculatePatternScale(const FloatRect& dstRect, const Fl
}
-void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op)
+void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, ColorSpace styleColorSpace, CompositeOperator op)
{
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, destRect, solidColor(), op);
+ fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, op);
return;
}
@@ -132,22 +132,22 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const Fl
visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
visibleSrcRect.setWidth(destRect.width() / scale.width());
visibleSrcRect.setHeight(destRect.height() / scale.height());
- draw(ctxt, destRect, visibleSrcRect, op);
+ draw(ctxt, destRect, visibleSrcRect, styleColorSpace, op);
return;
}
TransformationMatrix patternTransform = TransformationMatrix().scaleNonUniform(scale.width(), scale.height());
FloatRect tileRect(FloatPoint(), intrinsicTileSize);
- drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), op, destRect);
+ drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), styleColorSpace, op, destRect);
startAnimation();
}
// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
-void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, CompositeOperator op)
+void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, ColorSpace styleColorSpace, CompositeOperator op)
{
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, dstRect, solidColor(), op);
+ fillWithSolidColor(ctxt, dstRect, solidColor(), styleColorSpace, op);
return;
}
@@ -170,7 +170,7 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const Flo
vPhase -= fmodf(dstRect.height(), scale.height() * srcRect.height()) / 2.0f;
FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase);
- drawPattern(ctxt, srcRect, patternTransform, patternPhase, op, dstRect);
+ drawPattern(ctxt, srcRect, patternTransform, patternPhase, styleColorSpace, op, dstRect);
startAnimation();
}
diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h
index 294ddf6..f25169b 100644
--- a/WebCore/platform/graphics/Image.h
+++ b/WebCore/platform/graphics/Image.h
@@ -28,6 +28,7 @@
#define Image_h
#include "Color.h"
+#include "ColorSpace.h"
#include "GraphicsTypes.h"
#include "ImageSource.h"
#include "IntRect.h"
@@ -147,7 +148,7 @@ public:
virtual bool getHBITMAPOfSize(HBITMAP, LPSIZE) { return false; }
#endif
-#if PLATFORM(SGL)
+#if PLATFORM(ANDROID)
virtual void setURL(const String& str) {}
#endif
@@ -158,21 +159,22 @@ public:
protected:
Image(ImageObserver* = 0);
- static void fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op);
+ static void fillWithSolidColor(GraphicsContext*, const FloatRect& dstRect, const Color&, ColorSpace styleColorSpace, CompositeOperator);
+ // The ColorSpace parameter will only be used for untagged images.
#if PLATFORM(WIN)
- virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator) { }
+ virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator) { }
#endif
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator) = 0;
- void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, CompositeOperator);
- void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator) = 0;
+ void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, ColorSpace styleColorSpace, CompositeOperator);
+ void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, ColorSpace styleColorSpace, CompositeOperator);
// Supporting tiled drawing
virtual bool mayFillWithSolidColor() { return false; }
virtual Color solidColor() const { return Color(); }
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
private:
RefPtr<SharedBuffer> m_data; // The encoded raw data for the image.
diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h
index 2a96d3b..9432058 100644
--- a/WebCore/platform/graphics/ImageBuffer.h
+++ b/WebCore/platform/graphics/ImageBuffer.h
@@ -50,6 +50,11 @@ namespace WebCore {
LinearRGB
};
+ enum Multiply {
+ Premultiplied,
+ Unmultiplied
+ };
+
class ImageBuffer : public Noncopyable {
public:
// Will return a null pointer on allocation failure.
@@ -71,8 +76,11 @@ namespace WebCore {
void clearImage() { m_image.clear(); }
- PassRefPtr<ImageData> getImageData(const IntRect& rect) const;
- void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint);
+ PassRefPtr<ImageData> getUnmultipliedImageData(const IntRect&) const;
+ PassRefPtr<ImageData> getPremultipliedImageData(const IntRect&) const;
+
+ void putUnmultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint);
+ void putPremultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint);
String toDataURL(const String& mimeType) const;
#if !PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp b/WebCore/platform/graphics/ImageSource.cpp
index df62618..bf7ae21 100644
--- a/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
+++ b/WebCore/platform/graphics/ImageSource.cpp
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
+ * Copyright (C) 2008, Google Inc. All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,64 +29,20 @@
#include "config.h"
#include "ImageSource.h"
-#if PLATFORM(CAIRO)
+#if PLATFORM(QT)
+#include "ImageDecoderQt.h"
+#else
+#include "ImageDecoder.h"
+#endif
-#include "BMPImageDecoder.h"
-#include "GIFImageDecoder.h"
-#include "ICOImageDecoder.h"
-#include "JPEGImageDecoder.h"
-#include "PNGImageDecoder.h"
-#include "XBMImageDecoder.h"
-#include "SharedBuffer.h"
-#include <cairo.h>
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+#ifndef IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS
+#define IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS (1024 * 1024)
+#endif
+#endif
namespace WebCore {
-ImageDecoder* createDecoder(const Vector<char>& data)
-{
- // 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();
-
- // 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)
{
@@ -120,53 +78,41 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
// 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());
-
- if (!m_decoder)
- return;
+ if (!m_decoder) {
+ m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data));
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+ if (m_decoder)
+ m_decoder->setMaxNumPixels(IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS);
+#endif
+ }
- m_decoder->setData(data, allDataReceived);
+ if (m_decoder)
+ m_decoder->setData(data, allDataReceived);
}
String ImageSource::filenameExtension() const
{
- if (!m_decoder)
- return String();
-
- return m_decoder->filenameExtension();
+ return m_decoder ? m_decoder->filenameExtension() : String();
}
bool ImageSource::isSizeAvailable()
{
- if (!m_decoder)
- return false;
-
- return m_decoder->isSizeAvailable();
+ return m_decoder && m_decoder->isSizeAvailable();
}
IntSize ImageSource::size() const
{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->size();
+ return m_decoder ? m_decoder->size() : IntSize();
}
IntSize ImageSource::frameSizeAtIndex(size_t index) const
{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->frameSizeAtIndex(index);
+ return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize();
}
int ImageSource::repetitionCount()
{
- if (!m_decoder)
- return cAnimationNone;
-
- return m_decoder->repetitionCount();
+ return m_decoder ? m_decoder->repetitionCount() : cAnimationNone;
}
size_t ImageSource::frameCount() const
@@ -176,9 +122,6 @@ size_t ImageSource::frameCount() const
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
- if (!initialized())
- return 0;
-
if (!m_decoder)
return 0;
@@ -186,23 +129,16 @@ NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
return 0;
- // Cairo does not like zero height images.
- // If we have a zero height image, just pretend we don't have enough data yet.
- if (!size().height())
+ // Zero-height images can cause problems for some ports. If we have an
+ // empty image dimension, just bail.
+ if (size().isEmpty())
return 0;
+ // Return the buffer contents as a native image. For some ports, the data
+ // is already in a native container, and this just increments its refcount.
return buffer->asNewNativeImage();
}
-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)
@@ -223,17 +159,23 @@ float ImageSource::frameDurationAtIndex(size_t index)
bool ImageSource::frameHasAlphaAtIndex(size_t index)
{
- // When a frame has not finished decoding, always mark it as having alpha,
- // so we don't get a black background for the undecoded sections.
- // TODO: A better solution is probably to have the underlying buffer's
- // hasAlpha() return true in these cases, since it is, in fact, technically
- // true.
- if (!frameIsCompleteAtIndex(index))
- return true;
-
- return m_decoder->frameBufferAtIndex(index)->hasAlpha();
+ // When a frame has not finished decoding, always mark it as having alpha.
+ // Ports that check the result of this function to determine their
+ // compositing op need this in order to not draw the undecoded portion as
+ // black.
+ // TODO: Perhaps we should ensure that each individual decoder returns true
+ // in this case.
+ return !frameIsCompleteAtIndex(index)
+ || m_decoder->frameBufferAtIndex(index)->hasAlpha();
}
+bool ImageSource::frameIsCompleteAtIndex(size_t index)
+{
+ if (!m_decoder)
+ return false;
+
+ RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
+ return buffer && buffer->status() == RGBA32Buffer::FrameComplete;
}
-#endif // PLATFORM(CAIRO)
+}
diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h
index 173d50b..083c7b0 100644
--- a/WebCore/platform/graphics/ImageSource.h
+++ b/WebCore/platform/graphics/ImageSource.h
@@ -45,12 +45,16 @@ QT_END_NAMESPACE
#elif PLATFORM(CAIRO)
struct _cairo_surface;
typedef struct _cairo_surface cairo_surface_t;
-#elif PLATFORM(ANDROID) && PLATFORM(SGL)
+#elif PLATFORM(SKIA)
+#if PLATFORM(ANDROID)
#include "SkString.h"
class SkBitmapRef;
class PrivateAndroidImageSourceRec;
-#elif PLATFORM(SKIA)
+#else
class NativeImageSkia;
+#endif
+#elif PLATFORM(HAIKU)
+class BBitmap;
#elif PLATFORM(WINCE)
#include "SharedBitmap.h"
#endif
@@ -61,30 +65,21 @@ class IntSize;
class SharedBuffer;
class String;
-#if PLATFORM(WX)
-class ImageDecoder;
-typedef ImageDecoder* NativeImageSourcePtr;
-typedef const Vector<char>* NativeBytePtr;
-#if USE(WXGC)
-typedef wxGraphicsBitmap* NativeImagePtr;
-#else
-typedef wxBitmap* NativeImagePtr;
-#endif
-#elif PLATFORM(CG)
+#if PLATFORM(CG)
typedef CGImageSourceRef NativeImageSourcePtr;
typedef CGImageRef NativeImagePtr;
#elif PLATFORM(QT)
class ImageDecoderQt;
typedef ImageDecoderQt* NativeImageSourcePtr;
typedef QPixmap* NativeImagePtr;
-#elif PLATFORM(ANDROID)
-#if PLATFORM(SGL)
+#elif PLATFORM(SKIA)
+#if PLATFORM(ANDROID)
class String;
#ifdef ANDROID_ANIMATED_GIF
class ImageDecoder;
#endif
struct NativeImageSourcePtr {
- SkString m_url;
+ SkString m_url;
PrivateAndroidImageSourceRec* m_image;
#ifdef ANDROID_ANIMATED_GIF
ImageDecoder* m_gifDecoder;
@@ -92,24 +87,28 @@ struct NativeImageSourcePtr {
};
typedef const Vector<char>* NativeBytePtr;
typedef SkBitmapRef* NativeImagePtr;
-#elif PLATFORM(SKIA) // ANDROID
+#else
class ImageDecoder;
typedef ImageDecoder* NativeImageSourcePtr;
typedef NativeImageSkia* NativeImagePtr;
#endif
-#elif PLATFORM(CAIRO)
+#else
class ImageDecoder;
typedef ImageDecoder* NativeImageSourcePtr;
+#if PLATFORM(WX)
+#if USE(WXGC)
+typedef wxGraphicsBitmap* NativeImagePtr;
+#else
+typedef wxBitmap* NativeImagePtr;
+#endif
+#elif PLATFORM(CAIRO)
typedef cairo_surface_t* NativeImagePtr;
-#elif PLATFORM(SKIA)
-class ImageDecoder;
-typedef ImageDecoder* NativeImageSourcePtr;
-typedef NativeImageSkia* NativeImagePtr;
+#elif PLATFORM(HAIKU)
+typedef BBitmap* NativeImagePtr;
#elif PLATFORM(WINCE)
-class ImageDecoder;
-typedef ImageDecoder* NativeImageSourcePtr;
typedef RefPtr<SharedBitmap> NativeImagePtr;
#endif
+#endif
const int cAnimationLoopOnce = -1;
const int cAnimationNone = -2;
@@ -167,11 +166,9 @@ public:
bool frameIsCompleteAtIndex(size_t); // Whether or not the frame is completely decoded.
#if PLATFORM(ANDROID)
-#if PLATFORM(SGL)
void clearURL();
void setURL(const String& url);
#endif
-#endif
private:
#if PLATFORM(ANDROID)
// FIXME: This is protected only to allow ImageSourceSkia to set ICO decoder
diff --git a/WebCore/platform/graphics/IntPoint.h b/WebCore/platform/graphics/IntPoint.h
index e6d4816..ab5f3ec 100644
--- a/WebCore/platform/graphics/IntPoint.h
+++ b/WebCore/platform/graphics/IntPoint.h
@@ -55,13 +55,15 @@ class QPoint;
QT_END_NAMESPACE
#elif PLATFORM(GTK)
typedef struct _GdkPoint GdkPoint;
+#elif PLATFORM(HAIKU)
+class BPoint;
#endif
#if PLATFORM(WX)
class wxPoint;
#endif
-#if (PLATFORM(SKIA) || PLATFORM(SGL))
+#if PLATFORM(SKIA)
struct SkPoint;
struct SkIPoint;
#endif
@@ -121,6 +123,9 @@ public:
#elif PLATFORM(GTK)
IntPoint(const GdkPoint&);
operator GdkPoint() const;
+#elif PLATFORM(HAIKU)
+ explicit IntPoint(const BPoint&);
+ operator BPoint() const;
#endif
#if PLATFORM(WX)
@@ -128,7 +133,7 @@ public:
operator wxPoint() const;
#endif
-#if (PLATFORM(SKIA) || PLATFORM(SGL))
+#if PLATFORM(SKIA)
IntPoint(const SkIPoint&);
operator SkIPoint() const;
operator SkPoint() const;
diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h
index 0b607f5..97b21bc 100644
--- a/WebCore/platform/graphics/IntRect.h
+++ b/WebCore/platform/graphics/IntRect.h
@@ -33,7 +33,7 @@
typedef struct CGRect CGRect;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
typedef struct CGRect NSRect;
#else
@@ -49,13 +49,15 @@ class QRect;
QT_END_NAMESPACE
#elif PLATFORM(GTK)
typedef struct _GdkRectangle GdkRectangle;
+#elif PLATFORM(HAIKU)
+class BRect;
#endif
#if PLATFORM(WX)
class wxRect;
#endif
-#if (PLATFORM(SKIA) || PLATFORM(SGL))
+#if PLATFORM(SKIA)
struct SkRect;
struct SkIRect;
#endif
@@ -144,19 +146,23 @@ public:
#elif PLATFORM(GTK)
IntRect(const GdkRectangle&);
operator GdkRectangle() const;
+#elif PLATFORM(HAIKU)
+ explicit IntRect(const BRect&);
+ operator BRect() const;
#endif
#if PLATFORM(CG)
operator CGRect() const;
#endif
-#if (PLATFORM(SKIA) || PLATFORM(SGL))
+#if PLATFORM(SKIA)
IntRect(const SkIRect&);
operator SkRect() const;
operator SkIRect() const;
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
operator NSRect() const;
#endif
@@ -193,7 +199,8 @@ inline bool operator!=(const IntRect& a, const IntRect& b)
IntRect enclosingIntRect(const CGRect&);
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
IntRect enclosingIntRect(const NSRect&);
#endif
diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h
index dc7a85d..b242784 100644
--- a/WebCore/platform/graphics/IntSize.h
+++ b/WebCore/platform/graphics/IntSize.h
@@ -47,6 +47,12 @@ typedef struct tagSIZE SIZE;
QT_BEGIN_NAMESPACE
class QSize;
QT_END_NAMESPACE
+#elif PLATFORM(HAIKU)
+class BSize;
+#endif
+
+#if PLATFORM(WX)
+class wxSize;
#endif
namespace WebCore {
@@ -113,6 +119,15 @@ public:
operator QSize() const;
#endif
+#if PLATFORM(HAIKU)
+ explicit IntSize(const BSize&);
+ operator BSize() const;
+#endif
+
+#if PLATFORM(WX)
+ IntSize(const wxSize&);
+ operator wxSize() const;
+#endif
private:
int m_width, m_height;
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index 531c598..4c66c50 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -35,10 +35,11 @@
#include "FrameView.h"
#include "Frame.h"
#include "Document.h"
+#include "TimeRanges.h"
#if PLATFORM(MAC)
#include "MediaPlayerPrivateQTKit.h"
-#elif PLATFORM(WINCE)
+#elif PLATFORM(WINCE) && !PLATFORM(QT)
#include "MediaPlayerPrivateWince.h"
#elif PLATFORM(WIN)
#include "MediaPlayerPrivateQuickTimeWin.h"
@@ -63,14 +64,16 @@ public:
virtual void load(const String&) { }
virtual void cancelLoad() { }
+ virtual void prepareToPlay() { }
virtual void play() { }
virtual void pause() { }
- virtual bool supportsFullscreen() const { return false; }
+ virtual PlatformMedia platformMedia() const { return NoPlatformMedia; }
virtual IntSize naturalSize() const { return IntSize(0, 0); }
virtual bool hasVideo() const { return false; }
+ virtual bool hasAudio() const { return false; }
virtual void setVisible(bool) { }
@@ -88,11 +91,14 @@ public:
virtual void setVolume(float) { }
+ virtual bool hasClosedCaptions() const { return false; }
+ virtual void setClosedCaptionsVisible(bool) { };
+
virtual MediaPlayer::NetworkState networkState() const { return MediaPlayer::Empty; }
virtual MediaPlayer::ReadyState readyState() const { return MediaPlayer::HaveNothing; }
virtual float maxTimeSeekable() const { return 0; }
- virtual float maxTimeBuffered() const { return 0; }
+ virtual PassRefPtr<TimeRanges> buffered() const { return TimeRanges::create(); }
virtual int dataRate() const { return 0; }
@@ -104,14 +110,10 @@ public:
virtual void paint(GraphicsContext*, const IntRect&) { }
-#if PLATFORM(ANDROID)
virtual bool canLoadPoster() const { return false; }
virtual void setPoster(const String&) { }
- virtual void prepareToPlay() { }
-#endif
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- virtual void setPoster(const String& /*url*/) { }
virtual void deliverNotification(MediaPlayerProxyNotificationType) { }
virtual void setMediaPlayerProxy(WebMediaPlayerProxy*) { }
#endif
@@ -127,7 +129,7 @@ static MediaPlayerPrivateInterface* createNullMediaPlayer(MediaPlayer* player)
// engine support
-struct MediaPlayerFactory {
+struct MediaPlayerFactory : Noncopyable {
MediaPlayerFactory(CreateMediaEnginePlayer constructor, MediaEngineSupportedTypes getSupportedTypes, MediaEngineSupportsType supportsTypeAndCodecs)
: constructor(constructor)
, getSupportedTypes(getSupportedTypes)
@@ -259,30 +261,26 @@ void MediaPlayer::load(const String& url, const ContentType& contentType)
m_private.set(createNullMediaPlayer(this));
}
-#if PLATFORM(ANDROID)
bool MediaPlayer::canLoadPoster() const
{
return m_private->canLoadPoster();
}
-
-void MediaPlayer::prepareToPlay()
-{
- m_private->prepareToPlay();
-}
-#endif
-
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) || PLATFORM(ANDROID)
+
void MediaPlayer::setPoster(const String& url)
{
m_private->setPoster(url);
-}
-#endif
+}
void MediaPlayer::cancelLoad()
{
m_private->cancelLoad();
}
+void MediaPlayer::prepareToPlay()
+{
+ m_private->prepareToPlay();
+}
+
void MediaPlayer::play()
{
m_private->play();
@@ -338,11 +336,16 @@ IntSize MediaPlayer::naturalSize()
return m_private->naturalSize();
}
-bool MediaPlayer::hasVideo()
+bool MediaPlayer::hasVideo() const
{
return m_private->hasVideo();
}
+bool MediaPlayer::hasAudio() const
+{
+ return m_private->hasAudio();
+}
+
bool MediaPlayer::inMediaDocument()
{
Frame* frame = m_frameView ? m_frameView->frame() : 0;
@@ -351,6 +354,11 @@ bool MediaPlayer::inMediaDocument()
return document && document->isMediaDocument();
}
+PlatformMedia MediaPlayer::platformMedia() const
+{
+ return m_private->platformMedia();
+}
+
MediaPlayer::NetworkState MediaPlayer::networkState()
{
return m_private->networkState();
@@ -372,6 +380,16 @@ void MediaPlayer::setVolume(float volume)
m_private->setVolume(volume);
}
+bool MediaPlayer::hasClosedCaptions() const
+{
+ return m_private->hasClosedCaptions();
+}
+
+void MediaPlayer::setClosedCaptionsVisible(bool closedCaptionsVisible)
+{
+ m_private->setClosedCaptionsVisible(closedCaptionsVisible);
+}
+
float MediaPlayer::rate() const
{
return m_rate;
@@ -404,9 +422,9 @@ void MediaPlayer::setEndTime(float time)
m_private->setEndTime(time);
}
-float MediaPlayer::maxTimeBuffered()
+PassRefPtr<TimeRanges> MediaPlayer::buffered()
{
- return m_private->maxTimeBuffered();
+ return m_private->buffered();
}
float MediaPlayer::maxTimeSeekable()
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
index 8eade50..ec8ac33 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -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
@@ -37,9 +37,26 @@
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+
+#ifdef __OBJC__
+@class QTMovie;
+#else
+class QTMovie;
+#endif
namespace WebCore {
+// Structure that will hold every native
+// types supported by the current media player.
+// We have to do that has multiple media players
+// backend can live at runtime.
+typedef struct PlatformMedia {
+ QTMovie* qtMovie;
+} PlatformMedia;
+
+static const PlatformMedia NoPlatformMedia = { 0 };
+
class ContentType;
class FrameView;
class GraphicsContext;
@@ -48,6 +65,7 @@ class IntSize;
class MediaPlayer;
class MediaPlayerPrivateInterface;
class String;
+class TimeRanges;
#if USE(ACCELERATED_COMPOSITING)
class GraphicsLayer;
@@ -98,7 +116,11 @@ public:
class MediaPlayer : public Noncopyable {
public:
- MediaPlayer(MediaPlayerClient*);
+
+ static PassOwnPtr<MediaPlayer> create(MediaPlayerClient* client)
+ {
+ return new MediaPlayer(client);
+ }
virtual ~MediaPlayer();
// media engine support
@@ -109,8 +131,11 @@ public:
bool supportsFullscreen() const;
bool supportsSave() const;
+ PlatformMedia platformMedia() const;
+
IntSize naturalSize();
- bool hasVideo();
+ bool hasVideo() const;
+ bool hasAudio() const;
void setFrameView(FrameView* frameView) { m_frameView = frameView; }
FrameView* frameView() { return m_frameView; }
@@ -125,6 +150,7 @@ public:
bool visible() const;
void setVisible(bool);
+ void prepareToPlay();
void play();
void pause();
@@ -145,7 +171,7 @@ public:
bool preservesPitch() const;
void setPreservesPitch(bool);
- float maxTimeBuffered();
+ PassRefPtr<TimeRanges> buffered();
float maxTimeSeekable();
unsigned bytesLoaded();
@@ -154,7 +180,10 @@ public:
float volume() const;
void setVolume(float);
-
+
+ bool hasClosedCaptions() const;
+ void setClosedCaptionsVisible(bool closedCaptionsVisible);
+
int dataRate() const;
bool autobuffer() const;
@@ -184,14 +213,10 @@ public:
MediaPlayerClient* mediaPlayerClient() const { return m_mediaPlayerClient; }
-#if PLATFORM(ANDROID)
bool canLoadPoster() const;
void setPoster(const String&);
- void prepareToPlay();
-#endif
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- void setPoster(const String& url);
void deliverNotification(MediaPlayerProxyNotificationType notification);
void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
#endif
@@ -206,6 +231,8 @@ public:
bool hasSingleSecurityOrigin() const;
private:
+ MediaPlayer(MediaPlayerClient*);
+
static void initializeMediaEngines();
MediaPlayerClient* m_mediaPlayerClient;
diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h
index 109ad10..03906bd 100644
--- a/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -36,13 +36,16 @@ class IntRect;
class IntSize;
class String;
-class MediaPlayerPrivateInterface {
+class MediaPlayerPrivateInterface : public Noncopyable {
public:
virtual ~MediaPlayerPrivateInterface() { }
virtual void load(const String& url) = 0;
virtual void cancelLoad() = 0;
+ virtual void prepareToPlay() { }
+ virtual PlatformMedia platformMedia() const { return NoPlatformMedia; }
+
virtual void play() = 0;
virtual void pause() = 0;
@@ -52,6 +55,7 @@ public:
virtual IntSize naturalSize() const = 0;
virtual bool hasVideo() const = 0;
+ virtual bool hasAudio() const = 0;
virtual void setVisible(bool) = 0;
@@ -72,11 +76,14 @@ public:
virtual void setVolume(float) = 0;
+ virtual bool hasClosedCaptions() const { return false; }
+ virtual void setClosedCaptionsVisible(bool) { }
+
virtual MediaPlayer::NetworkState networkState() const = 0;
virtual MediaPlayer::ReadyState readyState() const = 0;
virtual float maxTimeSeekable() const = 0;
- virtual float maxTimeBuffered() const = 0;
+ virtual PassRefPtr<TimeRanges> buffered() const = 0;
virtual int dataRate() const = 0;
@@ -92,14 +99,10 @@ public:
virtual void setAutobuffer(bool) { };
-#if PLATFORM(ANDROID)
virtual bool canLoadPoster() const { return false; }
virtual void setPoster(const String&) { }
- virtual void prepareToPlay() { }
-#endif
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- virtual void setPoster(const String& url) = 0;
virtual void deliverNotification(MediaPlayerProxyNotificationType) = 0;
virtual void setMediaPlayerProxy(WebMediaPlayerProxy*) = 0;
#endif
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
index da324bc..6618fb7 100644
--- a/WebCore/platform/graphics/Path.h
+++ b/WebCore/platform/graphics/Path.h
@@ -29,6 +29,7 @@
#define Path_h
#include <algorithm>
+#include <wtf/FastAllocBase.h>
#if PLATFORM(CG)
typedef struct CGPath PlatformPath;
@@ -38,9 +39,6 @@ QT_BEGIN_NAMESPACE
class QPainterPath;
QT_END_NAMESPACE
typedef QPainterPath PlatformPath;
-#elif PLATFORM(SGL)
-class SkPath;
-typedef SkPath PlatformPath;
#elif PLATFORM(WX) && USE(WXGC)
class wxGraphicsPath;
typedef wxGraphicsPath PlatformPath;
@@ -52,6 +50,9 @@ typedef WebCore::CairoPath PlatformPath;
#elif PLATFORM(SKIA)
class SkPath;
typedef SkPath PlatformPath;
+#elif PLATFORM(HAIKU)
+class BRegion;
+typedef BRegion PlatformPath;
#elif PLATFORM(WINCE)
namespace WebCore {
class PlatformPath;
@@ -90,7 +91,7 @@ namespace WebCore {
typedef void (*PathApplierFunction)(void* info, const PathElement*);
- class Path {
+ class Path : public FastAllocBase {
public:
Path();
~Path();
diff --git a/WebCore/platform/graphics/Pattern.h b/WebCore/platform/graphics/Pattern.h
index 02ad3ec..aa0a357 100644
--- a/WebCore/platform/graphics/Pattern.h
+++ b/WebCore/platform/graphics/Pattern.h
@@ -39,7 +39,7 @@ typedef CGPatternRef PlatformPatternPtr;
#elif PLATFORM(CAIRO)
#include <cairo.h>
typedef cairo_pattern_t* PlatformPatternPtr;
-#elif PLATFORM(SKIA) || PLATFORM(SGL)
+#elif PLATFORM(SKIA)
class SkShader;
typedef SkShader* PlatformPatternPtr;
#elif PLATFORM(QT)
@@ -53,6 +53,9 @@ typedef wxGraphicsBrush* PlatformPatternPtr;
class wxBrush;
typedef wxBrush* PlatformPatternPtr;
#endif // USE(WXGC)
+#elif PLATFORM(HAIKU)
+#include <interface/GraphicsDefs.h>
+typedef pattern* PlatformPatternPtr;
#elif PLATFORM(WINCE)
typedef void* PlatformPatternPtr;
#endif
diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp
index c879228..2ec8abb 100644
--- a/WebCore/platform/graphics/SimpleFontData.cpp
+++ b/WebCore/platform/graphics/SimpleFontData.cpp
@@ -48,7 +48,9 @@ using namespace std;
namespace WebCore {
SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool loading, SVGFontData* svgFontData)
- : m_unitsPerEm(defaultUnitsPerEm)
+ : m_maxCharWidth(-1)
+ , m_avgCharWidth(-1)
+ , m_unitsPerEm(defaultUnitsPerEm)
, m_platformData(f)
, m_treatAsFixedPitch(false)
#if ENABLE(SVG_FONTS)
diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h
index cb472b0..387a5c7 100644
--- a/WebCore/platform/graphics/SimpleFontData.h
+++ b/WebCore/platform/graphics/SimpleFontData.h
@@ -2,6 +2,7 @@
* This file is part of the internal font implementation.
*
* Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2008 Torch Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,13 +28,14 @@
#include "FontPlatformData.h"
#include "GlyphPageTreeNode.h"
#include "GlyphWidthMap.h"
+#include "TextRenderingMode.h"
#include <wtf/OwnPtr.h>
#if USE(ATSUI)
typedef struct OpaqueATSUStyle* ATSUStyle;
#endif
-#if PLATFORM(WIN)
+#if PLATFORM(WIN) && !PLATFORM(WINCE)
#include <usp10.h>
#endif
@@ -45,6 +47,10 @@ typedef struct OpaqueATSUStyle* ATSUStyle;
#include <QFont>
#endif
+#if PLATFORM(HAIKU)
+#include <Font.h>
+#endif
+
namespace WebCore {
class FontDescription;
@@ -115,7 +121,7 @@ public:
#if USE(CORE_TEXT)
CTFontRef getCTFont() const;
- CFDictionaryRef getCFStringAttributes() const;
+ CFDictionaryRef getCFStringAttributes(TextRenderingMode) const;
#endif
#if USE(ATSUI)
@@ -134,17 +140,14 @@ public:
#if PLATFORM(WIN)
bool isSystemFont() const { return m_isSystemFont; }
+#if !PLATFORM(WINCE) // disable unused members to save space
SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
-
+#endif
static void setShouldApplyMacAscentHack(bool);
static bool shouldApplyMacAscentHack();
#endif
-#if PLATFORM(CAIRO)
- void setFont(cairo_t*) const;
-#endif
-
#if PLATFORM(WX)
wxFont* getWxFont() const { return m_platformData.font(); }
#endif
@@ -159,7 +162,7 @@ private:
void commonInit();
-#if PLATFORM(WIN)
+#if PLATFORM(WIN) && !PLATFORM(WINCE)
void initGDIFont();
void platformCommonDestroy();
float widthForGDIGlyph(Glyph glyph) const;
@@ -224,9 +227,11 @@ private:
#if PLATFORM(WIN)
bool m_isSystemFont;
+#if !PLATFORM(WINCE) // disable unused members to save space
mutable SCRIPT_CACHE m_scriptCache;
mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
#endif
+#endif
};
diff --git a/WebCore/platform/graphics/TextRenderingMode.h b/WebCore/platform/graphics/TextRenderingMode.h
new file mode 100644
index 0000000..4f817a4
--- /dev/null
+++ b/WebCore/platform/graphics/TextRenderingMode.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TextRenderingMode_h
+#define TextRenderingMode_h
+
+namespace WebCore {
+
+ enum TextRenderingMode { AutoTextRendering, OptimizeSpeed, OptimizeLegibility, GeometricPrecision };
+
+} // namespace WebCore
+
+#endif // TextRenderingMode_h
diff --git a/WebCore/platform/graphics/android/AndroidAnimation.cpp b/WebCore/platform/graphics/android/AndroidAnimation.cpp
new file mode 100644
index 0000000..9cdb0c7
--- /dev/null
+++ b/WebCore/platform/graphics/android/AndroidAnimation.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "AndroidAnimation.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "Animation.h"
+#include "GraphicsLayerAndroid.h"
+
+#include "Timer.h"
+#include "TimingFunction.h"
+#include "UnitBezier.h"
+
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+
+void AndroidTransformAnimationValue::apply()
+{
+ if (m_doTranslation)
+ m_layer->setTranslation(m_translation);
+
+ if (m_doScaling)
+ m_layer->setScale(m_scale);
+
+ if (m_doRotation)
+ m_layer->setRotation(m_rotation);
+}
+
+void AndroidAnimationTimer::fired()
+{
+ if (!m_notificationSent) {
+ m_notificationSent = true;
+ if (m_layer && m_layer->client())
+ m_layer->client()->notifyAnimationStarted(m_layer, WTF::currentTime());
+ }
+}
+
+static long gDebugAndroidAnimationInstances;
+
+long AndroidAnimation::instancesCount()
+{
+ return gDebugAndroidAnimationInstances;
+}
+
+AndroidAnimation::AndroidAnimation(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime) :
+ m_contentLayer(contentLayer),
+ m_beginTime(beginTime),
+ m_duration(animation->duration()),
+ m_iterationCount(animation->iterationCount()),
+ m_currentIteration(0),
+ m_direction(animation->direction()),
+ m_timingFunction(animation->timingFunction())
+{
+ if (!static_cast<int>(beginTime)) // time not set
+ m_beginTime = WTF::currentTime();
+
+ gDebugAndroidAnimationInstances++;
+}
+
+AndroidAnimation::AndroidAnimation(AndroidAnimation* anim) :
+ m_contentLayer(anim->m_contentLayer),
+ m_beginTime(anim->m_beginTime),
+ m_duration(anim->m_duration),
+ m_iterationCount(anim->m_iterationCount),
+ m_currentIteration(0),
+ m_direction(anim->m_direction),
+ m_timingFunction(anim->m_timingFunction)
+{
+ gDebugAndroidAnimationInstances++;
+}
+
+AndroidAnimation::~AndroidAnimation()
+{
+ gDebugAndroidAnimationInstances--;
+}
+
+float AndroidAnimation::currentProgress(double time)
+{
+ if (m_beginTime <= 0.000001) // overflow or not correctly set
+ m_beginTime = time;
+
+ m_elapsedTime = time - m_beginTime;
+
+ if (m_duration <= 0)
+ m_duration = 0.000001;
+
+ if (m_elapsedTime < 0) // animation not yet started.
+ return 0;
+
+ return m_elapsedTime / m_duration;
+}
+
+bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress)
+{
+ float progress = currentProgress(time);
+
+ int currentIteration = static_cast<int>(progress);
+ if (currentIteration != m_currentIteration)
+ if (m_direction == Animation::AnimationDirectionAlternate)
+ swapDirection();
+
+ m_currentIteration = currentIteration;
+ progress -= m_currentIteration;
+
+ if ((m_currentIteration >= m_iterationCount)
+ && (m_iterationCount != Animation::IterationCountInfinite))
+ return false;
+
+ if (m_timingFunction.type() != LinearTimingFunction) {
+ UnitBezier bezier(m_timingFunction.x1(),
+ m_timingFunction.y1(),
+ m_timingFunction.x2(),
+ m_timingFunction.y2());
+ if (m_duration > 0)
+ progress = bezier.solve(progress, 1.0f / (200.0f * m_duration));
+ }
+
+ *finalProgress = progress;
+ return true;
+}
+
+PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create(LayerAndroid* contentLayer,
+ float fromValue, float toValue,
+ const Animation* animation, double beginTime)
+{
+ return adoptRef(new AndroidOpacityAnimation(contentLayer,
+ fromValue, toValue, animation, beginTime));
+}
+
+AndroidOpacityAnimation::AndroidOpacityAnimation(LayerAndroid* contentLayer,
+ float fromValue, float toValue,
+ const Animation* animation,
+ double beginTime)
+ : AndroidAnimation(contentLayer, animation, beginTime),
+ m_fromValue(fromValue), m_toValue(toValue)
+{
+}
+
+AndroidOpacityAnimation::AndroidOpacityAnimation(AndroidOpacityAnimation* anim)
+ : AndroidAnimation(anim),
+ m_fromValue(anim->m_fromValue),
+ m_toValue(anim->m_toValue)
+{
+}
+
+AndroidAnimation* AndroidOpacityAnimation::copy()
+{
+ return new AndroidOpacityAnimation(this);
+}
+
+void AndroidOpacityAnimation::swapDirection()
+{
+ float v = m_toValue;
+ m_toValue = m_fromValue;
+ m_fromValue = m_toValue;
+}
+
+bool AndroidOpacityAnimation::evaluate(double time)
+{
+ float progress;
+ if (!checkIterationsAndProgress(time, &progress))
+ return false;
+
+ if (progress < 0) // we still want to be evaluated until we get progress > 0
+ return true;
+
+ float value = m_fromValue + ((m_toValue - m_fromValue) * progress);
+ m_result = AndroidOpacityAnimationValue::create(m_contentLayer.get(), value);
+ return true;
+}
+
+PassRefPtr<AndroidTransformAnimation> AndroidTransformAnimation::create(LayerAndroid* contentLayer,
+ const Animation* animation, double beginTime)
+{
+ return adoptRef(new AndroidTransformAnimation(contentLayer, animation, beginTime));
+}
+
+AndroidTransformAnimation::AndroidTransformAnimation(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime)
+ : AndroidAnimation(contentLayer, animation, beginTime),
+ m_doTranslation(false),
+ m_doScaling(false),
+ m_doRotation(false)
+{
+}
+
+AndroidTransformAnimation::AndroidTransformAnimation(AndroidTransformAnimation* anim)
+ : AndroidAnimation(anim),
+ m_doTranslation(anim->m_doTranslation),
+ m_doScaling(anim->m_doScaling),
+ m_doRotation(anim->m_doRotation),
+ m_position(anim->m_position),
+ m_fromX(anim->m_fromX), m_fromY(anim->m_fromY), m_fromZ(anim->m_fromZ),
+ m_toX(anim->m_toX), m_toY(anim->m_toY), m_toZ(anim->m_toZ),
+ m_fromAngle(anim->m_fromAngle), m_toAngle(anim->m_toAngle),
+ m_fromScaleX(anim->m_fromScaleX), m_fromScaleY(anim->m_fromScaleY), m_fromScaleZ(anim->m_fromScaleZ),
+ m_toScaleX(anim->m_toScaleX), m_toScaleY(anim->m_toScaleY), m_toScaleZ(anim->m_toScaleZ)
+{
+}
+
+AndroidAnimation* AndroidTransformAnimation::copy()
+{
+ return new AndroidTransformAnimation(this);
+}
+
+void AndroidTransformAnimation::setRotation(float fA, float tA)
+{
+ m_fromAngle = fA;
+ m_toAngle = tA;
+ m_doRotation = true;
+}
+
+void AndroidTransformAnimation::setTranslation(float fX, float fY, float fZ,
+ float tX, float tY, float tZ)
+{
+ m_fromX = fX;
+ m_fromY = fY;
+ m_fromZ = fZ;
+ m_toX = tX;
+ m_toY = tY;
+ m_toZ = tZ;
+ m_doTranslation = true;
+}
+
+void AndroidTransformAnimation::setScale(float fX, float fY, float fZ,
+ float tX, float tY, float tZ)
+{
+ m_fromScaleX = fX;
+ m_fromScaleY = fY;
+ m_fromScaleZ = fZ;
+ m_toScaleX = tX;
+ m_toScaleY = tY;
+ m_toScaleZ = tZ;
+ m_doScaling = true;
+}
+
+void AndroidTransformAnimation::swapDirection()
+{
+ if (m_doTranslation) {
+ float tx = m_toX;
+ m_toX = m_fromX;
+ m_fromX = tx;
+ float ty = m_toY;
+ m_toY = m_fromY;
+ m_fromY = ty;
+ float tz = m_toZ;
+ m_toZ = m_fromZ;
+ m_fromZ = tz;
+ }
+ if (m_doScaling) {
+ float sx = m_toScaleX;
+ m_toScaleX = m_fromScaleX;
+ m_fromScaleX = sx;
+ float sy = m_toScaleY;
+ m_toScaleY = m_fromScaleY;
+ m_fromScaleY = sy;
+ }
+ if (m_doRotation) {
+ float a = m_toAngle;
+ m_toAngle = m_fromAngle;
+ m_fromAngle = a;
+ }
+}
+
+bool AndroidTransformAnimation::evaluate(double time)
+{
+ float progress;
+ if (!checkIterationsAndProgress(time, &progress))
+ return false;
+
+ if (progress < 0) // we still want to be evaluated until we get progress > 0
+ return true;
+
+ float x = m_fromX + (m_toX - m_fromX) * progress;
+ float y = m_fromY + (m_toY - m_fromY) * progress;
+ float z = m_fromZ + (m_toZ - m_fromZ) * progress;
+ float sx = m_fromScaleX + (m_toScaleX - m_fromScaleX) * progress;
+ float sy = m_fromScaleY + (m_toScaleY - m_fromScaleY) * progress;
+ float sz = m_fromScaleZ + (m_toScaleZ - m_fromScaleZ) * progress;
+ float a = m_fromAngle + (m_toAngle - m_fromAngle) * progress;
+
+ FloatPoint translation(x, y);
+ FloatPoint3D scale(sx, sy, sz);
+ m_result = AndroidTransformAnimationValue::create(m_contentLayer.get(),
+ translation, scale, a);
+ m_result->setDoTranslation(m_doTranslation);
+ m_result->setDoScaling(m_doScaling);
+ m_result->setDoRotation(m_doRotation);
+ return true;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/android/AndroidAnimation.h b/WebCore/platform/graphics/android/AndroidAnimation.h
new file mode 100644
index 0000000..05d6a76
--- /dev/null
+++ b/WebCore/platform/graphics/android/AndroidAnimation.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AndroidAnimation_h
+#define AndroidAnimation_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatPoint.h"
+#include "FloatPoint3D.h"
+#include "HashMap.h"
+#include "LayerAndroid.h"
+#include "RefPtr.h"
+#include "Timer.h"
+#include "Vector.h"
+
+namespace WebCore {
+
+class AndroidAnimation;
+class GraphicsLayerAndroid;
+class TimingFunction;
+
+typedef Vector<RefPtr<AndroidAnimation> > AnimsVector;
+typedef HashMap<RefPtr<LayerAndroid>, AnimsVector* > LayersAnimsMap;
+
+class AndroidAnimationValue : public RefCounted<AndroidAnimationValue> {
+ public:
+ AndroidAnimationValue(LayerAndroid* layer) : m_layer(layer) { }
+ virtual ~AndroidAnimationValue() { }
+ virtual void apply() = 0;
+ protected:
+ RefPtr<LayerAndroid> m_layer;
+};
+
+class AndroidOpacityAnimationValue : public AndroidAnimationValue {
+ public:
+ static PassRefPtr<AndroidOpacityAnimationValue> create(
+ LayerAndroid* layer, float value) {
+ return adoptRef(new AndroidOpacityAnimationValue(layer, value));
+ }
+ AndroidOpacityAnimationValue(LayerAndroid* layer, float value) :
+ AndroidAnimationValue(layer), m_value(value) { }
+ virtual void apply() { m_layer->setOpacity(m_value); }
+ private:
+ float m_value;
+};
+
+class AndroidTransformAnimationValue : public AndroidAnimationValue {
+ public:
+ static PassRefPtr<AndroidTransformAnimationValue> create(
+ LayerAndroid* layer,
+ FloatPoint translation,
+ FloatPoint3D scale,
+ float rotation) {
+ return adoptRef(new AndroidTransformAnimationValue(layer, translation, scale, rotation));
+ }
+
+ AndroidTransformAnimationValue(LayerAndroid* layer,
+ FloatPoint translation,
+ FloatPoint3D scale,
+ float rotation) :
+ AndroidAnimationValue(layer),
+ m_doTranslation(false), m_doScaling(false), m_doRotation(false),
+ m_translation(translation), m_scale(scale), m_rotation(rotation) { }
+ void setDoTranslation(bool doTranslation) { m_doTranslation = doTranslation; }
+ void setDoScaling(bool doScaling) { m_doScaling = doScaling; }
+ void setDoRotation(bool doRotation) { m_doRotation = doRotation; }
+
+ virtual void apply();
+
+ private:
+ bool m_doTranslation;
+ bool m_doScaling;
+ bool m_doRotation;
+ FloatPoint m_translation;
+ FloatPoint3D m_scale;
+ float m_rotation;
+};
+
+class AndroidAnimation : public RefCounted<AndroidAnimation> {
+ public:
+ AndroidAnimation(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime);
+ AndroidAnimation(AndroidAnimation* anim);
+
+ virtual ~AndroidAnimation();
+ virtual AndroidAnimation* copy() = 0;
+ float currentProgress(double time);
+ bool checkIterationsAndProgress(double time, float* finalProgress);
+ virtual void swapDirection() = 0;
+ virtual bool evaluate(double time) = 0;
+ LayerAndroid* contentLayer() { return m_contentLayer.get(); }
+ static long instancesCount();
+ void setLayer(LayerAndroid* layer) { m_contentLayer = layer; }
+ void setName(const String& name) { m_name = name; }
+ String name() { return m_name; }
+ virtual PassRefPtr<AndroidAnimationValue> result() = 0;
+
+ protected:
+ RefPtr<LayerAndroid> m_contentLayer;
+ double m_beginTime;
+ double m_elapsedTime;
+ double m_duration;
+ int m_iterationCount;
+ int m_currentIteration;
+ int m_direction;
+ TimingFunction m_timingFunction;
+ String m_name;
+};
+
+class AndroidOpacityAnimation : public AndroidAnimation {
+ public:
+ static PassRefPtr<AndroidOpacityAnimation> create(LayerAndroid* contentLayer,
+ float fromValue, float toValue,
+ const Animation* animation,
+ double beginTime);
+ AndroidOpacityAnimation(LayerAndroid* contentLayer,
+ float fromValue, float toValue,
+ const Animation* animation,
+ double beginTime);
+ AndroidOpacityAnimation(AndroidOpacityAnimation* anim);
+ virtual AndroidAnimation* copy();
+ virtual PassRefPtr<AndroidAnimationValue> result() { return m_result.release(); }
+
+ virtual void swapDirection();
+ virtual bool evaluate(double time);
+
+ private:
+ RefPtr<AndroidOpacityAnimationValue> m_result;
+ float m_fromValue;
+ float m_toValue;
+};
+
+class AndroidTransformAnimation : public AndroidAnimation {
+ public:
+ static PassRefPtr<AndroidTransformAnimation> create(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime);
+ AndroidTransformAnimation(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime);
+
+ AndroidTransformAnimation(AndroidTransformAnimation* anim);
+ virtual AndroidAnimation* copy();
+
+ void setOriginalPosition(FloatPoint position) { m_position = position; }
+ void setRotation(float fA, float tA);
+ void setTranslation(float fX, float fY, float fZ,
+ float tX, float tY, float tZ);
+ void setScale(float fX, float fY, float fZ,
+ float tX, float tY, float tZ);
+ virtual void swapDirection();
+ virtual bool evaluate(double time);
+ virtual PassRefPtr<AndroidAnimationValue> result() { return m_result.release(); }
+
+ private:
+ RefPtr<AndroidTransformAnimationValue> m_result;
+ bool m_doTranslation;
+ bool m_doScaling;
+ bool m_doRotation;
+ FloatPoint m_position;
+ float m_fromX, m_fromY, m_fromZ;
+ float m_toX, m_toY, m_toZ;
+ float m_fromAngle, m_toAngle;
+ float m_fromScaleX, m_fromScaleY, m_fromScaleZ;
+ float m_toScaleX, m_toScaleY, m_toScaleZ;
+};
+
+class AndroidAnimationTimer : public TimerBase {
+ public:
+
+ AndroidAnimationTimer(GraphicsLayerAndroid* layer, double beginTime)
+ {
+ m_layer = layer;
+ m_notificationSent = false;
+ m_beginTime = beginTime;
+ }
+
+ private:
+ void fired();
+ GraphicsLayerAndroid* m_layer;
+ double m_beginTime;
+ bool m_notificationSent;
+};
+
+} // namespace WebCore
+
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // AndroidAnimation_h
diff --git a/WebCore/platform/graphics/android/BitmapAllocatorAndroid.cpp b/WebCore/platform/graphics/android/BitmapAllocatorAndroid.cpp
index 0f6057d..66340ee 100644
--- a/WebCore/platform/graphics/android/BitmapAllocatorAndroid.cpp
+++ b/WebCore/platform/graphics/android/BitmapAllocatorAndroid.cpp
@@ -1,17 +1,26 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright 2009, The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * 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.
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * 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 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"
@@ -60,4 +69,3 @@ bool BitmapAllocatorAndroid::allocPixelRef(SkBitmap* bitmap, SkColorTable*)
}
}
-
diff --git a/WebCore/platform/graphics/android/BitmapAllocatorAndroid.h b/WebCore/platform/graphics/android/BitmapAllocatorAndroid.h
index f2b2223..7b401d0 100644
--- a/WebCore/platform/graphics/android/BitmapAllocatorAndroid.h
+++ b/WebCore/platform/graphics/android/BitmapAllocatorAndroid.h
@@ -1,17 +1,26 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright 2009, The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * 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.
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * 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 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 WebCore_BitmapAllocatorAndroid_DEFINED
diff --git a/WebCore/platform/graphics/android/FontAndroid.cpp b/WebCore/platform/graphics/android/FontAndroid.cpp
index a430b07..36c6248 100644
--- a/WebCore/platform/graphics/android/FontAndroid.cpp
+++ b/WebCore/platform/graphics/android/FontAndroid.cpp
@@ -5,23 +5,23 @@
* 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
+ * * 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
+ * * 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
+ * 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
+ * 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
diff --git a/WebCore/platform/graphics/android/FontCacheAndroid.cpp b/WebCore/platform/graphics/android/FontCacheAndroid.cpp
index 0b3655f..ef795de 100644
--- a/WebCore/platform/graphics/android/FontCacheAndroid.cpp
+++ b/WebCore/platform/graphics/android/FontCacheAndroid.cpp
@@ -5,26 +5,23 @@
* 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.
*
- * 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.
+ * 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 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"
@@ -131,4 +128,3 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne
}
}
-
diff --git a/WebCore/platform/graphics/android/FontCustomPlatformData.cpp b/WebCore/platform/graphics/android/FontCustomPlatformData.cpp
index bb465ef..d954e70 100644
--- a/WebCore/platform/graphics/android/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/android/FontCustomPlatformData.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
diff --git a/WebCore/platform/graphics/android/FontCustomPlatformData.h b/WebCore/platform/graphics/android/FontCustomPlatformData.h
index 910d616..1d11e59 100644
--- a/WebCore/platform/graphics/android/FontCustomPlatformData.h
+++ b/WebCore/platform/graphics/android/FontCustomPlatformData.h
@@ -13,7 +13,7 @@
* 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
+ * 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
@@ -54,4 +54,3 @@ namespace WebCore {
} // namespace WebCore
#endif // FontCustomPlatformData_h_
-
diff --git a/WebCore/platform/graphics/android/FontDataAndroid.cpp b/WebCore/platform/graphics/android/FontDataAndroid.cpp
index 2bb53e4..ca54eb3 100644
--- a/WebCore/platform/graphics/android/FontDataAndroid.cpp
+++ b/WebCore/platform/graphics/android/FontDataAndroid.cpp
@@ -5,26 +5,23 @@
* 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.
*
- * 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.
+ * 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 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"
diff --git a/WebCore/platform/graphics/android/FontPlatformData.h b/WebCore/platform/graphics/android/FontPlatformData.h
index d7761a8..bb6b1c3 100644
--- a/WebCore/platform/graphics/android/FontPlatformData.h
+++ b/WebCore/platform/graphics/android/FontPlatformData.h
@@ -1,27 +1,32 @@
/*
- * 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 2009, The Android Open Source Project
* Copyright (C) 2006 Apple Computer, Inc.
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * 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 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.
*/
+// 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.
+
#ifndef FontPlatformData_H
#define FontPlatformData_H
diff --git a/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp b/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
index 3fcf3fe..640940f 100644
--- a/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
+++ b/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
@@ -1,27 +1,32 @@
/*
- * 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 2009, The Android Open Source Project
* Copyright (C) 2006 Apple Computer, Inc.
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * 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 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.
*/
+//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.
+
#include "config.h"
#include "FontPlatformData.h"
@@ -181,4 +186,3 @@ unsigned FontPlatformData::hash() const
}
}
-
diff --git a/WebCore/platform/graphics/android/GlyphMapAndroid.cpp b/WebCore/platform/graphics/android/GlyphMapAndroid.cpp
index fe64c9a..da9d99a 100644
--- a/WebCore/platform/graphics/android/GlyphMapAndroid.cpp
+++ b/WebCore/platform/graphics/android/GlyphMapAndroid.cpp
@@ -5,26 +5,23 @@
* 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.
*
- * 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.
+ * 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 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"
@@ -87,4 +84,3 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
}
}
-
diff --git a/WebCore/platform/graphics/android/GradientAndroid.cpp b/WebCore/platform/graphics/android/GradientAndroid.cpp
index 8334d1c..72ae336 100644
--- a/WebCore/platform/graphics/android/GradientAndroid.cpp
+++ b/WebCore/platform/graphics/android/GradientAndroid.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
@@ -90,9 +90,11 @@ SkShader* Gradient::getShader(SkShader::TileMode mode)
SkShader* s;
if (m_radial)
- // FIXME: SVG always passes 0 for m_r0
- s = SkGradientShader::CreateRadial(pts[0],
- SkFloatToScalar(m_r0 ? m_r0 : m_r1), colors, pos, count, mode);
+ s = SkGradientShader::CreateTwoPointRadial(pts[0],
+ SkFloatToScalar(m_r0),
+ pts[1],
+ SkFloatToScalar(m_r1),
+ colors, pos, count, mode);
else
s = SkGradientShader::CreateLinear(pts, colors, pos, count, mode);
diff --git a/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
index 34b709b..9a86b84 100644
--- a/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
+++ b/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
@@ -247,6 +247,13 @@ public:
paint->setColor(mState->applyAlpha(mState->mFillColor));
}
+ void setup_paint_bitmap(SkPaint* paint) const {
+ this->setup_paint_common(paint);
+ // we only want the global alpha for bitmaps,
+ // so just give applyAlpha opaque black
+ paint->setColor(mState->applyAlpha(0xFF000000));
+ }
+
/* sets up the paint for stroking. Returns true if the style is really
just a dash of squares (the size of the paint's stroke-width.
*/
@@ -323,23 +330,15 @@ static SkShader::TileMode SpreadMethod2TileMode(GradientSpreadMethod sm) {
return mode;
}
-static void extactShader(SkPaint* paint, ColorSpace cs, Pattern* pat,
- Gradient* grad)
+static void extactShader(SkPaint* paint, Pattern* pat, Gradient* grad)
{
- switch (cs) {
- case PatternColorSpace:
- // createPlatformPattern() returns a new inst
- paint->setShader(pat->createPlatformPattern(
- TransformationMatrix()))->safeUnref();
- break;
- case GradientColorSpace: {
- // grad->getShader() returns a cached obj
- GradientSpreadMethod sm = grad->spreadMethod();
- paint->setShader(grad->getShader(SpreadMethod2TileMode(sm)));
- break;
- }
- default:
- break;
+ if (pat) {
+ // createPlatformPattern() returns a new inst
+ paint->setShader(pat->createPlatformPattern(TransformationMatrix()))->safeUnref();
+ } else if (grad) {
+ // grad->getShader() returns a cached obj
+ GradientSpreadMethod sm = grad->spreadMethod();
+ paint->setShader(grad->getShader(SpreadMethod2TileMode(sm)));
}
}
@@ -639,7 +638,7 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* poin
}
void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
- const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+ const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace)
{
if (paintingDisabled())
return;
@@ -668,14 +667,14 @@ void GraphicsContext::fillRect(const FloatRect& rect)
m_data->setup_paint_fill(&paint);
- extactShader(&paint, m_common->state.fillColorSpace,
+ extactShader(&paint,
m_common->state.fillPattern.get(),
m_common->state.fillGradient.get());
GC2Canvas(this)->drawRect(rect, paint);
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace)
{
if (paintingDisabled())
return;
@@ -752,6 +751,11 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
GC2Canvas(this)->clipPath(path);
}
+void GraphicsContext::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
void GraphicsContext::clipOut(const IntRect& r)
{
if (paintingDisabled())
@@ -831,10 +835,14 @@ void GraphicsContext::endTransparencyLayer()
///////////////////////////////////////////////////////////////////////////
+ void GraphicsContext::setupBitmapPaint(SkPaint* paint) {
+ m_data->setup_paint_bitmap(paint);
+ }
+
void GraphicsContext::setupFillPaint(SkPaint* paint) {
m_data->setup_paint_fill(paint);
}
-
+
void GraphicsContext::setupStrokePaint(SkPaint* paint) {
m_data->setup_paint_stroke(paint, NULL);
}
@@ -842,24 +850,8 @@ void GraphicsContext::endTransparencyLayer()
bool GraphicsContext::setupShadowPaint(SkPaint* paint, SkPoint* offset) {
return m_data->mState->setupShadowPaint(paint, offset);
}
-
- // referenced from CanvasStyle.cpp
- void GraphicsContext::setCMYKAFillColor(float c, float m, float y, float k, float a) {
- float r = 1 - (c + k);
- float g = 1 - (m + k);
- float b = 1 - (y + k);
- return this->setFillColor(Color(r, g, b, a));
- }
- // referenced from CanvasStyle.cpp
- void GraphicsContext::setCMYKAStrokeColor(float c, float m, float y, float k, float a) {
- float r = 1 - (c + k);
- float g = 1 - (m + k);
- float b = 1 - (y + k);
- return this->setStrokeColor(Color(r, g, b, a));
- }
-
- void GraphicsContext::setPlatformStrokeColor(const Color& c) {
+ void GraphicsContext::setPlatformStrokeColor(const Color& c, ColorSpace) {
m_data->setStrokeColor(c);
}
@@ -867,11 +859,11 @@ void GraphicsContext::endTransparencyLayer()
m_data->setStrokeThickness(f);
}
- void GraphicsContext::setPlatformFillColor(const Color& c) {
+ void GraphicsContext::setPlatformFillColor(const Color& c, ColorSpace) {
m_data->setFillColor(c);
}
-void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color)
+void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace)
{
if (paintingDisabled())
return;
@@ -1038,16 +1030,21 @@ void GraphicsContext::concatCTM(const TransformationMatrix& xform)
GC2Canvas(this)->concat((SkMatrix) xform);
}
+/* This is intended to round the rect to device pixels (through the CTM)
+ and then invert the result back into source space, with the hope that when
+ it is drawn (through the matrix), it will land in the "right" place (i.e.
+ on pixel boundaries).
+
+ For android, we record this geometry once and then draw it though various
+ scale factors as the user zooms, without re-recording. Thus this routine
+ should just leave the original geometry alone.
+
+ If we instead draw into bitmap tiles, we should then perform this
+ transform -> round -> inverse step.
+ */
FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
{
- if (paintingDisabled())
- return FloatRect();
-
- const SkMatrix& matrix = GC2Canvas(this)->getTotalMatrix();
- SkRect r(rect);
- matrix.mapRect(&r);
- FloatRect result(SkScalarToFloat(r.fLeft), SkScalarToFloat(r.fTop), SkScalarToFloat(r.width()), SkScalarToFloat(r.height()));
- return result;
+ return rect;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1126,7 +1123,7 @@ void GraphicsContext::fillPath()
SkPaint paint;
m_data->setup_paint_fill(&paint);
- extactShader(&paint, m_common->state.fillColorSpace,
+ extactShader(&paint,
m_common->state.fillPattern.get(),
m_common->state.fillGradient.get());
@@ -1142,7 +1139,7 @@ void GraphicsContext::strokePath()
SkPaint paint;
m_data->setup_paint_stroke(&paint, NULL);
- extactShader(&paint, m_common->state.strokeColorSpace,
+ extactShader(&paint,
m_common->state.strokePattern.get(),
m_common->state.strokeGradient.get());
@@ -1175,4 +1172,3 @@ SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc)
{
return gc->platformContext()->mCanvas;
}
-
diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
new file mode 100644
index 0000000..fa012b0
--- /dev/null
+++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -0,0 +1,851 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "GraphicsLayerAndroid.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "AndroidAnimation.h"
+#include "Animation.h"
+#include "CString.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "Image.h"
+#include "PlatformBridge.h"
+#include "PlatformGraphicsContext.h"
+#include "RenderLayerBacking.h"
+#include "RenderView.h"
+#include "RotateTransformOperation.h"
+#include "ScaleTransformOperation.h"
+#include "SkCanvas.h"
+#include "TransformationMatrix.h"
+#include "TranslateTransformOperation.h"
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+
+#undef LOG
+#define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
+#define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
+#define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
+
+#undef LOG
+#define LOG(...)
+#undef MLOG
+#define MLOG(...)
+#undef TLOG
+#define TLOG(...)
+#undef LAYER_DEBUG
+
+using namespace std;
+
+static bool gPaused;
+static double gPausedDelay;
+
+namespace WebCore {
+
+static int gDebugGraphicsLayerAndroidInstances = 0;
+inline int GraphicsLayerAndroid::instancesCount()
+{
+ return gDebugGraphicsLayerAndroidInstances;
+}
+
+static String propertyIdToString(AnimatedPropertyID property)
+{
+ switch (property) {
+ case AnimatedPropertyWebkitTransform:
+ return "transform";
+ case AnimatedPropertyOpacity:
+ return "opacity";
+ case AnimatedPropertyBackgroundColor:
+ return "backgroundColor";
+ case AnimatedPropertyInvalid:
+ ASSERT_NOT_REACHED();
+ }
+ ASSERT_NOT_REACHED();
+ return "";
+}
+
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
+{
+ return CompositingCoordinatesBottomUp;
+}
+
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerAndroid(client);
+}
+
+GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
+ GraphicsLayer(client),
+ m_needsSyncChildren(false),
+ m_needsSyncMask(false),
+ m_needsRepaint(false),
+ m_needsDisplay(false),
+ m_haveContents(false),
+ m_haveImage(false),
+ m_translateX(0),
+ m_translateY(0),
+ m_currentTranslateX(0),
+ m_currentTranslateY(0),
+ m_currentPosition(0, 0)
+{
+ m_contentLayer = new LayerAndroid(true);
+ if (client) {
+ RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(client);
+ RenderLayer* renderLayer = backing->owningLayer();
+ m_contentLayer->setIsRootLayer(renderLayer->isRootLayer());
+ RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
+ if (view->isPositioned() && view->style()->position() == FixedPosition) {
+ m_contentLayer->setFixedPosition(view->style()->left(),
+ view->style()->top(),
+ view->style()->right(),
+ view->style()->bottom());
+ }
+ }
+ gDebugGraphicsLayerAndroidInstances++;
+}
+
+GraphicsLayerAndroid::~GraphicsLayerAndroid()
+{
+ gDebugGraphicsLayerAndroidInstances--;
+}
+
+void GraphicsLayerAndroid::setName(const String& name)
+{
+ GraphicsLayer::setName(name);
+}
+
+NativeLayer GraphicsLayerAndroid::nativeLayer() const
+{
+ LOG("(%x) nativeLayer", this);
+ return 0;
+}
+
+bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool childrenChanged = GraphicsLayer::setChildren(children);
+ if (childrenChanged) {
+ m_needsSyncChildren = true;
+ askForSync();
+ }
+
+ return childrenChanged;
+}
+
+void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
+{
+#ifndef NDEBUG
+ const char* n = (static_cast<GraphicsLayerAndroid*>(childLayer))->m_name.latin1().data();
+ LOG("(%x) addChild: %x (%s)", this, childLayer, n);
+#endif
+ GraphicsLayer::addChild(childLayer);
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
+{
+ LOG("(%x) addChild %x AtIndex %d", this, childLayer, index);
+ GraphicsLayer::addChildAtIndex(childLayer, index);
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ LOG("(%x) addChild %x Below %x", this, childLayer, sibling);
+ GraphicsLayer::addChildBelow(childLayer, sibling);
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ LOG("(%x) addChild %x Above %x", this, childLayer, sibling);
+ GraphicsLayer::addChildAbove(childLayer, sibling);
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ LOG("(%x) replaceChild %x by %x", this, oldChild, newChild);
+ bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
+ m_needsSyncChildren = true;
+ askForSync();
+ return ret;
+}
+
+void GraphicsLayerAndroid::removeFromParent()
+{
+ LOG("(%x) removeFromParent()", this);
+ if (m_parent)
+ static_cast<GraphicsLayerAndroid*>(m_parent)->needsSyncChildren();
+ GraphicsLayer::removeFromParent();
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::needsSyncChildren()
+{
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
+{
+ m_currentPosition = point;
+ m_needsDisplay = true;
+#ifdef LAYER_DEBUG_2
+ LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
+ this, point.x(), point.y(), m_currentPosition.x(), m_currentPosition.y(),
+ m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
+#endif
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point)
+{
+ GraphicsLayer::setAnchorPoint(point);
+ m_contentLayer->setAnchorPoint(point);
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setSize(const FloatSize& size)
+{
+ if ((size.width() != m_size.width())
+ || (size.height() != m_size.height())) {
+ MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
+ GraphicsLayer::setSize(size);
+ m_contentLayer->setSize(size);
+ askForSync();
+ }
+}
+
+void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
+{
+ TransformationMatrix::DecomposedType tDecomp;
+ t.decompose(tDecomp);
+ LOG("(%x) setTransform, translate (%.2f, %.2f), mpos(%.2f,%.2f)",
+ this, tDecomp.translateX, tDecomp.translateY,
+ m_position.x(), m_position.y());
+
+ if ((m_currentTranslateX != tDecomp.translateX)
+ || (m_currentTranslateY != tDecomp.translateY)) {
+ m_currentTranslateX = tDecomp.translateX;
+ m_currentTranslateY = tDecomp.translateY;
+ m_needsDisplay = true;
+ askForSync();
+ }
+}
+
+void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
+{
+ if (t == m_childrenTransform)
+ return;
+ LOG("(%x) setChildrenTransform", this);
+
+ GraphicsLayer::setChildrenTransform(t);
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ GraphicsLayer* layer = m_children[i];
+ layer->setTransform(t);
+ if (layer->children().size())
+ layer->setChildrenTransform(t);
+ }
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
+{
+ if (layer == m_maskLayer)
+ return;
+
+ GraphicsLayer::setMaskLayer(layer);
+ m_needsSyncMask = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
+{
+ GraphicsLayer::setMasksToBounds(masksToBounds);
+ m_needsSyncMask = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
+{
+ GraphicsLayer::setDrawsContent(drawsContent);
+ m_contentLayer->setDrawsContent(m_drawsContent);
+
+ if (m_drawsContent) {
+ m_haveContents = true;
+ m_contentLayer->setHaveContents(true);
+ setNeedsDisplay();
+ }
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
+{
+ LOG("(%x) setBackgroundColor", this);
+ GraphicsLayer::setBackgroundColor(color);
+ m_contentLayer->setBackgroundColor(color);
+ m_haveContents = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::clearBackgroundColor()
+{
+ LOG("(%x) clearBackgroundColor", this);
+ GraphicsLayer::clearBackgroundColor();
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
+{
+ LOG("(%x) setContentsOpaque (%d)", this, opaque);
+ GraphicsLayer::setContentsOpaque(opaque);
+ m_haveContents = true;
+ m_contentLayer->setHaveContents(true);
+ m_contentLayer->setDrawsContent(true);
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setOpacity(float opacity)
+{
+ LOG("(%x) setOpacity: %.2f", this, opacity);
+ float clampedOpacity = max(0.0f, min(opacity, 1.0f));
+
+ if (clampedOpacity == m_opacity)
+ return;
+
+ MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
+ opacity, clampedOpacity, m_opacity);
+ GraphicsLayer::setOpacity(clampedOpacity);
+ m_contentLayer->setOpacity(clampedOpacity);
+ askForSync();
+}
+
+bool GraphicsLayerAndroid::repaintAll()
+{
+ LOG("(%x) repaintAll", this);
+ bool ret = false;
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
+ if (layer && layer->repaintAll())
+ ret = true;
+ }
+ int nbRects = m_invalidatedRects.size();
+
+ for (int i = 0; !gPaused && i < nbRects; i++) {
+ FloatRect rect = m_invalidatedRects[i];
+ if (repaint(rect))
+ ret = true;
+ }
+ if (!gPaused) {
+ m_needsRepaint = false;
+ m_invalidatedRects.clear();
+ }
+ return ret;
+}
+
+void GraphicsLayerAndroid::setNeedsDisplay()
+{
+ LOG("(%x) setNeedsDisplay()", this);
+ FloatRect rect(0, 0, m_size.width(), m_size.height());
+ setNeedsDisplayInRect(rect);
+}
+
+void GraphicsLayerAndroid::setFrame(Frame* f)
+{
+ m_frame = f;
+}
+
+void GraphicsLayerAndroid::sendImmediateRepaint()
+{
+ LOG("(%x) sendImmediateRepaint()", this);
+ GraphicsLayerAndroid* rootGraphicsLayer = this;
+
+ while (rootGraphicsLayer->parent())
+ rootGraphicsLayer = static_cast<GraphicsLayerAndroid*>(rootGraphicsLayer->parent());
+
+ if (rootGraphicsLayer->m_frame
+ && rootGraphicsLayer->m_frame->view()) {
+ LayerAndroid* copyLayer = new LayerAndroid(m_contentLayer.get());
+ TLOG("(%x) sendImmediateRepaint, copy the layer, (%.2f,%.2f => %.2f,%.2f)",
+ this, m_contentLayer->size().width(), m_contentLayer->size().height(),
+ copyLayer->size().width(), copyLayer->size().height());
+ PlatformBridge::setRootLayer(m_frame->view(), (int)copyLayer);
+ PlatformBridge::immediateRepaint(m_frame->view());
+ }
+}
+
+bool GraphicsLayerAndroid::repaint(const FloatRect& rect)
+{
+ LOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
+ this, rect.x(), rect.y(), rect.width(), rect.height(),
+ gPaused, m_needsRepaint, m_haveContents);
+
+ m_contentLayer->setDrawsContent(true);
+
+ if (!gPaused && m_haveContents && m_needsRepaint) {
+ SkAutoPictureRecord arp(m_contentLayer->recordContext(), m_size.width(), m_size.height());
+ SkCanvas* recordingCanvas = arp.getRecordingCanvas();
+
+ if (!recordingCanvas)
+ return false;
+
+ if ((rect.width() > 0.5) && (rect.height() > 0.5)) {
+ IntRect r((int)rect.x(), (int)rect.y(),
+ (int)rect.width(), (int)rect.height());
+
+ PlatformGraphicsContext pgc(recordingCanvas, 0);
+ GraphicsContext gc(&pgc);
+
+ // with SkPicture, we request the entire layer's content.
+ r.setX(0);
+ r.setY(0);
+ r.setWidth(m_contentLayer->size().width());
+ r.setHeight(m_contentLayer->size().height());
+ paintGraphicsLayerContents(gc, r);
+
+ TLOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f) on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
+ this, rect.x(), rect.y(), rect.width(),
+ rect.height(), m_size.width(), m_size.height(),
+ m_contentLayer->position().x(),
+ m_contentLayer->position().y(),
+ m_contentLayer->size().width(),
+ m_contentLayer->size().height());
+ }
+ return true;
+ }
+ return false;
+}
+
+void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
+ if (layer) {
+ FloatRect childrenRect(m_position.x() + m_translateX + rect.x(),
+ m_position.y() + m_translateY + rect.y(),
+ rect.width(), rect.height());
+ layer->setNeedsDisplayInRect(childrenRect);
+ }
+ }
+ if (!m_haveImage && !drawsContent()) {
+ LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
+ this, rect.x(), rect.y(), rect.width(), rect.height());
+ return;
+ }
+
+ const size_t maxDirtyRects = 8;
+ for (size_t i = 0; i < m_invalidatedRects.size(); ++i) {
+ if (m_invalidatedRects[i].contains(rect))
+ return;
+ }
+
+#ifdef LAYER_DEBUG
+ LOG("(%x) setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this,
+ m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height());
+#endif
+
+ if (m_invalidatedRects.size() < maxDirtyRects)
+ m_invalidatedRects.append(rect);
+ else
+ m_invalidatedRects[0].unite(rect);
+
+ m_needsRepaint = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::pauseDisplay(bool state)
+{
+ gPaused = state;
+ if (gPaused)
+ gPausedDelay = WTF::currentTime() + 1;
+}
+
+bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
+ const IntSize& boxSize,
+ const Animation* anim,
+ const String& keyframesName,
+ double beginTime)
+{
+ if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
+ return false;
+
+ bool createdAnimations = false;
+ if (valueList.property() == AnimatedPropertyWebkitTransform) {
+ createdAnimations = createTransformAnimationsFromKeyframes(valueList,
+ anim,
+ keyframesName,
+ beginTime,
+ boxSize);
+ } else {
+ createdAnimations = createAnimationFromKeyframes(valueList,
+ anim,
+ keyframesName,
+ beginTime);
+ }
+ askForSync();
+ return createdAnimations;
+}
+
+bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
+ const Animation* animation, const String& keyframesName, double beginTime)
+{
+ bool isKeyframe = valueList.size() > 2;
+ TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
+ isKeyframe, keyframesName.latin1().data(), beginTime);
+ // TODO: handles keyframe animations correctly
+
+ switch (valueList.property()) {
+ case AnimatedPropertyInvalid: break;
+ case AnimatedPropertyWebkitTransform: break;
+ case AnimatedPropertyBackgroundColor: break;
+ case AnimatedPropertyOpacity: {
+ MLOG("ANIMATEDPROPERTYOPACITY");
+ const FloatAnimationValue* startVal =
+ static_cast<const FloatAnimationValue*>(valueList.at(0));
+ const FloatAnimationValue* endVal =
+ static_cast<const FloatAnimationValue*>(valueList.at(1));
+ RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(m_contentLayer.get(),
+ startVal->value(),
+ endVal->value(),
+ animation,
+ beginTime);
+ if (keyframesName.isEmpty())
+ anim->setName(propertyIdToString(valueList.property()));
+ else
+ anim->setName(keyframesName);
+
+ m_contentLayer->addAnimation(anim.release());
+ AndroidAnimationTimer* timer = new AndroidAnimationTimer(this, WTF::currentTime());
+ timer->startOneShot(0);
+ return true;
+ } break;
+ }
+ return false;
+}
+
+bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
+ const Animation* animation,
+ const String& keyframesName,
+ double beginTime,
+ const IntSize& boxSize)
+{
+ ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
+ TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
+ keyframesName.latin1().data(), beginTime);
+
+ TransformOperationList functionList;
+ bool listsMatch, hasBigRotation;
+ fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
+
+ // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation.
+ // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
+ // if that's not true as well.
+
+ bool isMatrixAnimation = !listsMatch;
+ size_t numAnimations = isMatrixAnimation ? 1 : functionList.size();
+ bool isKeyframe = valueList.size() > 2;
+
+ float fromTranslateX = 0;
+ float fromTranslateY = 0;
+ float fromTranslateZ = 0;
+ float toTranslateX = 0;
+ float toTranslateY = 0;
+ float toTranslateZ = 0;
+ float fromAngle = 0;
+ float toAngle = 0;
+ float fromScaleX = 1;
+ float fromScaleY = 1;
+ float fromScaleZ = 1;
+ float toScaleX = 1;
+ float toScaleY = 1;
+ float toScaleZ = 1;
+
+ bool doTranslation = false;
+ bool doRotation = false;
+ bool doScaling = false;
+
+ TLOG("(%x) animateTransform, valueList(%d) functionList(%d) duration(%.2f)", this,
+ valueList.size(), functionList.size(), animation->duration());
+
+ for (unsigned int i = 0; i < valueList.size(); i++) {
+ const TransformOperations* operation = ((TransformAnimationValue*)valueList.at(i))->value();
+ Vector<RefPtr<TransformOperation> > ops = operation->operations();
+ TLOG("(%x) animateTransform, dealing with the %d operation, with %d ops", this, i, ops.size());
+ for (unsigned int j = 0; j < ops.size(); j++) {
+ TransformOperation* op = ops[j].get();
+ TLOG("(%x) animateTransform, dealing with the %d:%d operation, current op: %d (translate is %d, rotate %d, scale %d)",
+ this, i, j, op->getOperationType(), TransformOperation::TRANSLATE, TransformOperation::ROTATE, TransformOperation::SCALE);
+ if (op->getOperationType() == TransformOperation::TRANSLATE) {
+ TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
+ IntSize bounds(m_size.width(), m_size.height());
+ float x = translateOperation->x(bounds);
+ float y = translateOperation->y(bounds);
+ float z = translateOperation->z(bounds);
+ if (!i) {
+ fromTranslateX = x;
+ fromTranslateY = y;
+ fromTranslateZ = z;
+ } else {
+ toTranslateX = x;
+ toTranslateY = y;
+ toTranslateZ = z;
+ }
+ TLOG("(%x) animateTransform, the %d operation is a translation(%.2f,%.2f,%.2f)",
+ this, j, x, y, z);
+ doTranslation = true;
+ } else if (op->getOperationType() == TransformOperation::TRANSLATE_X) {
+ TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
+ IntSize bounds(m_size.width(), m_size.height());
+ float x = translateOperation->x(bounds);
+ if (!i)
+ fromTranslateX = x;
+ else
+ toTranslateX = x;
+ TLOG("(%x) animateTransform, the %d operation is a translation_x(%.2f)",
+ this, j, x);
+ doTranslation = true;
+ } else if (op->getOperationType() == TransformOperation::TRANSLATE_Y) {
+ TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
+ IntSize bounds(m_size.width(), m_size.height());
+ float y = translateOperation->y(bounds);
+ if (!i)
+ fromTranslateY = y;
+ else
+ toTranslateY = y;
+ TLOG("(%x) animateTransform, the %d operation is a translation_y(%.2f)",
+ this, j, y);
+ doTranslation = true;
+ } else if ((op->getOperationType() == TransformOperation::ROTATE)
+ || (op->getOperationType() == TransformOperation::ROTATE_X)
+ || (op->getOperationType() == TransformOperation::ROTATE_Y)) {
+ LOG("(%x) animateTransform, the %d operation is a rotation", this, j);
+ RotateTransformOperation* rotateOperation = (RotateTransformOperation*) op;
+ float angle = rotateOperation->angle();
+ TLOG("(%x) animateTransform, the %d operation is a rotation (%d), of angle %.2f",
+ this, j, op->getOperationType(), angle);
+
+ if (!i)
+ fromAngle = angle;
+ else
+ toAngle = angle;
+ doRotation = true;
+ } else if (op->getOperationType() == TransformOperation::SCALE_X) {
+ ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
+ if (!i)
+ fromScaleX = scaleOperation->x();
+ else
+ toScaleX = scaleOperation->x();
+ doScaling = true;
+ } else if (op->getOperationType() == TransformOperation::SCALE_Y) {
+ ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
+ if (!i)
+ fromScaleY = scaleOperation->y();
+ else
+ toScaleY = scaleOperation->y();
+ doScaling = true;
+ } else if (op->getOperationType() == TransformOperation::SCALE_Z) {
+ ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
+ if (!i)
+ fromScaleZ = scaleOperation->z();
+ else
+ toScaleZ = scaleOperation->z();
+ doScaling = true;
+ } else if (op->getOperationType() == TransformOperation::SCALE) {
+ ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
+ if (!i) {
+ fromScaleX = scaleOperation->x();
+ fromScaleY = scaleOperation->y();
+ fromScaleZ = scaleOperation->z();
+ } else {
+ toScaleX = scaleOperation->x();
+ toScaleY = scaleOperation->y();
+ toScaleZ = scaleOperation->z();
+ }
+ doScaling = true;
+ } else {
+ TLOG("(%x) animateTransform, the %d operation is not a rotation (%d)",
+ this, j, op->getOperationType());
+ }
+ }
+ }
+
+ RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(m_contentLayer.get(),
+ animation, beginTime);
+
+ if (keyframesName.isEmpty())
+ anim->setName(propertyIdToString(valueList.property()));
+ else
+ anim->setName(keyframesName);
+
+ anim->setOriginalPosition(m_position);
+
+ if (doTranslation)
+ anim->setTranslation(fromTranslateX, fromTranslateY, fromTranslateZ,
+ toTranslateX, toTranslateY, toTranslateZ);
+ if (doRotation)
+ anim->setRotation(fromAngle, toAngle);
+ if (doScaling)
+ anim->setScale(fromScaleX, fromScaleY, fromScaleZ,
+ toScaleX, toScaleY, toScaleZ);
+ m_contentLayer->addAnimation(anim.release());
+
+ AndroidAnimationTimer* timer = new AndroidAnimationTimer(this, WTF::currentTime());
+ timer->startOneShot(0);
+ return true;
+}
+
+void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
+{
+ TLOG("NRO removeAnimationsForProperty(%d)", anID);
+ m_contentLayer->removeAnimation(propertyIdToString(anID));
+ askForSync();
+}
+
+void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
+{
+ TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
+ m_contentLayer->removeAnimation(keyframesName);
+ askForSync();
+}
+
+void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
+{
+ TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
+}
+
+void GraphicsLayerAndroid::suspendAnimations(double time)
+{
+ TLOG("NRO suspendAnimations(%.2f)", time);
+}
+
+void GraphicsLayerAndroid::resumeAnimations()
+{
+ TLOG("NRO resumeAnimations()");
+}
+
+void GraphicsLayerAndroid::setContentsToImage(Image* image)
+{
+ TLOG("(%x) setContentsToImage", this, image);
+ if (image) {
+ m_haveContents = true;
+ m_contentLayer->setHaveContents(true);
+ m_contentLayer->setDrawsContent(true);
+ m_contentLayer->setHaveImage(true);
+ if (!m_haveImage) {
+ m_haveImage = true;
+ setNeedsDisplay();
+ askForSync();
+ }
+ } else
+ m_contentLayer->setHaveImage(false);
+}
+
+PlatformLayer* GraphicsLayerAndroid::platformLayer() const
+{
+ LOG("platformLayer");
+ return (PlatformLayer*) m_contentLayer.get();
+}
+
+#ifndef NDEBUG
+void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
+{
+}
+
+void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
+{
+}
+#endif
+
+void GraphicsLayerAndroid::setZPosition(float position)
+{
+ LOG("(%x) setZPosition: %.2f", this, position);
+ GraphicsLayer::setZPosition(position);
+ askForSync();
+}
+
+void GraphicsLayerAndroid::askForSync()
+{
+ if (m_client)
+ m_client->notifySyncRequired(this);
+}
+
+void GraphicsLayerAndroid::syncChildren()
+{
+ if (m_needsSyncChildren) {
+ m_contentLayer->removeAllChildren();
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ m_contentLayer->addChildren(
+ (static_cast<GraphicsLayerAndroid*>(m_children[i]))->contentLayer());
+ }
+ m_needsSyncChildren = false;
+ }
+}
+
+void GraphicsLayerAndroid::syncMask()
+{
+ if (m_needsSyncMask) {
+ if (m_maskLayer) {
+ GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_maskLayer);
+ LayerAndroid* mask = reinterpret_cast<LayerAndroid*>(layer->platformLayer());
+ m_contentLayer->setMaskLayer(mask);
+ } else
+ m_contentLayer->setMaskLayer(0);
+
+ m_contentLayer->setMasksToBounds(m_masksToBounds);
+ m_needsSyncMask = false;
+ }
+}
+
+void GraphicsLayerAndroid::syncPositionState()
+{
+ if (m_needsDisplay) {
+ m_translateX = m_currentTranslateX;
+ m_translateY = m_currentTranslateY;
+ m_position = m_currentPosition;
+ FloatPoint translation(m_currentTranslateX, m_currentTranslateY);
+ m_contentLayer->setTranslation(translation);
+ m_contentLayer->setPosition(m_currentPosition);
+ m_needsDisplay = false;
+ }
+}
+
+void GraphicsLayerAndroid::syncCompositingState()
+{
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
+ layer->syncCompositingState();
+ }
+
+ syncChildren();
+ syncMask();
+ syncPositionState();
+
+ if (!gPaused || WTF::currentTime() >= gPausedDelay)
+ repaintAll();
+}
+
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
new file mode 100644
index 0000000..fc88fbf
--- /dev/null
+++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GraphicsLayerAndroid_h
+#define GraphicsLayerAndroid_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatRect.h"
+#include "Frame.h"
+#include "GraphicsLayer.h"
+#include "GraphicsLayerClient.h"
+#include "LayerAndroid.h"
+#include "RefPtr.h"
+#include "Vector.h"
+
+class FloatPoint3D;
+class Image;
+
+namespace WebCore {
+
+class GraphicsLayerAndroid : public GraphicsLayer {
+public:
+
+ GraphicsLayerAndroid(GraphicsLayerClient*);
+ virtual ~GraphicsLayerAndroid();
+
+ virtual void setName(const String&);
+
+ // for hosting this GraphicsLayer in a native layer hierarchy
+ virtual NativeLayer nativeLayer() const;
+
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
+ virtual void addChild(GraphicsLayer*);
+ virtual void addChildAtIndex(GraphicsLayer*, int index);
+ virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild);
+
+ virtual void removeFromParent();
+
+ virtual void setPosition(const FloatPoint&);
+ virtual void setAnchorPoint(const FloatPoint3D&);
+ virtual void setSize(const FloatSize&);
+
+ virtual void setTransform(const TransformationMatrix&);
+
+ virtual void setChildrenTransform(const TransformationMatrix&);
+
+ virtual void setMaskLayer(GraphicsLayer*);
+ virtual void setMasksToBounds(bool);
+ virtual void setDrawsContent(bool);
+
+ virtual void setBackgroundColor(const Color&);
+ virtual void clearBackgroundColor();
+
+ virtual void setContentsOpaque(bool);
+
+ virtual void setOpacity(float);
+
+ virtual void setNeedsDisplay();
+ virtual void setNeedsDisplayInRect(const FloatRect&);
+
+ virtual bool addAnimation(const KeyframeValueList& valueList,
+ const IntSize& boxSize,
+ const Animation* anim,
+ const String& keyframesName,
+ double beginTime);
+ bool createTransformAnimationsFromKeyframes(const KeyframeValueList&,
+ const Animation*,
+ const String& keyframesName,
+ double beginTime,
+ const IntSize& boxSize);
+ bool createAnimationFromKeyframes(const KeyframeValueList&,
+ const Animation*,
+ const String& keyframesName,
+ double beginTime);
+
+ virtual void removeAnimationsForProperty(AnimatedPropertyID);
+ virtual void removeAnimationsForKeyframes(const String& keyframesName);
+ virtual void pauseAnimation(const String& keyframesName);
+
+ virtual void suspendAnimations(double time);
+ virtual void resumeAnimations();
+
+ virtual void setContentsToImage(Image*);
+ bool repaintAll();
+ virtual PlatformLayer* platformLayer() const;
+
+ void pauseDisplay(bool state);
+
+#ifndef NDEBUG
+ virtual void setDebugBackgroundColor(const Color&);
+ virtual void setDebugBorder(const Color&, float borderWidth);
+#endif
+
+ virtual void setZPosition(float);
+
+ void askForSync();
+ void syncPositionState();
+ void needsSyncChildren();
+ void syncChildren();
+ void syncMask();
+ virtual void syncCompositingState();
+ void setFrame(Frame*);
+
+ void sendImmediateRepaint();
+ LayerAndroid* contentLayer() { return m_contentLayer.get(); }
+
+ static int instancesCount();
+
+private:
+
+ bool repaint(const FloatRect& rect);
+
+ bool m_needsSyncChildren;
+ bool m_needsSyncMask;
+ bool m_needsRepaint;
+ bool m_needsDisplay;
+
+ bool m_haveContents;
+ bool m_haveImage;
+
+ float m_translateX;
+ float m_translateY;
+ float m_currentTranslateX;
+ float m_currentTranslateY;
+
+ FloatPoint m_currentPosition;
+
+ RefPtr<Frame> m_frame;
+
+ Vector<FloatRect> m_invalidatedRects;
+
+ RefPtr<LayerAndroid> m_contentLayer;
+};
+
+} // namespace WebCore
+
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // GraphicsLayerAndroid_h
diff --git a/WebCore/platform/graphics/android/ImageAndroid.cpp b/WebCore/platform/graphics/android/ImageAndroid.cpp
index 16a450f..486200d 100644
--- a/WebCore/platform/graphics/android/ImageAndroid.cpp
+++ b/WebCore/platform/graphics/android/ImageAndroid.cpp
@@ -5,23 +5,23 @@
* 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
+ * * 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
+ * * 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
+ * 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
+ * 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
@@ -186,7 +186,8 @@ static inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) {
}
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
- const FloatRect& srcRect, CompositeOperator compositeOp)
+ const FloatRect& srcRect, ColorSpace,
+ CompositeOperator compositeOp)
{
startAnimation();
@@ -224,7 +225,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
SkCanvas* canvas = ctxt->platformContext()->mCanvas;
SkPaint paint;
- ctxt->setupFillPaint(&paint); // need global alpha among other things
+ ctxt->setupBitmapPaint(&paint); // need global alpha among other things
paint.setFilterBitmap(true);
paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
fixPaintForBitmapsThatMaySeam(&paint);
@@ -249,8 +250,8 @@ void BitmapImage::setURL(const String& str)
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect,
const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator compositeOp,
- const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace,
+ CompositeOperator compositeOp, const FloatRect& destRect)
{
SkBitmapRef* image = this->nativeImageForCurrentFrame();
if (!image) { // If it's too early we won't have an image yet.
@@ -292,7 +293,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect,
SkCanvas* canvas = ctxt->platformContext()->mCanvas;
SkPaint paint;
- ctxt->setupFillPaint(&paint); // need global alpha among other things
+ ctxt->setupBitmapPaint(&paint); // need global alpha among other things
SkShader* shader = SkShader::CreateBitmapShader(bitmap,
SkShader::kRepeat_TileMode,
@@ -366,4 +367,3 @@ PassRefPtr<Image> Image::loadPlatformResource(const char *name)
}
} // namespace
-
diff --git a/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
index 89d841d..6efccfe 100644
--- a/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
+++ b/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
@@ -86,7 +86,7 @@ Image* ImageBuffer::image() const
return m_image.get();
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
GraphicsContext* gc = this->context();
if (!gc) {
@@ -149,7 +149,7 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
{
GraphicsContext* gc = this->context();
if (!gc) {
diff --git a/WebCore/platform/graphics/android/ImageBufferData.h b/WebCore/platform/graphics/android/ImageBufferData.h
index 7d8cd3b..269b365 100644
--- a/WebCore/platform/graphics/android/ImageBufferData.h
+++ b/WebCore/platform/graphics/android/ImageBufferData.h
@@ -13,7 +13,7 @@
* 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
+ * 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
diff --git a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
index 5c75a15..ba65e92 100644
--- a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
+++ b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
@@ -37,6 +37,12 @@
#include "SkStream.h"
#include "SkTemplates.h"
+// need a flag to tell us when we're on a large-ram device (e.g. >= 256M)
+// for now just use this hack
+#if 1
+ #define ON_LARGE_RAM_DEVICE
+#endif
+
#ifdef ANDROID_ANIMATED_GIF
#include "EmojiFont.h"
#include "gif/GIFImageDecoder.h"
@@ -44,15 +50,25 @@
using namespace android;
#endif
+// TODO: We should make use of some of the common code in platform/graphics/ImageSource.cpp.
+
SkPixelRef* SkCreateRLEPixelRef(const SkBitmap& src);
//#define TRACE_SUBSAMPLE_BITMAPS
//#define TRACE_RLE_BITMAPS
-// don't use RLE for images smaller than this, since they incur a drawing cost
-// (and don't work as patterns yet) we only want to use RLE when we must
-#define MIN_RLE_ALLOC_SIZE (2*1024*1024)
+#ifdef ON_LARGE_RAM_DEVICE
+ // don't use RLE for images smaller than this, since they incur a drawing cost
+ // (and don't work as patterns yet) we only want to use RLE when we must
+ #define MIN_RLE_ALLOC_SIZE (8*1024*1024)
+
+ // see dox for computeMaxBitmapSizeForCache()
+ #define MAX_SIZE_BEFORE_SUBSAMPLE (8*1024*1024)
+#else
+ #define MIN_RLE_ALLOC_SIZE (2*1024*1024)
+ #define MAX_SIZE_BEFORE_SUBSAMPLE (2*1024*1024)
+#endif
/* Images larger than this should be subsampled. Using ashmem, the decoded
pixels will be purged as needed, so this value can be pretty large. Making
@@ -65,7 +81,7 @@ SkPixelRef* SkCreateRLEPixelRef(const SkBitmap& src);
Perhaps this value should be some fraction of the available RAM...
*/
static size_t computeMaxBitmapSizeForCache() {
- return 2*1024*1024;
+ return MAX_SIZE_BEFORE_SUBSAMPLE;
}
/* 8bit images larger than this should be recompressed in RLE, to reduce
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp
new file mode 100644
index 0000000..3b5d5b5
--- /dev/null
+++ b/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -0,0 +1,383 @@
+#include "config.h"
+#include "LayerAndroid.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "AndroidAnimation.h"
+#include "CString.h"
+#include "GraphicsLayerAndroid.h"
+#include "PlatformGraphicsContext.h"
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
+#include "RenderView.h"
+#include "SkDevice.h"
+#include "SkDrawFilter.h"
+#include <wtf/CurrentTime.h>
+
+#define LAYER_DEBUG // Add diagonals for debugging
+#undef LAYER_DEBUG
+
+namespace WebCore {
+
+static int gDebugLayerAndroidInstances;
+inline int LayerAndroid::instancesCount()
+{
+ return gDebugLayerAndroidInstances;
+}
+
+class OpacityDrawFilter : public SkDrawFilter {
+ public:
+ OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
+ virtual bool filter(SkCanvas* canvas, SkPaint* paint, Type)
+ {
+ m_previousOpacity = paint->getAlpha();
+ paint->setAlpha(m_opacity);
+ return true;
+ }
+ virtual void restore(SkCanvas* canvas, SkPaint* paint, Type)
+ {
+ paint->setAlpha(m_previousOpacity);
+ }
+ private:
+ int m_opacity;
+ int m_previousOpacity;
+};
+
+PassRefPtr<LayerAndroid> LayerAndroid::create(bool isRootLayer)
+{
+ return adoptRef(new LayerAndroid(isRootLayer));
+}
+
+LayerAndroid::LayerAndroid(bool isRootLayer) :
+ m_doRotation(false),
+ m_isRootLayer(isRootLayer),
+ m_isFixed(false),
+ m_haveContents(false),
+ m_drawsContent(true),
+ m_haveImage(false),
+ m_haveClip(false),
+ m_backgroundColorSet(false),
+ m_angleTransform(0),
+ m_opacity(1),
+ m_size(0, 0),
+ m_position(0, 0),
+ m_translation(0, 0),
+ m_anchorPoint(0, 0, 0),
+ m_scale(1, 1, 1),
+ m_fixedLeft(Auto),
+ m_fixedTop(Auto),
+ m_fixedRight(Auto),
+ m_fixedBottom(Auto),
+ m_recordingPicture(0)
+{
+ gDebugLayerAndroidInstances++;
+}
+
+LayerAndroid::LayerAndroid(LayerAndroid* layer) :
+ m_doRotation(layer->m_doRotation),
+ m_isRootLayer(layer->m_isRootLayer),
+ m_isFixed(layer->m_isFixed),
+ m_haveContents(layer->m_haveContents),
+ m_drawsContent(layer->m_drawsContent),
+ m_haveImage(layer->m_haveImage),
+ m_haveClip(layer->m_haveClip),
+ m_backgroundColorSet(layer->m_backgroundColorSet),
+ m_angleTransform(layer->m_angleTransform),
+ m_opacity(layer->m_opacity),
+ m_size(layer->m_size),
+ m_position(layer->m_position),
+ m_translation(layer->m_translation),
+ m_anchorPoint(layer->m_anchorPoint),
+ m_scale(layer->m_scale),
+ m_fixedLeft(layer->m_fixedLeft),
+ m_fixedRight(layer->m_fixedRight),
+ m_fixedTop(layer->m_fixedTop),
+ m_fixedBottom(layer->m_fixedBottom)
+{
+ if (layer->m_recordingPicture) {
+ layer->m_recordingPicture->ref();
+ m_recordingPicture = layer->m_recordingPicture;
+ } else
+ m_recordingPicture = 0;
+
+ for (unsigned int i = 0; i < layer->m_children.size(); i++)
+ m_children.append(adoptRef(new LayerAndroid(layer->m_children[i].get())));
+
+ KeyframesMap::const_iterator end = layer->m_animations.end();
+ for (KeyframesMap::const_iterator it = layer->m_animations.begin(); it != end; ++it)
+ m_animations.add((it->second)->name(), adoptRef((it->second)->copy()));
+
+ end = m_animations.end();
+ for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it)
+ (it->second)->setLayer(this);
+
+ gDebugLayerAndroidInstances++;
+}
+
+LayerAndroid::~LayerAndroid()
+{
+ m_recordingPicture->safeUnref();
+ m_children.clear();
+ m_animations.clear();
+ gDebugLayerAndroidInstances--;
+}
+
+static int gDebugNbAnims = 0;
+
+Vector<RefPtr<AndroidAnimationValue> >* LayerAndroid::evaluateAnimations() const
+{
+ double time = WTF::currentTime();
+ Vector<RefPtr<AndroidAnimationValue> >* result = new Vector<RefPtr<AndroidAnimationValue> >();
+ gDebugNbAnims = 0;
+ if (evaluateAnimations(time, result))
+ return result;
+ return 0;
+}
+
+bool LayerAndroid::hasAnimations() const
+{
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ if (m_children[i]->hasAnimations())
+ return true;
+ }
+ return !!m_animations.size();
+}
+
+bool LayerAndroid::evaluateAnimations(double time,
+ Vector<RefPtr<AndroidAnimationValue> >* result) const
+{
+ bool hasRunningAnimations = false;
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ if (m_children[i]->evaluateAnimations(time, result))
+ hasRunningAnimations = true;
+ }
+ KeyframesMap::const_iterator end = m_animations.end();
+ for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
+ gDebugNbAnims++;
+ if ((it->second)->evaluate(time)) {
+ result->append((it->second)->result());
+ hasRunningAnimations = true;
+ }
+ }
+
+ return hasRunningAnimations;
+}
+
+void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> anim)
+{
+ m_animations.add(anim->name(), anim);
+}
+
+void LayerAndroid::removeAnimation(const String& name)
+{
+ m_animations.remove(name);
+}
+
+void LayerAndroid::setFixedPosition(Length left, Length top,
+ Length right, Length bottom)
+{
+ m_fixedLeft = left;
+ m_fixedTop = top;
+ m_fixedRight = right;
+ m_fixedBottom = bottom;
+ m_isFixed = true;
+}
+
+void LayerAndroid::setDrawsContent(bool drawsContent)
+{
+ m_drawsContent = drawsContent;
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ LayerAndroid* layer = m_children[i].get();
+ layer->setDrawsContent(drawsContent);
+ }
+}
+
+// We only use the bounding rect of the layer as mask...
+// TODO: use a real mask?
+void LayerAndroid::setMaskLayer(LayerAndroid* layer)
+{
+ if (layer)
+ m_haveClip = true;
+}
+
+void LayerAndroid::setMasksToBounds(bool masksToBounds)
+{
+ m_haveClip = masksToBounds;
+}
+
+void LayerAndroid::setBackgroundColor(const Color& color)
+{
+ m_backgroundColor = color;
+ m_backgroundColorSet = true;
+ setHaveContents(true);
+ setDrawsContent(true);
+}
+
+static int gDebugChildLevel;
+
+void LayerAndroid::paintOn(int scrollX, int scrollY,
+ int width, int height,
+ float scale, SkCanvas* canvas)
+{
+ gDebugChildLevel = 0;
+ paintChildren(scrollX, scrollY, width, height, scale, canvas, 1);
+}
+
+void LayerAndroid::setClip(SkCanvas* canvas)
+{
+ SkRect clip;
+ clip.fLeft = m_position.x() + m_translation.x();
+ clip.fTop = m_position.y() + m_translation.y();
+ clip.fRight = clip.fLeft + m_size.width();
+ clip.fBottom = clip.fTop + m_size.height();
+ canvas->clipRect(clip);
+}
+
+void LayerAndroid::paintChildren(int scrollX, int scrollY,
+ int width, int height,
+ float scale, SkCanvas* canvas,
+ float opacity)
+{
+ canvas->save();
+
+ if (m_haveClip)
+ setClip(canvas);
+
+ paintMe(scrollX, scrollY, width, height, scale, canvas, opacity);
+ canvas->translate(m_position.x() + m_translation.x(),
+ m_position.y() + m_translation.y());
+
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ LayerAndroid* layer = m_children[i].get();
+ if (layer) {
+ gDebugChildLevel++;
+ layer->paintChildren(scrollX, scrollY, width, height, scale,
+ canvas, opacity * m_opacity);
+ gDebugChildLevel--;
+ }
+ }
+
+ canvas->restore();
+}
+
+void LayerAndroid::paintMe(int scrollX,
+ int scrollY,
+ int viewWidth,
+ int viewHeight,
+ float scale,
+ SkCanvas* canvas,
+ float opacity)
+{
+ if (!prepareContext())
+ return;
+
+ if (!m_haveImage && !m_drawsContent && !m_isRootLayer)
+ return;
+
+ SkAutoCanvasRestore restore(canvas, true);
+
+ int canvasOpacity = opacity * m_opacity * 255;
+ if (canvasOpacity != 255)
+ canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
+
+ SkPaint paintMode;
+ if (m_backgroundColorSet) {
+ paintMode.setARGB(m_backgroundColor.alpha(),
+ m_backgroundColor.red(),
+ m_backgroundColor.green(),
+ m_backgroundColor.blue());
+ } else
+ paintMode.setARGB(0, 0, 0, 0);
+
+ paintMode.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ float x = 0;
+ float y = 0;
+ if (m_isFixed) {
+ float w = viewWidth / scale;
+ float h = viewHeight / scale;
+ float dx = scrollX / scale;
+ float dy = scrollY / scale;
+
+ if (m_fixedLeft.type())
+ x = dx + m_fixedLeft.calcFloatValue(w);
+ else if (m_fixedRight.type())
+ x = dx + w - m_fixedRight.calcFloatValue(w) - m_size.width();
+
+ if (m_fixedTop.type())
+ y = dy + m_fixedTop.calcFloatValue(h);
+ else if (m_fixedBottom.type())
+ y = dy + h - m_fixedBottom.calcFloatValue(h) - m_size.height();
+
+ } else {
+ x = m_translation.x() + m_position.x();
+ y = m_translation.y() + m_position.y();
+ }
+
+ canvas->translate(x, y);
+
+ if (m_doRotation) {
+ float anchorX = m_anchorPoint.x() * m_size.width();
+ float anchorY = m_anchorPoint.y() * m_size.height();
+ canvas->translate(anchorX, anchorY);
+ canvas->rotate(m_angleTransform);
+ canvas->translate(-anchorX, -anchorY);
+ }
+
+ float sx = m_scale.x();
+ float sy = m_scale.y();
+ if (sx > 1.0f || sy > 1.0f) {
+ float dx = (sx * m_size.width()) - m_size.width();
+ float dy = (sy * m_size.height()) - m_size.height();
+ canvas->translate(-dx / 2.0f, -dy / 2.0f);
+ canvas->scale(sx, sy);
+ }
+
+ m_recordingPicture->draw(canvas);
+
+#ifdef LAYER_DEBUG
+ float w = m_size.width();
+ float h = m_size.height();
+ SkPaint paint;
+ paint.setARGB(128, 255, 0, 0);
+ canvas->drawLine(0, 0, w, h, paint);
+ canvas->drawLine(0, h, w, 0, paint);
+ paint.setARGB(128, 0, 255, 0);
+ canvas->drawLine(0, 0, 0, h, paint);
+ canvas->drawLine(0, h, w, h, paint);
+ canvas->drawLine(w, h, w, 0, paint);
+ canvas->drawLine(w, 0, 0, 0, paint);
+#endif
+}
+
+SkPicture* LayerAndroid::recordContext()
+{
+ if (prepareContext(true))
+ return m_recordingPicture;
+ return 0;
+}
+
+bool LayerAndroid::prepareContext(bool force)
+{
+ if (!m_haveContents)
+ return false;
+
+ if (!m_isRootLayer) {
+ if (force || !m_recordingPicture
+ || (m_recordingPicture
+ && ((m_recordingPicture->width() != (int) m_size.width())
+ || (m_recordingPicture->height() != (int) m_size.height())))) {
+ m_recordingPicture->safeUnref();
+ m_recordingPicture = new SkPicture();
+ }
+ } else if (m_recordingPicture) {
+ m_recordingPicture->safeUnref();
+ m_recordingPicture = 0;
+ }
+
+ return m_recordingPicture;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h
new file mode 100644
index 0000000..467c7dd
--- /dev/null
+++ b/WebCore/platform/graphics/android/LayerAndroid.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LayerAndroid_h
+#define LayerAndroid_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "Color.h"
+#include "FloatPoint.h"
+#include "FloatPoint3D.h"
+#include "FloatSize.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "Length.h"
+#include "RefPtr.h"
+#include "StringHash.h"
+#include "Vector.h"
+#include <wtf/HashSet.h>
+
+class SkCanvas;
+class SkPicture;
+class SkRect;
+
+namespace WebCore {
+
+class AndroidAnimation;
+class AndroidAnimationValue;
+
+class LayerAndroid : public RefCounted<LayerAndroid> {
+
+public:
+ static PassRefPtr<LayerAndroid> create(bool isRootLayer);
+ LayerAndroid(bool isRootLayer);
+ LayerAndroid(LayerAndroid* layer);
+ ~LayerAndroid();
+
+ static int instancesCount();
+
+ void setSize(FloatSize size) { m_size = size; }
+ void setOpacity(float opacity) { m_opacity = opacity; }
+ void setTranslation(FloatPoint translation) { m_translation = translation; }
+ void setRotation(float a) { m_angleTransform = a; m_doRotation = true; }
+ void setScale(FloatPoint3D scale) { m_scale = scale; }
+ void setPosition(FloatPoint position) { m_position = position; }
+ void setAnchorPoint(FloatPoint3D point) { m_anchorPoint = point; }
+ void setHaveContents(bool haveContents) { m_haveContents = haveContents; }
+ void setHaveImage(bool haveImage) { m_haveImage = haveImage; }
+ void setDrawsContent(bool drawsContent);
+ void setMaskLayer(LayerAndroid*);
+ void setMasksToBounds(bool);
+ void setBackgroundColor(const Color& color);
+ void setIsRootLayer(bool isRootLayer) { m_isRootLayer = isRootLayer; }
+
+ void paintOn(int scrollX, int scrollY, int width, int height, float scale, SkCanvas*);
+ GraphicsContext* paintContext();
+ void removeAllChildren() { m_children.clear(); }
+ void addChildren(LayerAndroid* layer) { m_children.append(layer); }
+ bool prepareContext(bool force = false);
+ void startRecording();
+ void stopRecording();
+ SkPicture* recordContext();
+ void setClip(SkCanvas* clip);
+ FloatPoint position() { return m_position; }
+ FloatPoint translation() { return m_translation; }
+ FloatSize size() { return m_size; }
+
+ void setFixedPosition(Length left, Length top, Length right, Length bottom);
+ void addAnimation(PassRefPtr<AndroidAnimation> anim);
+ void removeAnimation(const String& name);
+ Vector<RefPtr<AndroidAnimationValue> >* evaluateAnimations() const;
+ bool evaluateAnimations(double time,
+ Vector<RefPtr<AndroidAnimationValue> >* result) const;
+ bool hasAnimations() const;
+
+private:
+
+ void paintChildren(int scrollX, int scrollY,
+ int width, int height,
+ float scale, SkCanvas* canvas,
+ float opacity);
+
+ void paintMe(int scrollX, int scrollY,
+ int width, int height,
+ float scale, SkCanvas* canvas,
+ float opacity);
+
+ bool m_doRotation;
+ bool m_isRootLayer;
+ bool m_isFixed;
+ bool m_haveContents;
+ bool m_drawsContent;
+ bool m_haveImage;
+ bool m_haveClip;
+ bool m_backgroundColorSet;
+
+ float m_angleTransform;
+ float m_opacity;
+
+ FloatSize m_size;
+ FloatPoint m_position;
+ FloatPoint m_translation;
+ FloatPoint3D m_anchorPoint;
+ FloatPoint3D m_scale;
+
+ Length m_fixedLeft;
+ Length m_fixedTop;
+ Length m_fixedRight;
+ Length m_fixedBottom;
+
+ SkPicture* m_recordingPicture;
+ Color m_backgroundColor;
+
+ Vector<RefPtr<LayerAndroid> > m_children;
+ typedef HashMap<String, RefPtr<AndroidAnimation> > KeyframesMap;
+ KeyframesMap m_animations;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // LayerAndroid_h
diff --git a/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h b/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h
index 812a337..19bfcd1 100644
--- a/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h
+++ b/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h
@@ -13,7 +13,7 @@
* 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
+ * 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
@@ -48,6 +48,7 @@ public:
virtual IntSize naturalSize() const;
+ virtual bool hasAudio() const;
virtual bool hasVideo() const;
virtual void setVisible(bool);
@@ -69,7 +70,7 @@ public:
virtual MediaPlayer::ReadyState readyState() const;
virtual float maxTimeSeekable() const;
- virtual float maxTimeBuffered() const;
+ virtual PassRefPtr<TimeRanges> buffered() const;
virtual int dataRate() const;
@@ -88,6 +89,7 @@ public:
void onPrepared(int duration, int width, int height);
void onEnded();
void onPosterFetched(SkBitmap*);
+ void onTimeupdate(int position);
private:
// Android-specific methods and fields.
static MediaPlayerPrivateInterface* create(MediaPlayer* player);
@@ -106,6 +108,7 @@ private:
float m_currentTime;
bool m_paused;
+ bool m_hasVideo;
MediaPlayer::ReadyState m_readyState;
MediaPlayer::NetworkState m_networkState;
diff --git a/WebCore/platform/graphics/android/PathAndroid.cpp b/WebCore/platform/graphics/android/PathAndroid.cpp
index 90cd2db..4fdda23 100644
--- a/WebCore/platform/graphics/android/PathAndroid.cpp
+++ b/WebCore/platform/graphics/android/PathAndroid.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
diff --git a/WebCore/platform/graphics/android/PatternAndroid.cpp b/WebCore/platform/graphics/android/PatternAndroid.cpp
index a787113..58709fc 100644
--- a/WebCore/platform/graphics/android/PatternAndroid.cpp
+++ b/WebCore/platform/graphics/android/PatternAndroid.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
diff --git a/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp b/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp
index e0aecfa..fcdcce9 100644
--- a/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp
+++ b/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
diff --git a/WebCore/platform/graphics/android/PlatformGraphicsContext.h b/WebCore/platform/graphics/android/PlatformGraphicsContext.h
index 4eeb4c1..8d0df36 100644
--- a/WebCore/platform/graphics/android/PlatformGraphicsContext.h
+++ b/WebCore/platform/graphics/android/PlatformGraphicsContext.h
@@ -13,7 +13,7 @@
* 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
+ * 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
@@ -162,4 +162,3 @@ private:
}
#endif
-
diff --git a/WebCore/platform/graphics/android/SharedBufferStream.cpp b/WebCore/platform/graphics/android/SharedBufferStream.cpp
index fd63423..952495b 100644
--- a/WebCore/platform/graphics/android/SharedBufferStream.cpp
+++ b/WebCore/platform/graphics/android/SharedBufferStream.cpp
@@ -1,17 +1,26 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright 2009, The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * 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.
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * 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 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"
@@ -42,4 +51,3 @@ namespace WebCore {
}
}
-
diff --git a/WebCore/platform/graphics/android/SharedBufferStream.h b/WebCore/platform/graphics/android/SharedBufferStream.h
index 929aa9b..da59b69 100644
--- a/WebCore/platform/graphics/android/SharedBufferStream.h
+++ b/WebCore/platform/graphics/android/SharedBufferStream.h
@@ -1,17 +1,26 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright 2009, The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * 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.
*
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * 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 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 WebCore_SharedBufferStream_DEFINED
diff --git a/WebCore/platform/graphics/android/SkBitmapRef.h b/WebCore/platform/graphics/android/SkBitmapRef.h
index 094102b..2a6e59e 100644
--- a/WebCore/platform/graphics/android/SkBitmapRef.h
+++ b/WebCore/platform/graphics/android/SkBitmapRef.h
@@ -13,7 +13,7 @@
* 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
+ * 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
diff --git a/WebCore/platform/graphics/android/android_graphics.cpp b/WebCore/platform/graphics/android/android_graphics.cpp
index cdd8afe..af88b8c 100644
--- a/WebCore/platform/graphics/android/android_graphics.cpp
+++ b/WebCore/platform/graphics/android/android_graphics.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
@@ -88,5 +88,3 @@ void CursorRing::DrawRing(SkCanvas* canvas,
paint.setColor(cursorInnerColors[flavor]);
canvas->drawPath(path, paint);
}
-
-
diff --git a/WebCore/platform/graphics/android/android_graphics.h b/WebCore/platform/graphics/android/android_graphics.h
index 348daf1..a286e3a 100644
--- a/WebCore/platform/graphics/android/android_graphics.h
+++ b/WebCore/platform/graphics/android/android_graphics.h
@@ -13,7 +13,7 @@
* 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
+ * 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
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp
index 0f7ae79..3bfa8f3 100644
--- a/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -32,6 +32,7 @@
#include "GlyphBuffer.h"
#include "Gradient.h"
#include "GraphicsContext.h"
+#include "ImageBuffer.h"
#include "Pattern.h"
#include "SimpleFontData.h"
#include "TransformationMatrix.h"
@@ -46,7 +47,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_t* cr = context->platformContext();
cairo_save(cr);
- font->setFont(cr);
+ cairo_set_scaled_font(cr, font->platformData().scaledFont());
GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from);
@@ -85,6 +86,34 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
shadowFillColor.getRGBA(red, green, blue, alpha);
cairo_set_source_rgba(cr, red, green, blue, alpha);
+#if ENABLE(FILTERS)
+ cairo_text_extents_t extents;
+ cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
+
+ FloatRect rect(FloatPoint(), FloatSize(extents.width, extents.height));
+ IntSize shadowBufferSize;
+ FloatRect shadowRect;
+ float kernelSize = 0.f;
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur);
+
+ // Draw shadow into a new ImageBuffer
+ OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+ GraphicsContext* shadowContext = shadowBuffer->context();
+ cairo_t* shadowCr = shadowContext->platformContext();
+
+ cairo_translate(shadowCr, kernelSize, extents.height + kernelSize);
+
+ cairo_set_scaled_font(shadowCr, font->platformData().scaledFont());
+ cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
+ if (font->syntheticBoldOffset()) {
+ cairo_save(shadowCr);
+ cairo_translate(shadowCr, font->syntheticBoldOffset(), 0);
+ cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
+ cairo_restore(shadowCr);
+ }
+ cairo_translate(cr, 0.0, -extents.height);
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+#else
cairo_translate(cr, shadowSize.width(), shadowSize.height());
cairo_show_glyphs(cr, glyphs, numGlyphs);
if (font->syntheticBoldOffset()) {
@@ -93,6 +122,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_show_glyphs(cr, glyphs, numGlyphs);
cairo_restore(cr);
}
+#endif
cairo_restore(cr);
}
@@ -156,7 +186,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
// Re-enable the platform shadow we disabled earlier
if (hasShadow)
- context->setShadow(shadowSize, shadowBlur, shadowColor);
+ context->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace);
cairo_restore(cr);
}
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 5765546..14034fd 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -1,8 +1,9 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
- * Copyright (C) 2008 Dirk Schulze <vbs85@gmx.de>
+ * Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2008 Nuanti Ltd.
+ * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,16 +32,19 @@
#if PLATFORM(CAIRO)
-#include "TransformationMatrix.h"
#include "CairoPath.h"
+#include "FEGaussianBlur.h"
#include "FloatRect.h"
#include "Font.h"
#include "ImageBuffer.h"
+#include "ImageBufferFilter.h"
#include "IntRect.h"
#include "NotImplemented.h"
#include "Path.h"
#include "Pattern.h"
#include "SimpleFontData.h"
+#include "SourceGraphic.h"
+#include "TransformationMatrix.h"
#include <cairo.h>
#include <math.h>
@@ -53,8 +57,8 @@
#elif PLATFORM(WIN)
#include <cairo-win32.h>
#endif
-#include "GraphicsContextPrivate.h"
#include "GraphicsContextPlatformPrivateCairo.h"
+#include "GraphicsContextPrivate.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
@@ -69,6 +73,42 @@ static inline void setColor(cairo_t* cr, const Color& col)
cairo_set_source_rgba(cr, red, green, blue, alpha);
}
+static inline void setPlatformFill(GraphicsContext* context, cairo_t* cr, GraphicsContextPrivate* gcp)
+{
+ cairo_save(cr);
+ if (gcp->state.fillPattern) {
+ TransformationMatrix affine;
+ cairo_set_source(cr, gcp->state.fillPattern->createPlatformPattern(affine));
+ } else if (gcp->state.fillGradient)
+ cairo_set_source(cr, gcp->state.fillGradient->platformGradient());
+ else
+ setColor(cr, context->fillColor());
+ cairo_clip_preserve(cr);
+ cairo_paint_with_alpha(cr, gcp->state.globalAlpha);
+ cairo_restore(cr);
+}
+
+static inline void setPlatformStroke(GraphicsContext* context, cairo_t* cr, GraphicsContextPrivate* gcp)
+{
+ cairo_save(cr);
+ if (gcp->state.strokePattern) {
+ TransformationMatrix affine;
+ cairo_set_source(cr, gcp->state.strokePattern->createPlatformPattern(affine));
+ } else if (gcp->state.strokeGradient)
+ cairo_set_source(cr, gcp->state.strokeGradient->platformGradient());
+ else {
+ Color strokeColor = colorWithOverrideAlpha(context->strokeColor().rgb(), context->strokeColor().alpha() / 255.f * gcp->state.globalAlpha);
+ setColor(cr, strokeColor);
+ }
+ if (gcp->state.globalAlpha < 1.0f && (gcp->state.strokePattern || gcp->state.strokeGradient)) {
+ cairo_push_group(cr);
+ cairo_paint_with_alpha(cr, gcp->state.globalAlpha);
+ cairo_pop_group_to_source(cr);
+ }
+ cairo_stroke_preserve(cr);
+ cairo_restore(cr);
+}
+
// A fillRect helper
static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const Color& col)
{
@@ -78,6 +118,81 @@ static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const
cairo_fill(cr);
}
+static inline void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr)
+{
+ cairo_set_antialias(dstCr, cairo_get_antialias(srcCr));
+
+ size_t dashCount = cairo_get_dash_count(srcCr);
+ Vector<double> dashes(dashCount);
+
+ double offset;
+ cairo_get_dash(srcCr, dashes.data(), &offset);
+ cairo_set_dash(dstCr, dashes.data(), dashCount, offset);
+ cairo_set_line_cap(dstCr, cairo_get_line_cap(srcCr));
+ cairo_set_line_join(dstCr, cairo_get_line_join(srcCr));
+ cairo_set_line_width(dstCr, cairo_get_line_width(srcCr));
+ cairo_set_miter_limit(dstCr, cairo_get_miter_limit(srcCr));
+ cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr));
+}
+
+void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, int shadowBlur)
+{
+#if ENABLE(FILTERS)
+ // calculate the kernel size according to the HTML5 canvas shadow specification
+ kernelSize = (shadowBlur < 8 ? shadowBlur / 2.f : sqrt(shadowBlur * 2.f));
+ int blurRadius = ceil(kernelSize);
+
+ shadowBufferSize = IntSize(sourceRect.width() + blurRadius * 2, sourceRect.height() + blurRadius * 2);
+
+ // determine dimensions of shadow rect
+ shadowRect = FloatRect(sourceRect.location(), shadowBufferSize);
+ shadowRect.move(shadowSize.width() - kernelSize, shadowSize.height() - kernelSize);
+#endif
+}
+
+static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* gcp, bool fillShadow, bool strokeShadow)
+{
+#if ENABLE(FILTERS)
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (!context->getShadow(shadowSize, shadowBlur, shadowColor))
+ return;
+
+ // Calculate filter values to create appropriate shadow.
+ cairo_t* cr = context->platformContext();
+ cairo_path_t* path = cairo_copy_path(cr);
+ double x0, x1, y0, y1;
+ if (strokeShadow)
+ cairo_stroke_extents(cr, &x0, &y0, &x1, &y1);
+ else
+ cairo_fill_extents(cr, &x0, &y0, &x1, &y1);
+ FloatRect rect(x0, y0, x1 - x0, y1 - y0);
+
+ IntSize shadowBufferSize;
+ FloatRect shadowRect;
+ float kernelSize = 0;
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur);
+
+ // Create suitably-sized ImageBuffer to hold the shadow.
+ OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+
+ // Draw shadow into a new ImageBuffer.
+ cairo_t* shadowContext = shadowBuffer->context()->platformContext();
+ copyContextProperties(cr, shadowContext);
+ cairo_translate(shadowContext, -rect.x() + kernelSize, -rect.y() + kernelSize);
+ cairo_new_path(shadowContext);
+ cairo_append_path(shadowContext, path);
+
+ if (fillShadow)
+ setPlatformFill(context, shadowContext, gcp);
+ if (strokeShadow)
+ setPlatformStroke(context, shadowContext, gcp);
+
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+#endif
+}
+
GraphicsContext::GraphicsContext(PlatformGraphicsContext* cr)
: m_common(createGraphicsContextPrivate())
, m_data(new GraphicsContextPlatformPrivate)
@@ -142,38 +257,6 @@ void GraphicsContext::drawRect(const IntRect& rect)
cairo_restore(cr);
}
-// FIXME: Now that this is refactored, it should be shared by all contexts.
-static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle style)
-{
- // 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.
- if (style == DottedStroke || style == DashedStroke) {
- if (p1.x() == p2.x()) {
- p1.setY(p1.y() + strokeWidth);
- p2.setY(p2.y() - strokeWidth);
- }
- else {
- p1.setX(p1.x() + strokeWidth);
- p2.setX(p2.x() - strokeWidth);
- }
- }
-
- if (static_cast<int>(strokeWidth) % 2) {
- if (p1.x() == p2.x()) {
- // We're a vertical line. Adjust our x.
- p1.setX(p1.x() + 0.5);
- p2.setX(p2.x() + 0.5);
- }
- else {
- // We're a horizontal line. Adjust our y.
- p1.setY(p1.y() + 0.5);
- p2.setY(p2.y() + 0.5);
- }
- }
-}
-
// This is only used to draw borders.
void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
{
@@ -239,20 +322,18 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth == 1)
patternOffset = 1.0;
else {
- bool evenNumberOfSegments = numSegments%2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
if (remainder) {
patternOffset += patWidth - remainder;
- patternOffset += remainder/2;
- }
- else
- patternOffset = patWidth/2;
- }
- else if (!evenNumberOfSegments) {
+ patternOffset += remainder / 2;
+ } else
+ patternOffset = patWidth / 2;
+ } else if (!evenNumberOfSegments) {
if (remainder)
- patternOffset = (patWidth - remainder)/2;
+ patternOffset = (patWidth - remainder) / 2;
}
}
@@ -318,7 +399,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (w != h)
cairo_scale(cr, 1., scaleFactor);
-
+
cairo_arc_negative(cr, x + hRadius, (y + vRadius) * reverseScaleFactor, hRadius, -fa * M_PI/180, -falen * M_PI/180);
if (w != h)
@@ -326,16 +407,16 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
float width = strokeThickness();
int patWidth = 0;
-
+
switch (strokeStyle()) {
- case DottedStroke:
- patWidth = static_cast<int>(width / 2);
- break;
- case DashedStroke:
- patWidth = 3 * static_cast<int>(width / 2);
- break;
- default:
- break;
+ case DottedStroke:
+ patWidth = static_cast<int>(width / 2);
+ break;
+ case DashedStroke:
+ patWidth = 3 * static_cast<int>(width / 2);
+ break;
+ default:
+ break;
}
setColor(cr, strokeColor());
@@ -349,7 +430,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
distance = static_cast<int>((M_PI * hRadius) / 2.0);
else // We are elliptical and will have to estimate the distance
distance = static_cast<int>((M_PI * sqrtf((hRadius * hRadius + vRadius * vRadius) / 2.0)) / 2.0);
-
+
int remainder = distance % patWidth;
int coverage = distance - remainder;
int numSegments = coverage / patWidth;
@@ -359,7 +440,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (patWidth == 1)
patternOffset = 1.0;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -421,30 +502,12 @@ void GraphicsContext::fillPath()
return;
cairo_t* cr = m_data->cr;
- cairo_save(cr);
cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- setColor(cr, fillColor());
- cairo_clip(cr);
- cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
- break;
- 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->platformGradient();
- cairo_set_source(cr, pattern);
- cairo_clip(cr);
- cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
- break;
- }
- cairo_restore(cr);
+ drawPathShadow(this, m_common, true, false);
+
+ setPlatformFill(this, cr, m_common);
+ cairo_new_path(cr);
}
void GraphicsContext::strokePath()
@@ -453,45 +516,26 @@ void GraphicsContext::strokePath()
return;
cairo_t* cr = m_data->cr;
- cairo_save(cr);
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- 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: {
- 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);
- cairo_pop_group_to_source(cr);
- }
- cairo_stroke(cr);
- break;
- }
- case GradientColorSpace:
- cairo_pattern_t* pattern = m_common->state.strokeGradient->platformGradient();
- cairo_set_source(cr, pattern);
- 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);
- break;
- }
- cairo_restore(cr);
+ drawPathShadow(this, m_common, false, true);
+
+ setPlatformStroke(this, cr, m_common);
+ cairo_new_path(cr);
+
}
void GraphicsContext::drawPath()
{
- fillPath();
- strokePath();
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+
+ cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
+ drawPathShadow(this, m_common, true, true);
+
+ setPlatformFill(this, cr, m_common);
+ setPlatformStroke(this, cr, m_common);
+ cairo_new_path(cr);
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -504,11 +548,36 @@ void GraphicsContext::fillRect(const FloatRect& rect)
fillPath();
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor)
+{
+#if ENABLE(FILTERS)
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+
+ if (!context->getShadow(shadowSize, shadowBlur, shadowColor))
+ return;
+
+ IntSize shadowBufferSize;
+ FloatRect shadowRect;
+ float kernelSize = 0;
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur);
+
+ // Draw shadow into a new ImageBuffer
+ OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+ GraphicsContext* shadowContext = shadowBuffer->context();
+ shadowContext->fillRect(FloatRect(FloatPoint(kernelSize, kernelSize), rect.size()), rectColor, DeviceColorSpace);
+
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+#endif
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
+ drawBorderlessRectShadow(this, rect, color);
if (color.alpha())
fillRectSourceOver(m_data->cr, rect, color);
}
@@ -668,13 +737,13 @@ IntPoint GraphicsContext::origin()
return IntPoint(static_cast<int>(matrix.x0), static_cast<int>(matrix.y0));
}
-void GraphicsContext::setPlatformFillColor(const Color& col)
+void GraphicsContext::setPlatformFillColor(const Color& col, ColorSpace colorSpace)
{
// Cairo contexts can't hold separate fill and stroke colors
// so we set them just before we actually fill or stroke
}
-void GraphicsContext::setPlatformStrokeColor(const Color& col)
+void GraphicsContext::setPlatformStrokeColor(const Color& col, ColorSpace colorSpace)
{
// Cairo contexts can't hold separate fill and stroke colors
// so we set them just before we actually fill or stroke
@@ -760,9 +829,48 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer
notImplemented();
}
-void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&)
+void GraphicsContext::setPlatformShadow(IntSize const& size, int, Color const&, ColorSpace)
{
- notImplemented();
+ // Cairo doesn't support shadows natively, they are drawn manually in the draw*
+ // functions
+
+ if (m_common->state.shadowsIgnoreTransforms) {
+ // Meaning that this graphics context is associated with a CanvasRenderingContext
+ // We flip the height since CG and HTML5 Canvas have opposite Y axis
+ m_common->state.shadowSize = IntSize(size.width(), -size.height());
+ }
+}
+
+void GraphicsContext::createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float kernelSize)
+{
+#if ENABLE(FILTERS)
+ cairo_t* cr = m_data->cr;
+
+ // draw the shadow without blurring, if kernelSize is zero
+ if (!kernelSize) {
+ setColor(cr, shadowColor);
+ cairo_mask_surface(cr, buffer->image()->nativeImageForCurrentFrame(), shadowRect.x(), shadowRect.y());
+ return;
+ }
+
+ // limit kernel size to 1000, this is what CG is doing.
+ kernelSize = std::min(1000.f, kernelSize);
+
+ // create filter
+ RefPtr<Filter> filter = ImageBufferFilter::create();
+ filter->setSourceImage(buffer.release());
+ RefPtr<FilterEffect> source = SourceGraphic::create();
+ source->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
+ source->setIsAlphaImage(true);
+ RefPtr<FilterEffect> blur = FEGaussianBlur::create(source.get(), kernelSize, kernelSize);
+ blur->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
+ blur->apply(filter.get());
+
+ // Mask the filter with the shadow color and draw it to the context.
+ // Masking makes it possible to just blur the alpha channel.
+ setColor(cr, shadowColor);
+ cairo_mask_surface(cr, blur->resultImage()->image()->nativeImageForCurrentFrame(), shadowRect.x(), shadowRect.y());
+#endif
}
void GraphicsContext::clearPlatformShadow()
@@ -828,15 +936,15 @@ void GraphicsContext::setLineCap(LineCap lineCap)
cairo_line_cap_t cairoCap = CAIRO_LINE_CAP_BUTT;
switch (lineCap) {
- case ButtCap:
- // no-op
- break;
- case RoundCap:
- cairoCap = CAIRO_LINE_CAP_ROUND;
- break;
- case SquareCap:
- cairoCap = CAIRO_LINE_CAP_SQUARE;
- break;
+ case ButtCap:
+ // no-op
+ break;
+ case RoundCap:
+ cairoCap = CAIRO_LINE_CAP_ROUND;
+ break;
+ case SquareCap:
+ cairoCap = CAIRO_LINE_CAP_SQUARE;
+ break;
}
cairo_set_line_cap(m_data->cr, cairoCap);
}
@@ -853,15 +961,15 @@ void GraphicsContext::setLineJoin(LineJoin lineJoin)
cairo_line_join_t cairoJoin = CAIRO_LINE_JOIN_MITER;
switch (lineJoin) {
- case MiterJoin:
- // no-op
- break;
- case RoundJoin:
- cairoJoin = CAIRO_LINE_JOIN_ROUND;
- break;
- case BevelJoin:
- cairoJoin = CAIRO_LINE_JOIN_BEVEL;
- break;
+ case MiterJoin:
+ // no-op
+ break;
+ case RoundJoin:
+ cairoJoin = CAIRO_LINE_JOIN_ROUND;
+ break;
+ case BevelJoin:
+ cairoJoin = CAIRO_LINE_JOIN_BEVEL;
+ break;
}
cairo_set_line_join(m_data->cr, cairoJoin);
}
@@ -887,37 +995,37 @@ float GraphicsContext::getAlpha()
static inline cairo_operator_t toCairoOperator(CompositeOperator op)
{
switch (op) {
- case CompositeClear:
- return CAIRO_OPERATOR_CLEAR;
- case CompositeCopy:
- return CAIRO_OPERATOR_SOURCE;
- case CompositeSourceOver:
- return CAIRO_OPERATOR_OVER;
- case CompositeSourceIn:
- return CAIRO_OPERATOR_IN;
- case CompositeSourceOut:
- return CAIRO_OPERATOR_OUT;
- case CompositeSourceAtop:
- return CAIRO_OPERATOR_ATOP;
- case CompositeDestinationOver:
- return CAIRO_OPERATOR_DEST_OVER;
- case CompositeDestinationIn:
- return CAIRO_OPERATOR_DEST_IN;
- case CompositeDestinationOut:
- return CAIRO_OPERATOR_DEST_OUT;
- case CompositeDestinationAtop:
- return CAIRO_OPERATOR_DEST_ATOP;
- case CompositeXOR:
- return CAIRO_OPERATOR_XOR;
- case CompositePlusDarker:
- return CAIRO_OPERATOR_SATURATE;
- case CompositeHighlight:
- // There is no Cairo equivalent for CompositeHighlight.
- return CAIRO_OPERATOR_OVER;
- case CompositePlusLighter:
- return CAIRO_OPERATOR_ADD;
- default:
- return CAIRO_OPERATOR_SOURCE;
+ case CompositeClear:
+ return CAIRO_OPERATOR_CLEAR;
+ case CompositeCopy:
+ return CAIRO_OPERATOR_SOURCE;
+ case CompositeSourceOver:
+ return CAIRO_OPERATOR_OVER;
+ case CompositeSourceIn:
+ return CAIRO_OPERATOR_IN;
+ case CompositeSourceOut:
+ return CAIRO_OPERATOR_OUT;
+ case CompositeSourceAtop:
+ return CAIRO_OPERATOR_ATOP;
+ case CompositeDestinationOver:
+ return CAIRO_OPERATOR_DEST_OVER;
+ case CompositeDestinationIn:
+ return CAIRO_OPERATOR_DEST_IN;
+ case CompositeDestinationOut:
+ return CAIRO_OPERATOR_DEST_OUT;
+ case CompositeDestinationAtop:
+ return CAIRO_OPERATOR_DEST_ATOP;
+ case CompositeXOR:
+ return CAIRO_OPERATOR_XOR;
+ case CompositePlusDarker:
+ return CAIRO_OPERATOR_SATURATE;
+ case CompositeHighlight:
+ // There is no Cairo equivalent for CompositeHighlight.
+ return CAIRO_OPERATOR_OVER;
+ case CompositePlusLighter:
+ return CAIRO_OPERATOR_ADD;
+ default:
+ return CAIRO_OPERATOR_SOURCE;
}
}
@@ -965,12 +1073,16 @@ void GraphicsContext::clip(const Path& path)
m_data->clip(path);
}
+void GraphicsContext::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
return;
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,4,0)
cairo_t* cr = m_data->cr;
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
@@ -981,9 +1093,6 @@ void GraphicsContext::clipOut(const Path& path)
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_clip(cr);
cairo_set_fill_rule(cr, savedFillRule);
-#else
- notImplemented();
-#endif
}
void GraphicsContext::rotate(float radians)
@@ -1009,19 +1118,15 @@ void GraphicsContext::clipOut(const IntRect& r)
if (paintingDisabled())
return;
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,4,0)
cairo_t* cr = m_data->cr;
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
- cairo_rectangle(cr, x1, x2, x2 - x1, y2 - y1);
+ cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_clip(cr);
cairo_set_fill_rule(cr, savedFillRule);
-#else
- notImplemented();
-#endif
}
void GraphicsContext::clipOutEllipseInRect(const IntRect& r)
@@ -1034,7 +1139,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& r)
clipOut(p);
}
-void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -1044,6 +1149,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft,
beginPath();
addPath(Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight));
setColor(cr, color);
+ drawPathShadow(this, m_common, true, false);
cairo_fill(cr);
cairo_restore(cr);
}
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index c905ee8..d991c80 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -136,18 +136,20 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
*pixel = premultipliedARGBFromColor(pixelColor);
}
}
+ cairo_surface_mark_dirty_rectangle (m_data.m_surface, 0, 0, m_size.width(), m_size.height());
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+template <Multiply multiplied>
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& data, const IntSize& size)
{
- ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
+ ASSERT(cairo_surface_get_type(data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
- unsigned char* dataSrc = cairo_image_surface_get_data(m_data.m_surface);
+ unsigned char* dataSrc = cairo_image_surface_get_data(data.m_surface);
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());
+ if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
+ memset(dataDst, 0, result->data()->length());
int originx = rect.x();
int destx = 0;
@@ -156,8 +158,8 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originx = 0;
}
int endx = rect.x() + rect.width();
- if (endx > m_size.width())
- endx = m_size.width();
+ if (endx > size.width())
+ endx = size.width();
int numColumns = endx - originx;
int originy = rect.y();
@@ -167,11 +169,11 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originy = 0;
}
int endy = rect.y() + rect.height();
- if (endy > m_size.height())
- endy = m_size.height();
+ if (endy > size.height())
+ endy = size.height();
int numRows = endy - originy;
- int stride = cairo_image_surface_get_stride(m_data.m_surface);
+ int stride = cairo_image_surface_get_stride(data.m_surface);
unsigned destBytesPerRow = 4 * rect.width();
unsigned char* destRows = dataDst + desty * destBytesPerRow + destx * 4;
@@ -180,7 +182,11 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
for (int x = 0; x < numColumns; x++) {
int basex = x * 4;
unsigned* pixel = row + x + originx;
- Color pixelColor = colorFromPremultipliedARGB(*pixel);
+ Color pixelColor;
+ if (multiplied == Unmultiplied)
+ pixelColor = colorFromPremultipliedARGB(*pixel);
+ else
+ pixelColor = Color(*pixel);
destRows[basex] = pixelColor.red();
destRows[basex + 1] = pixelColor.green();
destRows[basex + 2] = pixelColor.blue();
@@ -192,11 +198,22 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
- ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
+ return getImageData<Unmultiplied>(rect, m_data, m_size);
+}
- unsigned char* dataDst = cairo_image_surface_get_data(m_data.m_surface);
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Premultiplied>(rect, m_data, m_size);
+}
+
+template <Multiply multiplied>
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size)
+{
+ ASSERT(cairo_surface_get_type(data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
+
+ unsigned char* dataDst = cairo_image_surface_get_data(data.m_surface);
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -204,28 +221,28 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
int originx = sourceRect.x();
int destx = destPoint.x() + sourceRect.x();
ASSERT(destx >= 0);
- ASSERT(destx < m_size.width());
+ ASSERT(destx < size.width());
ASSERT(originx >= 0);
ASSERT(originx <= sourceRect.right());
int endx = destPoint.x() + sourceRect.right();
- ASSERT(endx <= m_size.width());
+ ASSERT(endx <= 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(desty < size.height());
ASSERT(originy >= 0);
ASSERT(originy <= sourceRect.bottom());
int endy = destPoint.y() + sourceRect.bottom();
- ASSERT(endy <= m_size.height());
+ ASSERT(endy <= size.height());
int numRows = endy - desty;
unsigned srcBytesPerRow = 4 * source->width();
- int stride = cairo_image_surface_get_stride(m_data.m_surface);
+ int stride = cairo_image_surface_get_stride(data.m_surface);
unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
for (int y = 0; y < numRows; ++y) {
@@ -237,10 +254,26 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
srcRows[basex + 1],
srcRows[basex + 2],
srcRows[basex + 3]);
- *pixel = premultipliedARGBFromColor(pixelColor);
+ if (multiplied == Unmultiplied)
+ *pixel = premultipliedARGBFromColor(pixelColor);
+ else
+ *pixel = pixelColor.rgb();
}
srcRows += srcBytesPerRow;
}
+ cairo_surface_mark_dirty_rectangle (data.m_surface,
+ destx, desty,
+ numColumns, numRows);
+}
+
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size);
}
static cairo_status_t writeFunction(void* closure, const unsigned char* data, unsigned int length)
diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp
index c8c992e..92e36fc 100644
--- a/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -89,7 +89,7 @@ BitmapImage::BitmapImage(cairo_surface_t* surface, ImageObserver* observer)
checkForSolidColor();
}
-void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
+void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
FloatRect srcRect(src);
FloatRect dstRect(dst);
@@ -105,7 +105,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(context, dstRect, solidColor(), op);
+ fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op);
return;
}
@@ -125,17 +125,37 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
// Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
- // To avoid the unwanted gradient effect (#14017) we use
- // CAIRO_FILTER_NEAREST now, but the real fix will be to have
- // CAIRO_EXTEND_PAD implemented for surfaces in Cairo allowing us to still
- // use bilinear filtering
- cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
float scaleX = srcRect.width() / dstRect.width();
float scaleY = srcRect.height() / dstRect.height();
cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() };
cairo_pattern_set_matrix(pattern, &matrix);
+ // Draw the shadow
+#if ENABLE(FILTERS)
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (context->getShadow(shadowSize, shadowBlur, shadowColor)) {
+ IntSize shadowBufferSize;
+ FloatRect shadowRect;
+ float kernelSize (0.0);
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, dstRect, shadowSize, shadowBlur);
+ shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() * context->getAlpha()) / 255.f);
+
+ //draw shadow into a new ImageBuffer
+ OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+ cairo_t* shadowContext = shadowBuffer->context()->platformContext();
+ cairo_set_source(shadowContext, pattern);
+ cairo_translate(shadowContext, -dstRect.x(), -dstRect.y());
+ cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
+ cairo_fill(shadowContext);
+
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+ }
+#endif
+
// Draw the image.
cairo_translate(cr, dstRect.x(), dstRect.y());
cairo_set_source(cr, pattern);
@@ -151,7 +171,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
}
void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect)
{
cairo_surface_t* image = nativeImageForCurrentFrame();
if (!image) // If it's too early we won't have an image yet.
@@ -180,9 +200,6 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, con
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
- // Workaround to avoid the unwanted gradient effect (#14017)
- cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
-
cairo_matrix_t pattern_matrix = cairo_matrix_t(patternTransform);
cairo_matrix_t phase_matrix = {1, 0, 0, 1, phase.x() + tileRect.x() * patternTransform.a(), phase.y() + tileRect.y() * patternTransform.d()};
cairo_matrix_t combined;
diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp
index 75681bd..8bde57e 100644
--- a/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -78,15 +78,7 @@ void Path::clear()
bool Path::isEmpty() const
{
- cairo_t* cr = platformPath()->m_cr;
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,5,10)
- return !cairo_has_current_point(cr);
-#else
- cairo_path_t* p = cairo_copy_path(cr);
- bool hasData = p->num_data;
- cairo_path_destroy(p);
- return !hasData;
-#endif
+ return !cairo_has_current_point(platformPath()->m_cr);
}
bool Path::hasCurrentPoint() const
@@ -256,11 +248,7 @@ FloatRect Path::boundingRect() const
{
cairo_t* cr = platformPath()->m_cr;
double x0, x1, y0, y1;
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 6, 0)
cairo_path_extents(cr, &x0, &y0, &x1, &y1);
-#else
- cairo_stroke_extents(cr, &x0, &y0, &x1, &y1);
-#endif
return FloatRect(x0, y0, x1 - x0, y1 - y0);
}
diff --git a/WebCore/platform/graphics/cg/ColorCG.cpp b/WebCore/platform/graphics/cg/ColorCG.cpp
index 0465c0b..40aacc5 100644
--- a/WebCore/platform/graphics/cg/ColorCG.cpp
+++ b/WebCore/platform/graphics/cg/ColorCG.cpp
@@ -29,6 +29,7 @@
#if PLATFORM(CG)
#include <wtf/Assertions.h>
+#include <wtf/RetainPtr.h>
#include <ApplicationServices/ApplicationServices.h>
namespace WebCore {
@@ -75,13 +76,12 @@ CGColorRef createCGColor(const Color& c)
CMProfileRef prof = NULL;
CMGetSystemProfile(&prof);
- CGColorSpaceRef rgbSpace = CGColorSpaceCreateWithPlatformColorSpace(prof);
+ RetainPtr<CGColorSpaceRef> rgbSpace(AdoptCF, CGColorSpaceCreateWithPlatformColorSpace(prof));
- if (rgbSpace != NULL)
- {
- float components[4] = {c.red() / 255.0f, c.green() / 255.0f, c.blue() / 255.0f, c.alpha() / 255.0f};
- color = CGColorCreate(rgbSpace, components);
- CGColorSpaceRelease(rgbSpace);
+ if (rgbSpace) {
+ CGFloat components[4] = { static_cast<CGFloat>(c.red()) / 255, static_cast<CGFloat>(c.green()) / 255,
+ static_cast<CGFloat>(c.blue()) / 255, static_cast<CGFloat>(c.alpha()) / 255 };
+ color = CGColorCreate(rgbSpace.get(), components);
}
CMCloseProfile(prof);
diff --git a/WebCore/platform/graphics/cg/GradientCG.cpp b/WebCore/platform/graphics/cg/GradientCG.cpp
index c189fd5..05a0aad 100644
--- a/WebCore/platform/graphics/cg/GradientCG.cpp
+++ b/WebCore/platform/graphics/cg/GradientCG.cpp
@@ -58,17 +58,14 @@ CGShadingRef Gradient::platformGradient()
const CGFloat intervalRanges[2] = { 0, 1 };
const CGFloat colorComponentRanges[4 * 2] = { 0, 1, 0, 1, 0, 1, 0, 1 };
const CGFunctionCallbacks gradientCallbacks = { 0, gradientCallback, 0 };
- CGFunctionRef colorFunction = CGFunctionCreate(this, 1, intervalRanges, 4, colorComponentRanges, &gradientCallbacks);
+ RetainPtr<CGFunctionRef> colorFunction(AdoptCF, CGFunctionCreate(this, 1, intervalRanges, 4, colorComponentRanges, &gradientCallbacks));
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ static CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
if (m_radial)
- m_gradient = CGShadingCreateRadial(colorSpace, m_p0, m_r0, m_p1, m_r1, colorFunction, true, true);
+ m_gradient = CGShadingCreateRadial(colorSpace, m_p0, m_r0, m_p1, m_r1, colorFunction.get(), true, true);
else
- m_gradient = CGShadingCreateAxial(colorSpace, m_p0, m_p1, colorFunction, true, true);
-
- CGColorSpaceRelease(colorSpace);
- CGFunctionRelease(colorFunction);
+ m_gradient = CGShadingCreateAxial(colorSpace, m_p0, m_p1, colorFunction.get(), true, true);
return m_gradient;
}
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index ab8eb3c..39f06a6 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -28,40 +28,93 @@
#include "config.h"
#include "GraphicsContext.h"
-#include "TransformationMatrix.h"
#include "FloatConversion.h"
-#include "GraphicsContextPrivate.h"
#include "GraphicsContextPlatformPrivateCG.h"
+#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
#include "KURL.h"
#include "Path.h"
#include "Pattern.h"
+#include "TransformationMatrix.h"
+
#include <CoreGraphics/CGBitmapContext.h>
#include <CoreGraphics/CGPDFContext.h>
#include <wtf/MathExtras.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/RetainPtr.h>
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+// Building on 10.6 or later: kCGInterpolationMedium is defined in the CGInterpolationQuality enum.
#define HAVE_CG_INTERPOLATION_MEDIUM 1
#endif
+#if !defined(TARGETING_TIGER) && !defined(TARGETING_LEOPARD)
+// Targeting 10.6 or later: use kCGInterpolationMedium.
+#define WTF_USE_CG_INTERPOLATION_MEDIUM 1
+#endif
+
+#endif
+
using namespace std;
namespace WebCore {
-static void setCGFillColor(CGContextRef context, const Color& color)
+static CGColorRef createCGColorWithColorSpace(const Color& color, ColorSpace colorSpace)
{
- CGFloat red, green, blue, alpha;
- color.getRGBA(red, green, blue, alpha);
- CGContextSetRGBFillColor(context, red, green, blue, alpha);
+ CGFloat components[4];
+ color.getRGBA(components[0], components[1], components[2], components[3]);
+
+ CGColorRef cgColor = 0;
+ if (colorSpace == sRGBColorSpace)
+ cgColor = CGColorCreate(sRGBColorSpaceRef(), components);
+ else
+ cgColor = CGColorCreate(deviceRGBColorSpaceRef(), components);
+
+ return cgColor;
+}
+
+static void setCGFillColor(CGContextRef context, const Color& color, ColorSpace colorSpace)
+{
+ CGColorRef cgColor = createCGColorWithColorSpace(color, colorSpace);
+ CGContextSetFillColorWithColor(context, cgColor);
+ CFRelease(cgColor);
}
-static void setCGStrokeColor(CGContextRef context, const Color& color)
+static void setCGStrokeColor(CGContextRef context, const Color& color, ColorSpace colorSpace)
{
- CGFloat red, green, blue, alpha;
- color.getRGBA(red, green, blue, alpha);
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
+ CGColorRef cgColor = createCGColorWithColorSpace(color, colorSpace);
+ CGContextSetStrokeColorWithColor(context, cgColor);
+ CFRelease(cgColor);
+}
+
+static void setCGFillColorSpace(CGContextRef context, ColorSpace colorSpace)
+{
+ switch (colorSpace) {
+ case DeviceColorSpace:
+ break;
+ case sRGBColorSpace:
+ CGContextSetFillColorSpace(context, sRGBColorSpaceRef());
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+static void setCGStrokeColorSpace(CGContextRef context, ColorSpace colorSpace)
+{
+ switch (colorSpace) {
+ case DeviceColorSpace:
+ break;
+ case sRGBColorSpace:
+ CGContextSetStrokeColorSpace(context, sRGBColorSpaceRef());
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
}
GraphicsContext::GraphicsContext(CGContextRef cgContext)
@@ -71,8 +124,8 @@ GraphicsContext::GraphicsContext(CGContextRef cgContext)
setPaintingDisabled(!cgContext);
if (cgContext) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), fillColorSpace());
+ setPlatformStrokeColor(strokeColor(), strokeColorSpace());
}
}
@@ -86,7 +139,7 @@ CGContextRef GraphicsContext::platformContext() const
{
ASSERT(!paintingDisabled());
ASSERT(m_data->m_cgContext);
- return m_data->m_cgContext;
+ return m_data->m_cgContext.get();
}
void GraphicsContext::savePlatformState()
@@ -122,7 +175,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
// We do a fill of four rects to simulate the stroke of a border.
Color oldFillColor = fillColor();
if (oldFillColor != strokeColor())
- setCGFillColor(context, strokeColor());
+ setCGFillColor(context, strokeColor(), strokeColorSpace());
CGRect rects[4] = {
FloatRect(rect.x(), rect.y(), rect.width(), 1),
FloatRect(rect.x(), rect.bottom() - 1, rect.width(), 1),
@@ -131,7 +184,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
};
CGContextFillRects(context, rects, 4);
if (oldFillColor != strokeColor())
- setCGFillColor(context, oldFillColor);
+ setCGFillColor(context, oldFillColor, fillColorSpace());
}
}
@@ -178,19 +231,19 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
int patWidth = 0;
switch (strokeStyle()) {
- case NoStroke:
- case SolidStroke:
- break;
- case DottedStroke:
- patWidth = (int)width;
- break;
- case DashedStroke:
- patWidth = 3 * (int)width;
- break;
+ case NoStroke:
+ case SolidStroke:
+ break;
+ case DottedStroke:
+ patWidth = (int)width;
+ break;
+ case DashedStroke:
+ patWidth = 3 * (int)width;
+ break;
}
CGContextRef context = platformContext();
-
+
if (shouldAntialias())
CGContextSetShouldAntialias(context, false);
@@ -199,7 +252,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
// 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.
+ setCGFillColor(context, strokeColor(), strokeColorSpace()); // The save/restore make it safe to mutate the fill color here without setting it back to the old color.
if (isVerticalLine) {
CGContextFillRect(context, FloatRect(p1.x() - width / 2, p1.y() - width, width, width));
CGContextFillRect(context, FloatRect(p2.x() - width / 2, p2.y(), width, width));
@@ -221,7 +274,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth == 1)
patternOffset = 1.0f;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -235,7 +288,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
patternOffset = (patWidth - remainder)/2;
}
}
-
+
const CGFloat dottedLine[2] = { patWidth, patWidth };
CGContextSetLineDash(context, patternOffset, dottedLine, 2);
}
@@ -248,7 +301,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth)
CGContextRestoreGState(context);
-
+
if (shouldAntialias())
CGContextSetShouldAntialias(context, true);
}
@@ -263,7 +316,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
if (paintingDisabled())
return;
-
+
CGContextRef context = platformContext();
CGContextBeginPath(context);
float r = (float)rect.width() / 2;
@@ -275,25 +328,25 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
-{
+{
if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f)
return;
-
+
CGContextRef context = platformContext();
CGContextSaveGState(context);
CGContextBeginPath(context);
CGContextSetShouldAntialias(context, false);
-
+
int x = rect.x();
int y = rect.y();
float w = (float)rect.width();
float h = (float)rect.height();
float scaleFactor = h / w;
float reverseScaleFactor = w / h;
-
+
if (w != h)
scale(FloatSize(1, scaleFactor));
-
+
float hRadius = w / 2;
float vRadius = h / 2;
float fa = startAngle;
@@ -304,22 +357,21 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (w != h)
scale(FloatSize(1, reverseScaleFactor));
-
-
+
float width = strokeThickness();
int patWidth = 0;
-
+
switch (strokeStyle()) {
- case DottedStroke:
- patWidth = (int)(width / 2);
- break;
- case DashedStroke:
- patWidth = 3 * (int)(width / 2);
- break;
- default:
- break;
+ case DottedStroke:
+ patWidth = (int)(width / 2);
+ break;
+ case DashedStroke:
+ patWidth = 3 * (int)(width / 2);
+ break;
+ default:
+ break;
}
-
+
if (patWidth) {
// Example: 80 pixels with a width of 30 pixels.
// Remainder is 20. The maximum pixels of line we could paint
@@ -329,7 +381,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
distance = static_cast<int>((piFloat * hRadius) / 2.0f);
else // We are elliptical and will have to estimate the distance
distance = static_cast<int>((piFloat * sqrtf((hRadius * hRadius + vRadius * vRadius) / 2.0f)) / 2.0f);
-
+
int remainder = distance % patWidth;
int coverage = distance - remainder;
int numSegments = coverage / patWidth;
@@ -339,7 +391,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (patWidth == 1)
patternOffset = 1.0f;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -353,13 +405,13 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
patternOffset = (patWidth - remainder) / 2.0f;
}
}
-
+
const CGFloat dottedLine[2] = { patWidth, patWidth };
CGContextSetLineDash(context, patternOffset, dottedLine, 2);
}
CGContextStrokePath(context);
-
+
CGContextRestoreGState(context);
}
@@ -375,7 +427,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
if (antialiased != shouldAntialias())
CGContextSetShouldAntialias(context, antialiased);
-
+
CGContextBeginPath(context);
CGContextMoveToPoint(context, points[0].x(), points[0].y());
for (size_t i = 1; i < npoints; i++)
@@ -383,7 +435,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
CGContextClosePath(context);
drawPath();
-
+
if (antialiased != shouldAntialias())
CGContextSetShouldAntialias(context, shouldAntialias());
}
@@ -391,41 +443,37 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
void GraphicsContext::applyStrokePattern()
{
CGContextRef cgContext = platformContext();
-
- CGPatternRef platformPattern = m_common->state.strokePattern.get()->createPlatformPattern(getCTM());
+
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.strokePattern->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
- CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0);
- CGContextSetStrokeColorSpace(cgContext, patternSpace);
- CGColorSpaceRelease(patternSpace);
+ RetainPtr<CGColorSpaceRef> patternSpace(AdoptCF, CGColorSpaceCreatePattern(0));
+ CGContextSetStrokeColorSpace(cgContext, patternSpace.get());
const CGFloat patternAlpha = 1;
- CGContextSetStrokePattern(cgContext, platformPattern, &patternAlpha);
- CGPatternRelease(platformPattern);
+ CGContextSetStrokePattern(cgContext, platformPattern.get(), &patternAlpha);
}
void GraphicsContext::applyFillPattern()
{
CGContextRef cgContext = platformContext();
- CGPatternRef platformPattern = m_common->state.fillPattern.get()->createPlatformPattern(getCTM());
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.fillPattern->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
- CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0);
- CGContextSetFillColorSpace(cgContext, patternSpace);
- CGColorSpaceRelease(patternSpace);
+ RetainPtr<CGColorSpaceRef> patternSpace(AdoptCF, CGColorSpaceCreatePattern(0));
+ CGContextSetFillColorSpace(cgContext, patternSpace.get());
const CGFloat patternAlpha = 1;
- CGContextSetFillPattern(cgContext, platformPattern, &patternAlpha);
- CGPatternRelease(platformPattern);
+ CGContextSetFillPattern(cgContext, platformPattern.get(), &patternAlpha);
}
static inline bool calculateDrawingMode(const GraphicsContextState& state, CGPathDrawingMode& mode)
{
- bool shouldFill = state.fillColorSpace == PatternColorSpace || state.fillColor.alpha();
- bool shouldStroke = state.strokeColorSpace == PatternColorSpace || (state.strokeStyle != NoStroke && state.strokeColor.alpha());
+ bool shouldFill = state.fillPattern || state.fillColor.alpha();
+ bool shouldStroke = state.strokePattern || (state.strokeStyle != NoStroke && state.strokeColor.alpha());
bool useEOFill = state.fillRule == RULE_EVENODD;
if (shouldFill) {
@@ -457,16 +505,16 @@ void GraphicsContext::drawPath()
CGContextRef context = platformContext();
const GraphicsContextState& state = m_common->state;
- if (state.fillColorSpace == GradientColorSpace || state.strokeColorSpace == GradientColorSpace) {
+ if (state.fillGradient || state.strokeGradient) {
// We don't have any optimized way to fill & stroke a path using gradients
fillPath();
strokePath();
return;
}
-
- if (state.fillColorSpace == PatternColorSpace)
+
+ if (state.fillPattern)
applyFillPattern();
- if (state.strokeColorSpace == PatternColorSpace)
+ if (state.strokePattern)
applyStrokePattern();
CGPathDrawingMode drawingMode;
@@ -488,15 +536,11 @@ void GraphicsContext::fillPath()
return;
CGContextRef context = platformContext();
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- fillPathWithFillRule(context, fillRule());
- break;
- case PatternColorSpace:
- applyFillPattern();
- fillPathWithFillRule(context, fillRule());
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the fillPattern and fillGradient cases?
+ setCGFillColorSpace(context, m_common->state.fillColorSpace);
+
+ if (m_common->state.fillGradient) {
CGContextSaveGState(context);
if (fillRule() == RULE_EVENODD)
CGContextEOClip(context);
@@ -505,8 +549,12 @@ void GraphicsContext::fillPath()
CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform());
CGContextDrawShading(context, m_common->state.fillGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.fillPattern)
+ applyFillPattern();
+ fillPathWithFillRule(context, fillRule());
}
void GraphicsContext::strokePath()
@@ -515,76 +563,83 @@ void GraphicsContext::strokePath()
return;
CGContextRef context = platformContext();
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- CGContextStrokePath(context);
- break;
- case PatternColorSpace:
- applyStrokePattern();
- CGContextStrokePath(context);
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the strokePattern and strokeGradient cases?
+ setCGStrokeColorSpace(context, m_common->state.strokeColorSpace);
+
+ if (m_common->state.strokeGradient) {
CGContextSaveGState(context);
CGContextReplacePathWithStrokedPath(context);
CGContextClip(context);
CGContextConcatCTM(context, m_common->state.strokeGradient->gradientSpaceTransform());
CGContextDrawShading(context, m_common->state.strokeGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.strokePattern)
+ applyStrokePattern();
+ CGContextStrokePath(context);
}
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
+
CGContextRef context = platformContext();
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- CGContextFillRect(context, rect);
- break;
- case PatternColorSpace:
- applyFillPattern();
- CGContextFillRect(context, rect);
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the fillPattern and fillGradient cases?
+ setCGFillColorSpace(context, m_common->state.fillColorSpace);
+
+ if (m_common->state.fillGradient) {
CGContextSaveGState(context);
CGContextClipToRect(context, rect);
CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform());
CGContextDrawShading(context, m_common->state.fillGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.fillPattern)
+ applyFillPattern();
+ CGContextFillRect(context, rect);
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
CGContextRef context = platformContext();
Color oldFillColor = fillColor();
- if (oldFillColor != color)
- setCGFillColor(context, color);
+ ColorSpace oldColorSpace = fillColorSpace();
+
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, color, colorSpace);
+
CGContextFillRect(context, rect);
- if (oldFillColor != color)
- setCGFillColor(context, oldFillColor);
+
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, oldFillColor, oldColorSpace);
}
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
CGContextRef context = platformContext();
Color oldFillColor = fillColor();
- if (oldFillColor != color)
- setCGFillColor(context, color);
+ ColorSpace oldColorSpace = fillColorSpace();
+
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, color, colorSpace);
addPath(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
fillPath();
- if (oldFillColor != color)
- setCGFillColor(context, oldFillColor);
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, oldFillColor, oldColorSpace);
}
void GraphicsContext::clip(const FloatRect& rect)
@@ -599,7 +654,7 @@ void GraphicsContext::clipOut(const IntRect& rect)
{
if (paintingDisabled())
return;
-
+
CGRect rects[2] = { CGContextGetClipBoundingBox(platformContext()), rect };
CGContextBeginPath(platformContext());
CGContextAddRects(platformContext(), rects, 2);
@@ -610,7 +665,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
{
if (paintingDisabled())
return;
-
+
CGContextBeginPath(platformContext());
CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
CGContextAddEllipseInRect(platformContext(), rect);
@@ -639,13 +694,13 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
clip(rect);
CGContextRef context = platformContext();
-
+
// Add outer ellipse
CGContextAddEllipseInRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()));
// Add inner ellipse.
CGContextAddEllipseInRect(context, CGRectMake(rect.x() + thickness, rect.y() + thickness,
rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
-
+
CGContextEOClip(context);
}
@@ -653,7 +708,7 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer
{
if (paintingDisabled())
return;
-
+
CGContextTranslateCTM(platformContext(), rect.x(), rect.y() + rect.height());
CGContextScaleCTM(platformContext(), 1, -1);
CGContextClipToMask(platformContext(), FloatRect(FloatPoint(), rect.size()), imageBuffer->image()->getCGImageRef());
@@ -684,7 +739,7 @@ void GraphicsContext::endTransparencyLayer()
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
}
-void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color)
+void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -731,12 +786,11 @@ void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Col
if (!color.isValid())
CGContextSetShadow(context, CGSizeMake(width, height), blurRadius);
else {
- CGColorRef colorCG = createCGColor(color);
+ RetainPtr<CGColorRef> colorCG(AdoptCF, createCGColorWithColorSpace(color, colorSpace));
CGContextSetShadowWithColor(context,
CGSizeMake(width, height),
- blurRadius,
- colorCG);
- CGColorRelease(colorCG);
+ blurRadius,
+ colorCG.get());
}
}
@@ -774,15 +828,11 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
return;
CGContextRef context = platformContext();
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- CGContextStrokeRectWithWidth(context, r, lineWidth);
- break;
- case PatternColorSpace:
- applyStrokePattern();
- CGContextStrokeRectWithWidth(context, r, lineWidth);
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the strokePattern and strokeGradient cases?
+ setCGStrokeColorSpace(context, m_common->state.strokeColorSpace);
+
+ if (m_common->state.strokeGradient) {
CGContextSaveGState(context);
setStrokeThickness(lineWidth);
CGContextAddRect(context, r);
@@ -790,8 +840,12 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
CGContextClip(context);
CGContextDrawShading(context, m_common->state.strokeGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.strokePattern)
+ applyStrokePattern();
+ CGContextStrokeRectWithWidth(context, r, lineWidth);
}
void GraphicsContext::setLineCap(LineCap cap)
@@ -799,15 +853,15 @@ void GraphicsContext::setLineCap(LineCap cap)
if (paintingDisabled())
return;
switch (cap) {
- case ButtCap:
- CGContextSetLineCap(platformContext(), kCGLineCapButt);
- break;
- case RoundCap:
- CGContextSetLineCap(platformContext(), kCGLineCapRound);
- break;
- case SquareCap:
- CGContextSetLineCap(platformContext(), kCGLineCapSquare);
- break;
+ case ButtCap:
+ CGContextSetLineCap(platformContext(), kCGLineCapButt);
+ break;
+ case RoundCap:
+ CGContextSetLineCap(platformContext(), kCGLineCapRound);
+ break;
+ case SquareCap:
+ CGContextSetLineCap(platformContext(), kCGLineCapSquare);
+ break;
}
}
@@ -821,15 +875,15 @@ void GraphicsContext::setLineJoin(LineJoin join)
if (paintingDisabled())
return;
switch (join) {
- case MiterJoin:
- CGContextSetLineJoin(platformContext(), kCGLineJoinMiter);
- break;
- case RoundJoin:
- CGContextSetLineJoin(platformContext(), kCGLineJoinRound);
- break;
- case BevelJoin:
- CGContextSetLineJoin(platformContext(), kCGLineJoinBevel);
- break;
+ case MiterJoin:
+ CGContextSetLineJoin(platformContext(), kCGLineJoinMiter);
+ break;
+ case RoundJoin:
+ CGContextSetLineJoin(platformContext(), kCGLineJoinRound);
+ break;
+ case BevelJoin:
+ CGContextSetLineJoin(platformContext(), kCGLineJoinBevel);
+ break;
}
}
@@ -854,11 +908,16 @@ void GraphicsContext::clip(const Path& path)
m_data->clip(path);
}
+void GraphicsContext::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
return;
-
+
CGContextBeginPath(platformContext());
CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
CGContextAddPath(platformContext(), path.platformPath());
@@ -909,9 +968,9 @@ TransformationMatrix GraphicsContext::getCTM() const
FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
{
- // It is not enough just to round to pixels in device space. The rotation part of the
+ // 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
+ // 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.
if (m_data->m_userToDeviceTransformKnownToBeIdentity)
@@ -934,11 +993,11 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
deviceOrigin.y = roundf(deviceOrigin.y);
deviceLowerRight.x = roundf(deviceLowerRight.x);
deviceLowerRight.y = 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)
+ if (deviceOrigin.y == deviceLowerRight.y && rect.height())
deviceLowerRight.y += 1;
- if (deviceOrigin.x == deviceLowerRight.x && rect.width() != 0)
+ if (deviceOrigin.x == deviceLowerRight.x && rect.width())
deviceLowerRight.x += 1;
FloatPoint roundedOrigin = FloatPoint(deviceOrigin.x / deviceScaleX, deviceOrigin.y / deviceScaleY);
@@ -984,13 +1043,13 @@ void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool pri
}
}
}
-
+
if (fillColor() != strokeColor())
- setCGFillColor(platformContext(), strokeColor());
+ setCGFillColor(platformContext(), strokeColor(), strokeColorSpace());
CGContextFillRect(platformContext(), CGRectMake(x, y, lineLength, thickness));
if (fillColor() != strokeColor())
- setCGFillColor(platformContext(), fillColor());
-
+ setCGFillColor(platformContext(), fillColor(), fillColorSpace());
+
if (restoreAntialiasMode)
CGContextSetShouldAntialias(platformContext(), true);
}
@@ -999,51 +1058,50 @@ void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
{
if (paintingDisabled())
return;
-
- CFURLRef urlRef = link.createCFURL();
- if (urlRef) {
- CGContextRef context = platformContext();
-
- // Get the bounding box to handle clipping.
- CGRect box = CGContextGetClipBoundingBox(context);
-
- IntRect intBox((int)box.origin.x, (int)box.origin.y, (int)box.size.width, (int)box.size.height);
- IntRect rect = destRect;
- rect.intersect(intBox);
-
- CGPDFContextSetURLForRect(context, urlRef,
- CGRectApplyAffineTransform(rect, CGContextGetCTM(context)));
-
- CFRelease(urlRef);
- }
+
+ RetainPtr<CFURLRef> urlRef(AdoptCF, link.createCFURL());
+ if (!urlRef)
+ return;
+
+ CGContextRef context = platformContext();
+
+ // Get the bounding box to handle clipping.
+ CGRect box = CGContextGetClipBoundingBox(context);
+
+ IntRect intBox((int)box.origin.x, (int)box.origin.y, (int)box.size.width, (int)box.size.height);
+ IntRect rect = destRect;
+ rect.intersect(intBox);
+
+ CGPDFContextSetURLForRect(context, urlRef.get(),
+ CGRectApplyAffineTransform(rect, CGContextGetCTM(context)));
}
void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode)
{
if (paintingDisabled())
return;
-
+
CGInterpolationQuality quality = kCGInterpolationDefault;
switch (mode) {
- case InterpolationDefault:
- quality = kCGInterpolationDefault;
- break;
- case InterpolationNone:
- quality = kCGInterpolationNone;
- break;
- case InterpolationLow:
- quality = kCGInterpolationLow;
- break;
-
- // Fall through to InterpolationHigh if kCGInterpolationMedium is not available
- case InterpolationMedium:
-#if HAVE(CG_INTERPOLATION_MEDIUM)
- quality = kCGInterpolationMedium;
- break;
+ case InterpolationDefault:
+ quality = kCGInterpolationDefault;
+ break;
+ case InterpolationNone:
+ quality = kCGInterpolationNone;
+ break;
+ case InterpolationLow:
+ quality = kCGInterpolationLow;
+ break;
+
+ // Fall through to InterpolationHigh if kCGInterpolationMedium is not usable.
+ case InterpolationMedium:
+#if USE(CG_INTERPOLATION_MEDIUM)
+ quality = kCGInterpolationMedium;
+ break;
#endif
- case InterpolationHigh:
- quality = kCGInterpolationHigh;
- break;
+ case InterpolationHigh:
+ quality = kCGInterpolationHigh;
+ break;
}
CGContextSetInterpolationQuality(platformContext(), quality);
}
@@ -1055,18 +1113,24 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const
CGInterpolationQuality quality = CGContextGetInterpolationQuality(platformContext());
switch (quality) {
- case kCGInterpolationDefault:
- return InterpolationDefault;
- case kCGInterpolationNone:
- return InterpolationNone;
- case kCGInterpolationLow:
- return InterpolationLow;
+ case kCGInterpolationDefault:
+ return InterpolationDefault;
+ case kCGInterpolationNone:
+ return InterpolationNone;
+ case kCGInterpolationLow:
+ return InterpolationLow;
#if HAVE(CG_INTERPOLATION_MEDIUM)
- case kCGInterpolationMedium:
- return InterpolationMedium;
-#endif
- case kCGInterpolationHigh:
- return InterpolationHigh;
+ // kCGInterpolationMedium is known to be present in the CGInterpolationQuality enum.
+ case kCGInterpolationMedium:
+#if USE(CG_INTERPOLATION_MEDIUM)
+ // Only map to InterpolationMedium if targeting a system that understands it.
+ return InterpolationMedium;
+#else
+ return InterpolationDefault;
+#endif // USE(CG_INTERPOLATION_MEDIUM)
+#endif // HAVE(CG_INTERPOLATION_MEDIUM)
+ case kCGInterpolationHigh:
+ return InterpolationHigh;
}
return InterpolationDefault;
}
@@ -1079,40 +1143,40 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode)
// Wow, wish CG had used bits here.
CGContextRef context = platformContext();
switch (mode) {
- case cTextInvisible: // Invisible
- CGContextSetTextDrawingMode(context, kCGTextInvisible);
- break;
- case cTextFill: // Fill
- CGContextSetTextDrawingMode(context, kCGTextFill);
- break;
- case cTextStroke: // Stroke
- CGContextSetTextDrawingMode(context, kCGTextStroke);
- break;
- case 3: // Fill | Stroke
- CGContextSetTextDrawingMode(context, kCGTextFillStroke);
- break;
- case cTextClip: // Clip
- CGContextSetTextDrawingMode(context, kCGTextClip);
- break;
- case 5: // Fill | Clip
- CGContextSetTextDrawingMode(context, kCGTextFillClip);
- break;
- case 6: // Stroke | Clip
- CGContextSetTextDrawingMode(context, kCGTextStrokeClip);
- break;
- case 7: // Fill | Stroke | Clip
- CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip);
- break;
- default:
- break;
+ case cTextInvisible: // Invisible
+ CGContextSetTextDrawingMode(context, kCGTextInvisible);
+ break;
+ case cTextFill: // Fill
+ CGContextSetTextDrawingMode(context, kCGTextFill);
+ break;
+ case cTextStroke: // Stroke
+ CGContextSetTextDrawingMode(context, kCGTextStroke);
+ break;
+ case 3: // Fill | Stroke
+ CGContextSetTextDrawingMode(context, kCGTextFillStroke);
+ break;
+ case cTextClip: // Clip
+ CGContextSetTextDrawingMode(context, kCGTextClip);
+ break;
+ case 5: // Fill | Clip
+ CGContextSetTextDrawingMode(context, kCGTextFillClip);
+ break;
+ case 6: // Stroke | Clip
+ CGContextSetTextDrawingMode(context, kCGTextStrokeClip);
+ break;
+ case 7: // Fill | Stroke | Clip
+ CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip);
+ break;
+ default:
+ break;
}
}
-void GraphicsContext::setPlatformStrokeColor(const Color& color)
+void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
- setCGStrokeColor(platformContext(), color);
+ setCGStrokeColor(platformContext(), color, colorSpace);
}
void GraphicsContext::setPlatformStrokeThickness(float thickness)
@@ -1122,11 +1186,11 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness)
CGContextSetLineWidth(platformContext(), thickness);
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
- setCGFillColor(platformContext(), color);
+ setCGFillColor(platformContext(), color, colorSpace);
}
void GraphicsContext::setPlatformShouldAntialias(bool enable)
@@ -1138,54 +1202,54 @@ void GraphicsContext::setPlatformShouldAntialias(bool enable)
#ifndef BUILDING_ON_TIGER // Tiger's setCompositeOperation() is defined in GraphicsContextMac.mm.
void GraphicsContext::setCompositeOperation(CompositeOperator mode)
-{
+{
if (paintingDisabled())
return;
- CGBlendMode target = kCGBlendModeNormal;
+ CGBlendMode target = kCGBlendModeNormal;
switch (mode) {
- case CompositeClear:
- target = kCGBlendModeClear;
- break;
- case CompositeCopy:
- target = kCGBlendModeCopy;
- break;
- case CompositeSourceOver:
- //kCGBlendModeNormal
- break;
- case CompositeSourceIn:
- target = kCGBlendModeSourceIn;
- break;
- case CompositeSourceOut:
- target = kCGBlendModeSourceOut;
- break;
- case CompositeSourceAtop:
- target = kCGBlendModeSourceAtop;
- break;
- case CompositeDestinationOver:
- target = kCGBlendModeDestinationOver;
- break;
- case CompositeDestinationIn:
- target = kCGBlendModeDestinationIn;
- break;
- case CompositeDestinationOut:
- target = kCGBlendModeDestinationOut;
- break;
- case CompositeDestinationAtop:
- target = kCGBlendModeDestinationAtop;
- break;
- case CompositeXOR:
- target = kCGBlendModeXOR;
- break;
- case CompositePlusDarker:
- target = kCGBlendModePlusDarker;
- break;
- case CompositeHighlight:
- // currently unsupported
- break;
- case CompositePlusLighter:
- target = kCGBlendModePlusLighter;
- break;
+ case CompositeClear:
+ target = kCGBlendModeClear;
+ break;
+ case CompositeCopy:
+ target = kCGBlendModeCopy;
+ break;
+ case CompositeSourceOver:
+ //kCGBlendModeNormal
+ break;
+ case CompositeSourceIn:
+ target = kCGBlendModeSourceIn;
+ break;
+ case CompositeSourceOut:
+ target = kCGBlendModeSourceOut;
+ break;
+ case CompositeSourceAtop:
+ target = kCGBlendModeSourceAtop;
+ break;
+ case CompositeDestinationOver:
+ target = kCGBlendModeDestinationOver;
+ break;
+ case CompositeDestinationIn:
+ target = kCGBlendModeDestinationIn;
+ break;
+ case CompositeDestinationOut:
+ target = kCGBlendModeDestinationOut;
+ break;
+ case CompositeDestinationAtop:
+ target = kCGBlendModeDestinationAtop;
+ break;
+ case CompositeXOR:
+ target = kCGBlendModeXOR;
+ break;
+ case CompositePlusDarker:
+ target = kCGBlendModePlusDarker;
+ break;
+ case CompositeHighlight:
+ // currently unsupported
+ break;
+ case CompositePlusLighter:
+ target = kCGBlendModePlusLighter;
+ break;
}
CGContextSetBlendMode(platformContext(), target);
}
diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
index f63a8dd..ff1816f 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
+++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -27,6 +27,25 @@
namespace WebCore {
+// FIXME: This would be in GraphicsContextCG.h if that existed.
+inline CGColorSpaceRef deviceRGBColorSpaceRef()
+{
+ static CGColorSpaceRef deviceSpace = CGColorSpaceCreateDeviceRGB();
+ return deviceSpace;
+}
+
+// FIXME: This would be in GraphicsContextCG.h if that existed.
+inline CGColorSpaceRef sRGBColorSpaceRef()
+{
+ // FIXME: Windows should be able to use kCGColorSpaceSRGB, this is tracked by http://webkit.org/b/31363.
+#if PLATFORM(WIN) || defined(BUILDING_ON_TIGER)
+ return deviceRGBColorSpaceRef();
+#else
+ static CGColorSpaceRef sRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
+ return sRGBSpace;
+#endif
+}
+
class GraphicsContextPlatformPrivate {
public:
GraphicsContextPlatformPrivate(CGContextRef cgContext)
@@ -38,12 +57,10 @@ public:
#endif
, m_userToDeviceTransformKnownToBeIdentity(false)
{
- CGContextRetain(m_cgContext);
}
~GraphicsContextPlatformPrivate()
{
- CGContextRelease(m_cgContext);
}
#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
@@ -80,7 +97,7 @@ public:
bool m_shouldIncludeChildWindows;
#endif
- CGContextRef m_cgContext;
+ RetainPtr<CGContextRef> m_cgContext;
bool m_userToDeviceTransformKnownToBeIdentity;
};
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 6db7e88..b1896f8 100644
--- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -65,37 +65,37 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
bytesPerRow *= 4;
}
- m_data.m_data = tryFastCalloc(size.height(), bytesPerRow);
+ if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data))
+ return;
+
ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0);
- CGColorSpaceRef colorSpace;
+ RetainPtr<CGColorSpaceRef> colorSpace;
switch(imageColorSpace) {
case DeviceRGB:
- colorSpace = CGColorSpaceCreateDeviceRGB();
+ colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
break;
case GrayScale:
- colorSpace = CGColorSpaceCreateDeviceGray();
+ colorSpace.adoptCF(CGColorSpaceCreateDeviceGray());
break;
#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER)
case LinearRGB:
- colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear);
+ colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear));
break;
#endif
default:
- colorSpace = CGColorSpaceCreateDeviceRGB();
+ colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
break;
}
- CGContextRef cgContext = CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow,
- colorSpace, (imageColorSpace == GrayScale) ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast);
- CGColorSpaceRelease(colorSpace);
+ RetainPtr<CGContextRef> cgContext(AdoptCF, CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow,
+ colorSpace.get(), (imageColorSpace == GrayScale) ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast));
if (!cgContext)
return;
- m_context.set(new GraphicsContext(cgContext));
+ m_context.set(new GraphicsContext(cgContext.get()));
m_context->scale(FloatSize(1, -1));
m_context->translate(0, -size.height());
- CGContextRelease(cgContext);
success = true;
}
@@ -122,12 +122,13 @@ Image* ImageBuffer::image() const
return m_image.get();
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+template <Multiply multiplied>
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size)
{
PassRefPtr<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())
+ if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
memset(data, 0, result->data()->length());
int originx = rect.x();
@@ -137,8 +138,8 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originx = 0;
}
int endx = rect.x() + rect.width();
- if (endx > m_size.width())
- endx = m_size.width();
+ if (endx > size.width())
+ endx = size.width();
int numColumns = endx - originx;
int originy = rect.y();
@@ -148,20 +149,21 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originy = 0;
}
int endy = rect.y() + rect.height();
- if (endy > m_size.height())
- endy = m_size.height();
+ if (endy > size.height())
+ endy = size.height();
int numRows = endy - originy;
- unsigned srcBytesPerRow = 4 * m_size.width();
+ unsigned srcBytesPerRow = 4 * size.width();
unsigned destBytesPerRow = 4 * rect.width();
// ::create ensures that all ImageBuffers have valid data, so we don't need to check it here.
- unsigned char* srcRows = reinterpret_cast<unsigned char*>(m_data.m_data) + originy * srcBytesPerRow + originx * 4;
+ unsigned char* srcRows = reinterpret_cast<unsigned char*>(imageData.m_data) + originy * srcBytesPerRow + originx * 4;
unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
for (int y = 0; y < numRows; ++y) {
for (int x = 0; x < numColumns; x++) {
int basex = x * 4;
- if (unsigned char alpha = srcRows[basex + 3]) {
+ unsigned char alpha = srcRows[basex + 3];
+ if (multiplied == Unmultiplied && alpha) {
destRows[basex] = (srcRows[basex] * 255) / alpha;
destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha;
@@ -175,7 +177,18 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Unmultiplied>(rect, m_data, m_size);
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Premultiplied>(rect, m_data, m_size);
+}
+
+template <Multiply multiplied>
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -183,36 +196,36 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
int originx = sourceRect.x();
int destx = destPoint.x() + sourceRect.x();
ASSERT(destx >= 0);
- ASSERT(destx < m_size.width());
+ ASSERT(destx < size.width());
ASSERT(originx >= 0);
ASSERT(originx <= sourceRect.right());
int endx = destPoint.x() + sourceRect.right();
- ASSERT(endx <= m_size.width());
+ ASSERT(endx <= 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(desty < size.height());
ASSERT(originy >= 0);
ASSERT(originy <= sourceRect.bottom());
int endy = destPoint.y() + sourceRect.bottom();
- ASSERT(endy <= m_size.height());
+ ASSERT(endy <= size.height());
int numRows = endy - desty;
unsigned srcBytesPerRow = 4 * source->width();
- unsigned destBytesPerRow = 4 * m_size.width();
+ unsigned destBytesPerRow = 4 * size.width();
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;
+ unsigned char* destRows = reinterpret_cast<unsigned char*>(imageData.m_data) + desty * destBytesPerRow + destx * 4;
for (int y = 0; y < numRows; ++y) {
for (int x = 0; x < numColumns; x++) {
int basex = x * 4;
unsigned char alpha = srcRows[basex + 3];
- if (alpha != 255) {
+ if (multiplied == Unmultiplied && alpha != 255) {
destRows[basex] = (srcRows[basex] * alpha + 254) / 255;
destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255;
@@ -225,6 +238,16 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
}
}
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
{
#if PLATFORM(MAC)
diff --git a/WebCore/platform/graphics/cg/ImageCG.cpp b/WebCore/platform/graphics/cg/ImageCG.cpp
index a5620e8..2e372e2 100644
--- a/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -32,6 +32,7 @@
#include "FloatConversion.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
+#include "GraphicsContextPlatformPrivateCG.h"
#include "ImageObserver.h"
#include "PDFDocumentImage.h"
#include "PlatformString.h"
@@ -101,52 +102,72 @@ BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer)
void BitmapImage::checkForSolidColor()
{
m_checkedForSolidColor = true;
- if (frameCount() > 1)
+ if (frameCount() > 1) {
m_isSolidColor = false;
- else {
- CGImageRef image = frameAtIndex(0);
-
- // Currently we only check for solid color in the important special case of a 1x1 image.
- if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
- unsigned char pixel[4]; // RGBA
- CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
- CGContextRef bmap = CGBitmapContextCreate(pixel, 1, 1, 8, sizeof(pixel), space,
- kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
- if (bmap) {
- GraphicsContext(bmap).setCompositeOperation(CompositeCopy);
- CGRect dst = { {0, 0}, {1, 1} };
- CGContextDrawImage(bmap, dst, image);
- if (pixel[3] == 0)
- m_solidColor = Color(0, 0, 0, 0);
- else
- m_solidColor = Color(pixel[0] * 255 / pixel[3], pixel[1] * 255 / pixel[3], pixel[2] * 255 / pixel[3], pixel[3]);
- m_isSolidColor = true;
- CFRelease(bmap);
- }
- CFRelease(space);
- }
+ return;
+ }
+
+ CGImageRef image = frameAtIndex(0);
+
+ // Currently we only check for solid color in the important special case of a 1x1 image.
+ if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
+ unsigned char pixel[4]; // RGBA
+ static CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+ RetainPtr<CGContextRef> bmap(AdoptCF, CGBitmapContextCreate(pixel, 1, 1, 8, sizeof(pixel), space,
+ kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big));
+ if (!bmap)
+ return;
+ GraphicsContext(bmap.get()).setCompositeOperation(CompositeCopy);
+ CGRect dst = { {0, 0}, {1, 1} };
+ CGContextDrawImage(bmap.get(), dst, image);
+ if (pixel[3] == 0)
+ m_solidColor = Color(0, 0, 0, 0);
+ else
+ m_solidColor = Color(pixel[0] * 255 / pixel[3], pixel[1] * 255 / pixel[3], pixel[2] * 255 / pixel[3], pixel[3]);
+ m_isSolidColor = true;
}
}
+static RetainPtr<CGImageRef> imageWithColorSpace(CGImageRef originalImage, ColorSpace colorSpace)
+{
+ CGColorSpaceRef originalColorSpace = CGImageGetColorSpace(originalImage);
+
+ // If the image already has a (non-device) color space, we don't want to
+ // override it, so return.
+ if (!originalColorSpace || !CFEqual(originalColorSpace, deviceRGBColorSpaceRef()))
+ return originalImage;
+
+ switch (colorSpace) {
+ case DeviceColorSpace:
+ return originalImage;
+ case sRGBColorSpace:
+ return RetainPtr<CGImageRef>(AdoptCF, CGImageCreateCopyWithColorSpace(originalImage,
+ sRGBColorSpaceRef()));
+ }
+
+ ASSERT_NOT_REACHED();
+ return originalImage;
+}
+
CGImageRef BitmapImage::getCGImageRef()
{
return frameAtIndex(0);
}
-void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
startAnimation();
- CGImageRef image = frameAtIndex(m_currentFrame);
+ RetainPtr<CGImageRef> image = frameAtIndex(m_currentFrame);
if (!image) // If it's too early we won't have an image yet.
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, destRect, solidColor(), compositeOp);
+ fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, compositeOp);
return;
}
- float currHeight = CGImageGetHeight(image);
+ float currHeight = CGImageGetHeight(image.get());
if (currHeight <= srcRect.y())
return;
@@ -182,10 +203,10 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
adjustedDestRect.setHeight(subimageRect.height() / yScale);
- image = CGImageCreateWithImageInRect(image, subimageRect);
+ image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
if (currHeight < srcRect.bottom()) {
- ASSERT(CGImageGetHeight(image) == currHeight - CGRectIntegral(srcRect).origin.y);
- adjustedDestRect.setHeight(CGImageGetHeight(image) / yScale);
+ ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
+ adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
}
} else {
adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
@@ -205,11 +226,11 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
CGContextScaleCTM(context, 1, -1);
adjustedDestRect.setY(-adjustedDestRect.bottom());
- // Draw the image.
- CGContextDrawImage(context, adjustedDestRect, image);
+ // Adjust the color space.
+ image = imageWithColorSpace(image.get(), styleColorSpace);
- if (shouldUseSubimage)
- CGImageRelease(image);
+ // Draw the image.
+ CGContextDrawImage(context, adjustedDestRect, image.get());
ctxt->restore();
@@ -224,7 +245,7 @@ static void drawPatternCallback(void* info, CGContextRef context)
}
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
{
if (!nativeImageForCurrentFrame())
return;
@@ -252,15 +273,18 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
CGImageRef tileImage = nativeImageForCurrentFrame();
float h = CGImageGetHeight(tileImage);
- CGImageRef subImage;
+ RetainPtr<CGImageRef> subImage;
if (tileRect.size() == size())
subImage = tileImage;
else {
// Copying a sub-image out of a partially-decoded image stops the decoding of the original image. It should never happen
// because sub-images are only used for border-image, which only renders when the image is fully decoded.
ASSERT(h == height());
- subImage = CGImageCreateWithImageInRect(tileImage, tileRect);
+ subImage.adoptCF(CGImageCreateWithImageInRect(tileImage, tileRect));
}
+
+ // Adjust the color space.
+ subImage = imageWithColorSpace(subImage.get(), styleColorSpace);
#ifndef BUILDING_ON_TIGER
// Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
@@ -275,7 +299,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
#else
if (w == size().width() && h == size().height())
#endif
- CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage);
+ CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage.get());
else {
#endif
@@ -288,39 +312,31 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context));
// The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top.
matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h);
- CGPatternRef pattern = CGPatternCreate(subImage, CGRectMake(0, 0, tileRect.width(), tileRect.height()),
- matrix, tileRect.width(), tileRect.height(),
- kCGPatternTilingConstantSpacing, true, &patternCallbacks);
- if (pattern == NULL) {
- if (subImage != tileImage)
- CGImageRelease(subImage);
+ RetainPtr<CGPatternRef> pattern(AdoptCF, CGPatternCreate(subImage.get(), CGRectMake(0, 0, tileRect.width(), tileRect.height()),
+ matrix, tileRect.width(), tileRect.height(),
+ kCGPatternTilingConstantSpacing, true, &patternCallbacks));
+ if (!pattern) {
ctxt->restore();
return;
}
- CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
+ RetainPtr<CGColorSpaceRef> patternSpace(AdoptCF, CGColorSpaceCreatePattern(0));
CGFloat alpha = 1;
- CGColorRef color = CGColorCreateWithPattern(patternSpace, pattern, &alpha);
- CGContextSetFillColorSpace(context, patternSpace);
- CGColorSpaceRelease(patternSpace);
- CGPatternRelease(pattern);
+ RetainPtr<CGColorRef> color(AdoptCF, CGColorCreateWithPattern(patternSpace.get(), pattern.get(), &alpha));
+ CGContextSetFillColorSpace(context, patternSpace.get());
// FIXME: Really want a public API for this. It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
wkSetPatternBaseCTM(context, CGAffineTransformIdentity);
CGContextSetPatternPhase(context, CGSizeZero);
- CGContextSetFillColorWithColor(context, color);
+ CGContextSetFillColorWithColor(context, color.get());
CGContextFillRect(context, CGContextGetClipBoundingBox(context));
-
- CGColorRelease(color);
-
+
#ifndef BUILDING_ON_TIGER
}
#endif
- if (subImage != tileImage)
- CGImageRelease(subImage);
ctxt->restore();
if (imageObserver())
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index b716060..2b2c6b0 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -35,12 +35,27 @@
#include <ApplicationServices/ApplicationServices.h>
#include <wtf/UnusedParam.h>
+using namespace std;
+
namespace WebCore {
static const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
#if !PLATFORM(MAC)
-static void sharedBufferDerefCallback(void*, void* info)
+size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count)
+{
+ SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
+ size_t sourceSize = sharedBuffer->size();
+ if (position >= sourceSize)
+ return 0;
+
+ const char* source = sharedBuffer->data() + position;
+ size_t amount = min<size_t>(count, sourceSize - position);
+ memcpy(buffer, source, amount);
+ return amount;
+}
+
+void sharedBufferRelease(void* info)
{
SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
sharedBuffer->deref();
@@ -109,18 +124,18 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
#if PLATFORM(MAC)
// On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. We use SharedBuffer's ability
// to wrap itself inside CFData to get around this, ensuring that ImageIO is really looking at the SharedBuffer.
- CFDataRef cfData = data->createCFData();
+ RetainPtr<CFDataRef> cfData(AdoptCF, data->createCFData());
+ CGImageSourceUpdateData(m_decoder, cfData.get(), allDataReceived);
#else
- // If no NSData is available, then we know SharedBuffer will always just be a vector. That means no secret changes can occur to it behind the
- // scenes. We use CFDataCreateWithBytesNoCopy in that case. Ensure that the SharedBuffer lives as long as the CFDataRef.
+ // Create a CGDataProvider to wrap the SharedBuffer.
data->ref();
- CFAllocatorContext context = {0, data, 0, 0, 0, 0, 0, &sharedBufferDerefCallback, 0};
- CFAllocatorRef derefAllocator = CFAllocatorCreate(kCFAllocatorDefault, &context);
- CFDataRef cfData = CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data->data()), data->size(), derefAllocator);
- CFRelease(derefAllocator);
+ // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
+ // does not provide a way to lock down the byte pointer and guarantee that it won't move, which
+ // is a requirement for using the GetBytePointer callback.
+ CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, sharedBufferRelease };
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirect(data, data->size(), &providerCallbacks));
+ CGImageSourceUpdateDataProvider(m_decoder, dataProvider.get(), allDataReceived);
#endif
- CGImageSourceUpdateData(m_decoder, cfData, allDataReceived);
- CFRelease(cfData);
}
String ImageSource::filenameExtension() const
@@ -138,12 +153,11 @@ bool ImageSource::isSizeAvailable()
// Ragnaros yells: TOO SOON! You have awakened me TOO SOON, Executus!
if (imageSourceStatus >= kCGImageStatusIncomplete) {
- CFDictionaryRef image0Properties = CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions());
+ RetainPtr<CFDictionaryRef> image0Properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions()));
if (image0Properties) {
- CFNumberRef widthNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties, kCGImagePropertyPixelWidth);
- CFNumberRef heightNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties, kCGImagePropertyPixelHeight);
+ CFNumberRef widthNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties.get(), kCGImagePropertyPixelWidth);
+ CFNumberRef heightNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties.get(), kCGImagePropertyPixelHeight);
result = widthNumber && heightNumber;
- CFRelease(image0Properties);
}
}
@@ -153,17 +167,16 @@ bool ImageSource::isSizeAvailable()
IntSize ImageSource::frameSizeAtIndex(size_t index) const
{
IntSize result;
- CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions());
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions()));
if (properties) {
int w = 0, h = 0;
- CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth);
+ CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
if (num)
CFNumberGetValue(num, kCFNumberIntType, &w);
- num = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight);
+ num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
if (num)
CFNumberGetValue(num, kCFNumberIntType, &h);
result = IntSize(w, h);
- CFRelease(properties);
}
return result;
}
@@ -180,17 +193,15 @@ int ImageSource::repetitionCount()
return result;
// A property with value 0 means loop forever.
- CFDictionaryRef properties = CGImageSourceCopyProperties(m_decoder, imageSourceOptions());
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyProperties(m_decoder, imageSourceOptions()));
if (properties) {
- CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
+ CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
if (gifProperties) {
CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFLoopCount);
if (num)
CFNumberGetValue(num, kCFNumberIntType, &result);
} else
result = cAnimationNone; // Turns out we're not a GIF after all, so we don't animate.
-
- CFRelease(properties);
}
return result;
@@ -206,20 +217,19 @@ CGImageRef ImageSource::createFrameAtIndex(size_t index)
if (!initialized())
return 0;
- CGImageRef image = CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions());
+ RetainPtr<CGImageRef> image(AdoptCF, CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions()));
CFStringRef imageUTI = CGImageSourceGetType(m_decoder);
static const CFStringRef xbmUTI = CFSTR("public.xbitmap-image");
if (!imageUTI || !CFEqual(imageUTI, xbmUTI))
- return image;
+ return image.releaseRef();
// If it is an xbm image, mask out all the white areas to render them transparent.
const CGFloat maskingColors[6] = {255, 255, 255, 255, 255, 255};
- CGImageRef maskedImage = CGImageCreateWithMaskingColors(image, maskingColors);
+ RetainPtr<CGImageRef> maskedImage(AdoptCF, CGImageCreateWithMaskingColors(image.get(), maskingColors));
if (!maskedImage)
- return image;
-
- CGImageRelease(image);
- return maskedImage;
+ return image.releaseRef();
+
+ return maskedImage.releaseRef();
}
bool ImageSource::frameIsCompleteAtIndex(size_t index)
@@ -233,15 +243,14 @@ float ImageSource::frameDurationAtIndex(size_t index)
return 0;
float duration = 0;
- CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions());
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions()));
if (properties) {
- CFDictionaryRef typeProperties = (CFDictionaryRef)CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
+ CFDictionaryRef typeProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
if (typeProperties) {
CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(typeProperties, kCGImagePropertyGIFDelayTime);
if (num)
CFNumberGetValue(num, kCFNumberFloatType, &duration);
}
- CFRelease(properties);
}
// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.h b/WebCore/platform/graphics/cg/ImageSourceCG.h
index d5b4b5a..76b4160 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.h
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.h
@@ -36,6 +36,10 @@ String preferredExtensionForImageSourceType(const String& type);
String MIMETypeForImageSourceType(const String& type);
+#if !PLATFORM(MAC)
+size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count);
+#endif
+
}
#endif // ImageSourceCG_h
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
index 858b18e..67333ae 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
@@ -33,6 +33,10 @@
#include "ImageObserver.h"
#include <wtf/MathExtras.h>
+#if !PLATFORM(MAC)
+#include "ImageSourceCG.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -68,16 +72,17 @@ bool PDFDocumentImage::dataChanged(bool allDataReceived)
#if PLATFORM(MAC)
// On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. We use SharedBuffer's ability
// to wrap itself inside CFData to get around this, ensuring that ImageIO is really looking at the SharedBuffer.
- CFDataRef data = this->data()->createCFData();
+ RetainPtr<CFDataRef> data(AdoptCF, this->data()->createCFData());
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(data.get()));
#else
- // If no NSData is available, then we know SharedBuffer will always just be a vector. That means no secret changes can occur to it behind the
- // scenes. We use CFDataCreateWithBytesNoCopy in that case.
- CFDataRef data = CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(this->data()->data()), this->data()->size(), kCFAllocatorNull);
+ // Create a CGDataProvider to wrap the SharedBuffer.
+ // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
+ // does not provide a way to lock down the byte pointer and guarantee that it won't move, which
+ // is a requirement for using the GetBytePointer callback.
+ CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, 0 };
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirect(this->data(), this->data()->size(), &providerCallbacks));
#endif
- CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(data);
- CFRelease(data);
- m_document = CGPDFDocumentCreateWithProvider(dataProvider);
- CGDataProviderRelease(dataProvider);
+ m_document = CGPDFDocumentCreateWithProvider(dataProvider.get());
setCurrentPage(0);
}
return m_document; // return true if size is available
@@ -141,7 +146,7 @@ int PDFDocumentImage::pageCount() const
return m_document ? CGPDFDocumentGetNumberOfPages(m_document) : 0;
}
-void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op)
+void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator op)
{
if (!m_document || m_currentPage == -1)
return;
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.h b/WebCore/platform/graphics/cg/PDFDocumentImage.h
index 130c12c..12ab46c 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.h
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.h
@@ -58,7 +58,7 @@ namespace WebCore {
virtual IntSize size() const;
PDFDocumentImage();
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
void setCurrentPage(int);
int pageCount() const;
diff --git a/WebCore/platform/graphics/cg/PathCG.cpp b/WebCore/platform/graphics/cg/PathCG.cpp
index 5812cea..3b05641 100644
--- a/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/WebCore/platform/graphics/cg/PathCG.cpp
@@ -49,9 +49,8 @@ static size_t putBytesNowhere(void*, const void*, size_t count)
static CGContextRef createScratchContext()
{
CGDataConsumerCallbacks callbacks = { putBytesNowhere, 0 };
- CGDataConsumerRef consumer = CGDataConsumerCreate(0, &callbacks);
- CGContextRef context = CGPDFContextCreate(consumer, 0, 0);
- CGDataConsumerRelease(consumer);
+ RetainPtr<CGDataConsumerRef> consumer(AdoptCF, CGDataConsumerCreate(0, &callbacks));
+ CGContextRef context = CGPDFContextCreate(consumer.get(), 0, 0);
CGFloat black[4] = { 0, 0, 0, 1 };
CGContextSetFillColor(context, black);
@@ -129,9 +128,8 @@ bool Path::contains(const FloatPoint &point, WindRule rule) const
return false;
// CGPathContainsPoint returns false for non-closed paths, as a work-around, we copy and close the path first. Radar 4758998 asks for a better CG API to use
- CGMutablePathRef path = copyCGPathClosingSubpaths(m_path);
- bool ret = CGPathContainsPoint(path, 0, point, rule == RULE_EVENODD ? true : false);
- CGPathRelease(path);
+ RetainPtr<CGMutablePathRef> path(AdoptCF, copyCGPathClosingSubpaths(m_path));
+ bool ret = CGPathContainsPoint(path.get(), 0, point, rule == RULE_EVENODD ? true : false);
return ret;
}
diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
index 9252ae0..e8fa860 100644
--- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -261,7 +261,7 @@ static HFONT createFontIndirectAndGetWinName(const String& family, LOGFONT* winf
// 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;
+typedef HashMap<const wchar_t*, icu::UnicodeSet*> FontCmapCache;
static bool fontContainsCharacter(const FontPlatformData* fontData,
const wchar_t* family, UChar32 character)
@@ -277,7 +277,7 @@ static bool fontContainsCharacter(const FontPlatformData* fontData,
if (!fontCmapCache)
fontCmapCache = new FontCmapCache;
- HashMap<const wchar_t*, UnicodeSet*>::iterator it = fontCmapCache->find(family);
+ HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family);
if (it != fontCmapCache->end())
return it->second->contains(character);
@@ -308,7 +308,7 @@ static bool fontContainsCharacter(const FontPlatformData* fontData,
// 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;
+ icu::UnicodeSet* cmap = new icu::UnicodeSet;
while (i < glyphset->cRanges) {
WCHAR start = glyphset->ranges[i].wcLow;
cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1);
diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 3d67992..9f8f354 100644
--- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -112,12 +112,16 @@ void TransparencyAwareFontPainter::init()
void TransparencyAwareFontPainter::initializeForGDI()
{
+ m_graphicsContext->save();
SkColor color = m_platformContext->effectiveFillColor();
+ // Used only when m_createdTransparencyLayer is true.
+ float layerAlpha = 0.0f;
if (SkColorGetA(color) != 0xFF) {
// When the font has some transparency, apply it by creating a new
- // transparency layer with that opacity applied.
+ // transparency layer with that opacity applied. We'll actually create
+ // a new transparency layer after we calculate the bounding box.
m_createdTransparencyLayer = true;
- m_graphicsContext->beginTransparencyLayer(SkColorGetA(color) / 255.0f);
+ layerAlpha = SkColorGetA(color) / 255.0f;
// The color should be opaque now.
color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
}
@@ -131,16 +135,22 @@ void TransparencyAwareFontPainter::initializeForGDI()
// and we could do ClearType in that case.
layerMode = TransparencyWin::TextComposite;
layerRect = estimateTextBounds();
+ m_graphicsContext->clip(layerRect);
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->beginTransparencyLayer(layerAlpha);
// The transparency helper requires that we draw text in black in
// this mode and it will apply the color.
m_transparency.setTextCompositeColor(color);
color = SkColorSetRGB(0, 0, 0);
- } else if (canvasHasMultipleLayers(m_platformContext->canvas())) {
+ } else if (m_createdTransparencyLayer || canvasHasMultipleLayers(m_platformContext->canvas())) {
// When we're drawing a web page, we know the background is opaque,
// but if we're drawing to a layer, we still need extra work.
layerMode = TransparencyWin::OpaqueCompositeLayer;
layerRect = estimateTextBounds();
+ m_graphicsContext->clip(layerRect);
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->beginTransparencyLayer(layerAlpha);
} else {
// Common case of drawing onto the bottom layer of a web page: we
// know everything is opaque so don't need to do anything special.
@@ -167,6 +177,7 @@ TransparencyAwareFontPainter::~TransparencyAwareFontPainter()
m_transparency.composite();
if (m_createdTransparencyLayer)
m_graphicsContext->endTransparencyLayer();
+ m_graphicsContext->restore();
m_platformContext->canvas()->endPlatformPaint();
}
@@ -459,14 +470,16 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
TransparencyAwareUniscribePainter painter(graphicsContext, this, run, from, to, point);
HDC hdc = painter.hdc();
- if (!hdc)
+ if (windowsCanHandleTextDrawing(graphicsContext) && !hdc)
return;
// 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);
+ if (hdc) {
+ SetTextColor(hdc, skia::SkColorToCOLORREF(color));
+ SetBkMode(hdc, TRANSPARENT);
+ }
// If there is a non-blur shadow and both the fill color and shadow color
// are opaque, handle without skia.
diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
index 88035d5..6bd7d7c 100644
--- a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
@@ -42,12 +42,11 @@
#include "FontPlatformData.h"
#include "NotImplemented.h"
+#include "OpenTypeSanitizer.h"
#include "SharedBuffer.h"
#if PLATFORM(WIN_OS)
#include <objbase.h>
-#include <t2embapi.h>
-#pragma comment(lib, "t2embed")
#elif PLATFORM(LINUX)
#include <cstring>
#endif
@@ -57,13 +56,8 @@ 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);
- }
+ if (m_fontReference)
+ RemoveFontMemResourceEx(m_fontReference);
#elif PLATFORM(LINUX)
if (m_fontReference)
m_fontReference->unref();
@@ -76,19 +70,15 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
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()));
+ // 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.
@@ -119,69 +109,6 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
}
#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 EOTHeader& 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 EOTHeader& 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()
@@ -245,38 +172,22 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
{
ASSERT_ARG(buffer, buffer);
+#if ENABLE(OPENTYPE_SANITIZER)
+ OpenTypeSanitizer sanitizer(buffer);
+ RefPtr<SharedBuffer> transcodeBuffer = sanitizer.sanitize();
+ if (!transcodeBuffer)
+ return 0; // validation failed.
+ buffer = transcodeBuffer.get();
+#endif
+
#if PLATFORM(WIN_OS)
- // Introduce the font to GDI. AddFontMemResourceEx cannot be used, because it will pollute the process's
+ // Introduce the font to GDI. AddFontMemResourceEx should be used with care, 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.
-
+ // entire process first).
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.
- EOTHeader eotHeader;
- size_t overlayDst;
- size_t overlaySrc;
- size_t overlayLength;
-
- if (!getEOTHeader(buffer, eotHeader, overlayDst, overlaySrc, overlayLength))
+ HANDLE fontReference = renameAndActivateFont(buffer, fontName);
+ if (!fontReference)
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);
#elif PLATFORM(LINUX)
RemoteFontStream stream(buffer);
diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp
index d4e45fb..a4526a8 100644
--- a/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -45,6 +45,11 @@
#include "SkTypeface.h"
#include "SkUtils.h"
+#include <unicode/normlzr.h>
+#include <unicode/uchar.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/OwnPtr.h>
+
namespace WebCore {
bool Font::canReturnFallbackFontsForComplexText()
@@ -52,6 +57,23 @@ bool Font::canReturnFallbackFontsForComplexText()
return false;
}
+static bool isCanvasMultiLayered(SkCanvas* canvas)
+{
+ SkCanvas::LayerIter layerIterator(canvas, false);
+ layerIterator.next();
+ return !layerIterator.done();
+}
+
+static bool adjustTextRenderMode(SkPaint* paint, bool isCanvasMultiLayered)
+{
+ // Our layers only have a single alpha channel. This means that subpixel
+ // rendered text cannot be compositied correctly when the layer is
+ // collapsed. Therefore, subpixel text is disabled when we are drawing
+ // onto a layer.
+ if (isCanvasMultiLayered)
+ paint->setLCDRenderText(false);
+}
+
void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, int from, int numGlyphs,
const FloatPoint& point) const {
@@ -79,12 +101,14 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
SkCanvas* canvas = gc->platformContext()->canvas();
int textMode = gc->platformContext()->getTextDrawingMode();
+ bool haveMultipleLayers = isCanvasMultiLayered(canvas);
// We draw text up to two times (once for fill, once for stroke).
if (textMode & cTextFill) {
SkPaint paint;
gc->platformContext()->setupPaintForFilling(&paint);
font->platformData().setupPaint(&paint);
+ adjustTextRenderMode(&paint, haveMultipleLayers);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setColor(gc->fillColor().rgb());
canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
@@ -97,6 +121,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
SkPaint paint;
gc->platformContext()->setupPaintForStroking(&paint, 0, 0);
font->platformData().setupPaint(&paint);
+ adjustTextRenderMode(&paint, haveMultipleLayers);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setColor(gc->strokeColor().rgb());
@@ -136,27 +161,29 @@ class TextRunWalker {
public:
TextRunWalker(const TextRun& run, unsigned startingX, const Font* font)
: m_font(font)
- , m_run(run)
, m_startingX(startingX)
, m_offsetX(m_startingX)
- , m_iterateBackwards(run.rtl())
+ , m_run(getTextRun(run))
+ , m_iterateBackwards(m_run.rtl())
{
+ // Do not use |run| inside this constructor. Use |m_run| instead.
+
memset(&m_item, 0, sizeof(m_item));
// We cannot know, ahead of time, how many glyphs a given script run
// will produce. We take a guess that script runs will not produce more
// than twice as many glyphs as there are code points and fallback if
// we find that we are wrong.
- m_maxGlyphs = run.length() * 2;
+ m_maxGlyphs = m_run.length() * 2;
createGlyphArrays();
- m_item.log_clusters = new unsigned short[run.length()];
+ m_item.log_clusters = new unsigned short[m_run.length()];
m_item.face = 0;
m_item.font = allocHarfbuzzFont();
- m_item.string = run.characters();
- m_item.stringLength = run.length();
- m_item.item.bidiLevel = run.rtl();
+ m_item.string = m_run.characters();
+ m_item.stringLength = m_run.length();
+ m_item.item.bidiLevel = m_run.rtl();
reset();
}
@@ -283,6 +310,43 @@ public:
}
private:
+ const TextRun& getTextRun(const TextRun& originalRun)
+ {
+ // Convert the |originalRun| to NFC normalized form if combining diacritical marks
+ // (U+0300..) are used in the run. This conversion is necessary since most OpenType
+ // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in
+ // their GSUB tables.
+ //
+ // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since
+ // the API returns FALSE (= not normalized) for complex runs that don't require NFC
+ // normalization (e.g., Arabic text). Unless the run contains the diacritical marks,
+ // Harfbuzz will do the same thing for us using the GSUB table.
+ for (unsigned i = 0; i < originalRun.length(); ++i) {
+ UBlockCode block = ::ublock_getCode(originalRun[i]);
+ if (block == UBLOCK_COMBINING_DIACRITICAL_MARKS) {
+ return getNormalizedTextRun(originalRun);
+ }
+ }
+ return originalRun;
+ }
+
+ const TextRun& getNormalizedTextRun(const TextRun& originalRun)
+ {
+ icu::UnicodeString normalizedString;
+ UErrorCode error = U_ZERO_ERROR;
+ icu::Normalizer::normalize(icu::UnicodeString(originalRun.characters(), originalRun.length()), UNORM_NFC, 0 /* no options */, normalizedString, error);
+ if (U_FAILURE(error))
+ return originalRun;
+
+ m_normalizedBuffer.set(new UChar[normalizedString.length() + 1]);
+ normalizedString.extract(m_normalizedBuffer.get(), normalizedString.length() + 1, error);
+ ASSERT(U_SUCCESS(error));
+
+ m_normalizedRun.set(new TextRun(originalRun));
+ m_normalizedRun->setText(m_normalizedBuffer.get(), normalizedString.length());
+ return *m_normalizedRun;
+ }
+
void setupFontForScriptRun()
{
const FontData* fontData = m_font->fontDataAt(0);
@@ -379,7 +443,6 @@ private:
}
const Font* const m_font;
- const TextRun& m_run;
HB_ShaperItem m_item;
uint16_t* m_glyphs16; // A vector of 16-bit glyph ids.
SkScalar* m_xPositions; // A vector of x positions for each glyph.
@@ -389,6 +452,10 @@ private:
unsigned m_pixelWidth; // Width (in px) of the current script run.
unsigned m_numCodePoints; // Code points in current script run.
unsigned m_maxGlyphs; // Current size of all the Harfbuzz arrays.
+
+ OwnPtr<TextRun> m_normalizedRun;
+ OwnArrayPtr<UChar> m_normalizedBuffer; // A buffer for normalized run.
+ const TextRun& m_run;
bool m_iterateBackwards;
};
@@ -425,15 +492,18 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
}
TextRunWalker walker(run, point.x(), this);
+ bool haveMultipleLayers = isCanvasMultiLayered(canvas);
while (walker.nextScriptRun()) {
if (fill) {
walker.fontPlatformDataForScriptRun()->setupPaint(&fillPaint);
+ adjustTextRenderMode(&fillPaint, haveMultipleLayers);
canvas->drawPosTextH(walker.glyphs(), walker.length() << 1, walker.xPositions(), point.y(), fillPaint);
}
if (stroke) {
walker.fontPlatformDataForScriptRun()->setupPaint(&strokePaint);
+ adjustTextRenderMode(&strokePaint, haveMultipleLayers);
canvas->drawPosTextH(walker.glyphs(), walker.length() << 1, walker.xPositions(), point.y(), strokePaint);
}
}
@@ -598,8 +668,6 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run,
if (toX == -1 && !to)
toX = rightEdge;
- else if (!walker.rtl())
- toX += truncateFixedPointToInteger(toAdvance);
ASSERT(fromX != -1 && toX != -1);
diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
index 9596a4c..4e2a226 100644
--- a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
@@ -100,11 +100,11 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap)
// 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();
+ icu::Locale locale = icu::Locale::getDefault();
const UChar* localeFamily = 0;
- if (locale == Locale::getJapanese())
+ if (locale == icu::Locale::getJapanese())
localeFamily = scriptFontMap[USCRIPT_HIRAGANA];
- else if (locale == Locale::getKorean())
+ else if (locale == icu::Locale::getKorean())
localeFamily = scriptFontMap[USCRIPT_HANGUL];
else {
// Use Simplified Chinese font for all other locales including
diff --git a/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
index a5a6e1f..1386163 100644
--- a/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
+++ b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
@@ -46,12 +46,6 @@ Icon::~Icon()
{
}
-PassRefPtr<Icon> Icon::createIconForFile(const String&)
-{
- notImplemented();
- return 0;
-}
-
PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
{
notImplemented();
diff --git a/WebCore/platform/graphics/chromium/IconChromiumMac.cpp b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
index 93e36ba..23ca698 100644
--- a/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
+++ b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
@@ -39,11 +39,6 @@
namespace WebCore {
-PassRefPtr<Icon> Icon::createIconForFile(const String&)
-{
- return 0;
-}
-
PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
{
return 0;
diff --git a/WebCore/platform/graphics/chromium/IconChromiumWin.cpp b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
index b419e6f..b0145f8 100644
--- a/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
@@ -52,26 +52,11 @@ Icon::~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.
+ // FIXME: We can't access icons directly from renderer processes.
// http://code.google.com/p/chromium/issues/detail?id=4092
- if (!filenames.size())
- return 0;
-
- return createIconForFile(filenames[0]);
+ return 0;
}
void Icon::paint(GraphicsContext* context, const IntRect& rect)
diff --git a/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/WebCore/platform/graphics/chromium/TransparencyWin.cpp
index 7957d5a..6dcd595 100644
--- a/WebCore/platform/graphics/chromium/TransparencyWin.cpp
+++ b/WebCore/platform/graphics/chromium/TransparencyWin.cpp
@@ -275,7 +275,7 @@ void TransparencyWin::setupLayerForWhiteLayer()
if (!m_validLayer)
return;
- m_drawContext->fillRect(IntRect(IntPoint(0, 0), m_layerSize), Color::white);
+ m_drawContext->fillRect(IntRect(IntPoint(0, 0), m_layerSize), Color::white, DeviceColorSpace);
// Layer rect represents the part of the original layer.
}
diff --git a/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
index 39b0847..10fcdf6 100644
--- a/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
+++ b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
@@ -375,11 +375,13 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext,
// 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);
+ if (useWindowsDrawing) {
+ 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
@@ -401,7 +403,7 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext,
} else {
SkPoint origin;
origin.fX = curX + + innerOffset;
- origin.fY = y + m_ascent - shaping.m_ascentOffset;
+ origin.fY = y + m_ascent;
textOutOk = paintSkiaText(graphicsContext,
shaping.m_hfont,
glyphCount,
diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp
index 86b702f..f362148 100644
--- a/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 2009 Dirk Schulze <krit@webkit.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -24,7 +25,13 @@
#if ENABLE(FILTERS)
#include "FEBlend.h"
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "FloatPoint.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+
+typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
namespace WebCore {
@@ -61,8 +68,77 @@ void FEBlend::setBlendMode(BlendModeType mode)
m_mode = mode;
}
-void FEBlend::apply(Filter*)
+static unsigned char unknown(unsigned char, unsigned char, unsigned char, unsigned char)
+{
+ return 0;
+}
+
+static unsigned char normal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char)
+{
+ return (((255 - alphaA) * colorB + colorA * 255) / 255);
+}
+
+static unsigned char multiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
+{
+ return (((255 - alphaA) * colorB + (255 - alphaB + colorB) * colorA) / 255);
+}
+
+static unsigned char screen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char)
+{
+ return (((colorB + colorA) * 255 - colorA * colorB) / 255);
+}
+
+static unsigned char darken(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
+{
+ return ((std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
+}
+
+static unsigned char lighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
{
+ return ((std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
+}
+
+void FEBlend::apply(Filter* filter)
+{
+ m_in->apply(filter);
+ m_in2->apply(filter);
+ if (!m_in->resultImage() || !m_in2->resultImage())
+ return;
+
+ if (m_mode == FEBLEND_MODE_UNKNOWN)
+ return;
+
+ if (!getEffectContext())
+ return;
+
+ IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
+
+ IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data());
+
+ IntRect imageRect(IntPoint(), resultImage()->size());
+ RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
+
+ // Keep synchronized with BlendModeType
+ static const BlendType callEffect[] = {unknown, normal, multiply, screen, darken, lighten};
+
+ ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
+ for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) {
+ unsigned char alphaA = srcPixelArrayA->get(pixelOffset + 3);
+ unsigned char alphaB = srcPixelArrayB->get(pixelOffset + 3);
+ for (unsigned channel = 0; channel < 3; ++channel) {
+ unsigned char colorA = srcPixelArrayA->get(pixelOffset + channel);
+ unsigned char colorB = srcPixelArrayB->get(pixelOffset + channel);
+
+ unsigned char result = (*callEffect[m_mode])(colorA, colorB, alphaA, alphaB);
+ imageData->data()->set(pixelOffset + channel, result);
+ }
+ unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255;
+ imageData->data()->set(pixelOffset + 3, alphaR);
+ }
+
+ resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEBlend::dump()
diff --git a/WebCore/platform/graphics/filters/FEBlend.h b/WebCore/platform/graphics/filters/FEBlend.h
index b09cd72..31c625f 100644
--- a/WebCore/platform/graphics/filters/FEBlend.h
+++ b/WebCore/platform/graphics/filters/FEBlend.h
@@ -41,7 +41,7 @@ namespace WebCore {
class FEBlend : public FilterEffect {
public:
static PassRefPtr<FEBlend> create(FilterEffect*, FilterEffect*, BlendModeType);
-
+
FilterEffect* in2() const;
void setIn2(FilterEffect*);
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index fb0a194..f422157 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -30,6 +30,7 @@
#include "GraphicsContext.h"
#include "ImageData.h"
#include <math.h>
+#include <wtf/MathExtras.h>
namespace WebCore {
@@ -92,8 +93,8 @@ inline void saturate(double& red, double& green, double& blue, const float& s)
inline void huerotate(double& red, double& green, double& blue, const float& hue)
{
- double cosHue = cos(hue * M_PI / 180);
- double sinHue = sin(hue * M_PI / 180);
+ double cosHue = cos(hue * piDouble / 180);
+ double sinHue = sin(hue * piDouble / 180);
double r = red * (0.213 + cosHue * 0.787 - sinHue * 0.213) +
green * (0.715 - cosHue * 0.715 - sinHue * 0.715) +
blue * (0.072 - cosHue * 0.072 + sinHue * 0.928);
@@ -163,10 +164,10 @@ void FEColorMatrix::apply(Filter* filter)
if (!filterContext)
return;
- filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
IntRect imageRect(IntPoint(), resultImage()->size());
- PassRefPtr<ImageData> imageData(resultImage()->getImageData(imageRect));
+ PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect));
PassRefPtr<CanvasPixelArray> srcPixelArray(imageData->data());
switch (m_type) {
@@ -186,7 +187,7 @@ void FEColorMatrix::apply(Filter* filter)
break;
}
- resultImage()->putImageData(imageData.get(), imageRect, IntPoint());
+ resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEColorMatrix::dump()
diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index 54ac123..1d9cfff 100644
--- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 2009 Dirk Schulze <krit@webkit.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -24,10 +25,16 @@
#if ENABLE(FILTERS)
#include "FEComponentTransfer.h"
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include <math.h>
namespace WebCore {
+typedef void (*TransferType)(unsigned char*, const ComponentTransferFunction&);
+
FEComponentTransfer::FEComponentTransfer(FilterEffect* in, const ComponentTransferFunction& redFunc,
const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc)
: FilterEffect()
@@ -85,8 +92,91 @@ void FEComponentTransfer::setAlphaFunction(const ComponentTransferFunction& func
m_alphaFunc = func;
}
-void FEComponentTransfer::apply(Filter*)
+static void identity(unsigned char*, const ComponentTransferFunction&)
+{
+}
+
+static void table(unsigned char* values, const ComponentTransferFunction& transferFunction)
+{
+ const Vector<float>& tableValues = transferFunction.tableValues;
+ unsigned n = tableValues.size();
+ if (n < 1)
+ return;
+ for (unsigned i = 0; i < 256; ++i) {
+ double c = i / 255.0;
+ unsigned k = static_cast<unsigned>(c * (n - 1));
+ double v1 = tableValues[k];
+ double v2 = tableValues[std::min((k + 1), (n - 1))];
+ double val = 255.0 * (v1 + (c * (n - 1) - k) * (v2 - v1));
+ val = std::max(0.0, std::min(255.0, val));
+ values[i] = static_cast<unsigned char>(val);
+ }
+}
+
+static void discrete(unsigned char* values, const ComponentTransferFunction& transferFunction)
+{
+ const Vector<float>& tableValues = transferFunction.tableValues;
+ unsigned n = tableValues.size();
+ if (n < 1)
+ return;
+ for (unsigned i = 0; i < 256; ++i) {
+ unsigned k = static_cast<unsigned>((i * n) / 255.0);
+ k = std::min(k, n - 1);
+ double val = 255 * tableValues[k];
+ val = std::max(0.0, std::min(255.0, val));
+ values[i] = static_cast<unsigned char>(val);
+ }
+}
+
+static void linear(unsigned char* values, const ComponentTransferFunction& transferFunction)
+{
+ for (unsigned i = 0; i < 256; ++i) {
+ double val = transferFunction.slope * i + 255 * transferFunction.intercept;
+ val = std::max(0.0, std::min(255.0, val));
+ values[i] = static_cast<unsigned char>(val);
+ }
+}
+
+static void gamma(unsigned char* values, const ComponentTransferFunction& transferFunction)
+{
+ for (unsigned i = 0; i < 256; ++i) {
+ double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), transferFunction.exponent) + transferFunction.offset);
+ val = std::max(0.0, std::min(255.0, val));
+ values[i] = static_cast<unsigned char>(val);
+ }
+}
+
+void FEComponentTransfer::apply(Filter* filter)
{
+ m_in->apply(filter);
+ if (!m_in->resultImage())
+ return;
+
+ if (!getEffectContext())
+ return;
+
+ unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
+ for (unsigned i = 0; i < 256; ++i)
+ rValues[i] = gValues[i] = bValues[i] = aValues[i] = i;
+ unsigned char* tables[] = { rValues, gValues, bValues, aValues };
+ ComponentTransferFunction transferFunction[] = {m_redFunc, m_greenFunc, m_blueFunc, m_alphaFunc};
+ TransferType callEffect[] = {identity, identity, table, discrete, linear, gamma};
+
+ for (unsigned channel = 0; channel < 4; channel++)
+ (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
+
+ IntRect drawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
+ RefPtr<ImageData> imageData(m_in->resultImage()->getUnmultipliedImageData(drawingRect));
+ CanvasPixelArray* srcPixelArray(imageData->data());
+
+ for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) {
+ for (unsigned channel = 0; channel < 4; ++channel) {
+ unsigned char c = srcPixelArray->get(pixelOffset + channel);
+ imageData->data()->set(pixelOffset + channel, tables[channel][c]);
+ }
+ }
+
+ resultImage()->putUnmultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
}
void FEComponentTransfer::dump()
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index 0706358..c540cb7 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 2009 Dirk Schulze <krit@webkit.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -24,7 +25,10 @@
#if ENABLE(FILTERS)
#include "FEComposite.h"
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
namespace WebCore {
@@ -97,8 +101,74 @@ void FEComposite::setK4(float k4)
m_k4 = k4;
}
-void FEComposite::apply(Filter*)
+inline void arithmetic(const RefPtr<CanvasPixelArray>& srcPixelArrayA, CanvasPixelArray*& srcPixelArrayB,
+ float k1, float k2, float k3, float k4)
{
+ float scaledK1 = k1 / 255.f;
+ float scaledK4 = k4 * 255.f;
+ for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) {
+ for (unsigned channel = 0; channel < 4; ++channel) {
+ unsigned char i1 = srcPixelArrayA->get(pixelOffset + channel);
+ unsigned char i2 = srcPixelArrayB->get(pixelOffset + channel);
+
+ unsigned char result = scaledK1 * i1 * i2 + k2 * i1 + k3 * i2 + scaledK4;
+ if (channel == 3 && i1 == 0 && i2 == 0)
+ result = 0;
+ srcPixelArrayB->set(pixelOffset + channel, result);
+ }
+ }
+}
+
+void FEComposite::apply(Filter* filter)
+{
+ m_in->apply(filter);
+ m_in2->apply(filter);
+ if (!m_in->resultImage() || !m_in2->resultImage())
+ return;
+
+ GraphicsContext* filterContext = getEffectContext();
+ if (!filterContext)
+ return;
+
+ FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f);
+ switch (m_type) {
+ case FECOMPOSITE_OPERATOR_OVER:
+ filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
+ break;
+ case FECOMPOSITE_OPERATOR_IN:
+ filterContext->save();
+ filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->scaledSubRegion()), m_in2->resultImage());
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
+ filterContext->restore();
+ break;
+ case FECOMPOSITE_OPERATOR_OUT:
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
+ filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut);
+ break;
+ case FECOMPOSITE_OPERATOR_ATOP:
+ filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop);
+ break;
+ case FECOMPOSITE_OPERATOR_XOR:
+ filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR);
+ break;
+ case FECOMPOSITE_OPERATOR_ARITHMETIC: {
+ IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
+
+ IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion());
+ RefPtr<ImageData> imageData(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect));
+ CanvasPixelArray* srcPixelArrayB(imageData->data());
+
+ arithmetic(srcPixelArrayA, srcPixelArrayB, m_k1, m_k2, m_k3, m_k4);
+ resultImage()->putPremultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
+ }
+ break;
+ default:
+ break;
+ }
}
void FEComposite::dump()
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
new file mode 100644
index 0000000..0b97e39
--- /dev/null
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ 2004, 2005 Rob Buis <buis@kde.org>
+ 2005 Eric Seidel <eric@webkit.org>
+ 2009 Dirk Schulze <krit@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(FILTERS)
+#include "FEGaussianBlur.h"
+
+#include "CanvasPixelArray.h"
+#include "Filter.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include <math.h>
+#include <wtf/MathExtras.h>
+
+using std::max;
+
+namespace WebCore {
+
+FEGaussianBlur::FEGaussianBlur(FilterEffect* in, const float& x, const float& y)
+ : FilterEffect()
+ , m_in(in)
+ , m_x(x)
+ , m_y(y)
+{
+}
+
+PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(FilterEffect* in, const float& x, const float& y)
+{
+ return adoptRef(new FEGaussianBlur(in, x, y));
+}
+
+float FEGaussianBlur::stdDeviationX() const
+{
+ return m_x;
+}
+
+void FEGaussianBlur::setStdDeviationX(float x)
+{
+ m_x = x;
+}
+
+float FEGaussianBlur::stdDeviationY() const
+{
+ return m_y;
+}
+
+void FEGaussianBlur::setStdDeviationY(float y)
+{
+ m_y = y;
+}
+
+static void boxBlur(CanvasPixelArray*& srcPixelArray, CanvasPixelArray*& dstPixelArray,
+ unsigned dx, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage)
+{
+ int dxLeft = dx / 2;
+ int dxRight = dx - dxLeft;
+
+ for (int y = 0; y < effectHeight; ++y) {
+ int line = y * strideLine;
+ for (int channel = 3; channel >= 0; --channel) {
+ int sum = 0;
+ // Fill the kernel
+ int maxKernelSize = std::min(dxRight, effectWidth);
+ for (int i = 0; i < maxKernelSize; ++i)
+ sum += srcPixelArray->get(line + i * stride + channel);
+
+ // Blurring
+ for (int x = 0; x < effectWidth; ++x) {
+ int pixelByteOffset = line + x * stride + channel;
+ dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
+ if (x >= dxLeft)
+ sum -= srcPixelArray->get(pixelByteOffset - dxLeft * stride);
+ if (x + dxRight < effectWidth)
+ sum += srcPixelArray->get(pixelByteOffset + dxRight * stride);
+ }
+ if (alphaImage) // Source image is black, it just has different alpha values
+ break;
+ }
+ }
+}
+
+void FEGaussianBlur::apply(Filter* filter)
+{
+ m_in->apply(filter);
+ if (!m_in->resultImage())
+ return;
+
+ if (!getEffectContext())
+ return;
+
+ setIsAlphaImage(m_in->isAlphaImage());
+
+ if (m_x == 0 || m_y == 0)
+ return;
+
+ unsigned sdx = static_cast<unsigned>(floor(m_x * filter->filterResolution().width() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
+ unsigned sdy = static_cast<unsigned>(floor(m_y * filter->filterResolution().height() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
+ sdx = max(sdx, static_cast<unsigned>(1));
+ sdy = max(sdy, static_cast<unsigned>(1));
+
+ IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
+ RefPtr<ImageData> srcImageData(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect));
+ CanvasPixelArray* srcPixelArray(srcImageData->data());
+
+ IntRect imageRect(IntPoint(), resultImage()->size());
+ RefPtr<ImageData> tmpImageData = ImageData::create(imageRect.width(), imageRect.height());
+ CanvasPixelArray* tmpPixelArray(tmpImageData->data());
+
+ int stride = 4 * imageRect.width();
+ for (int i = 0; i < 3; ++i) {
+ boxBlur(srcPixelArray, tmpPixelArray, sdx, 4, stride, imageRect.width(), imageRect.height(), isAlphaImage());
+ boxBlur(tmpPixelArray, srcPixelArray, sdy, stride, 4, imageRect.height(), imageRect.width(), isAlphaImage());
+ }
+
+ resultImage()->putPremultipliedImageData(srcImageData.get(), imageRect, IntPoint());
+}
+
+void FEGaussianBlur::dump()
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.h b/WebCore/platform/graphics/filters/FEGaussianBlur.h
new file mode 100644
index 0000000..ecdb9e3
--- /dev/null
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ 2004, 2005 Rob Buis <buis@kde.org>
+ 2005 Eric Seidel <eric@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef FEGaussianBlur_h
+#define FEGaussianBlur_h
+
+#if ENABLE(FILTERS)
+#include "FilterEffect.h"
+#include "Filter.h"
+
+namespace WebCore {
+
+ class FEGaussianBlur : public FilterEffect {
+ public:
+ static PassRefPtr<FEGaussianBlur> create(FilterEffect*, const float&, const float&);
+
+ float stdDeviationX() const;
+ void setStdDeviationX(float);
+
+ float stdDeviationY() const;
+ void setStdDeviationY(float);
+
+ virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); }
+ void apply(Filter*);
+ void dump();
+
+ private:
+ FEGaussianBlur(FilterEffect*, const float&, const float&);
+
+ RefPtr<FilterEffect> m_in;
+ float m_x;
+ float m_y;
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
+
+#endif // FEGaussianBlur_h
diff --git a/WebCore/platform/graphics/filters/Filter.h b/WebCore/platform/graphics/filters/Filter.h
index ee97afc..8924b94 100644
--- a/WebCore/platform/graphics/filters/Filter.h
+++ b/WebCore/platform/graphics/filters/Filter.h
@@ -22,6 +22,7 @@
#if ENABLE(FILTERS)
#include "FloatRect.h"
+#include "FloatSize.h"
#include "ImageBuffer.h"
#include "StringHash.h"
@@ -40,15 +41,21 @@ namespace WebCore {
void setSourceImage(PassOwnPtr<ImageBuffer> sourceImage) { m_sourceImage = sourceImage; }
ImageBuffer* sourceImage() { return m_sourceImage.get(); }
- virtual FloatRect sourceImageRect() = 0;
- virtual FloatRect filterRegion() = 0;
+ FloatSize filterResolution() const { return m_filterResolution; }
+ void setFilterResolution(const FloatSize& filterResolution) { m_filterResolution = filterResolution; }
+
+ virtual FloatRect sourceImageRect() const = 0;
+ virtual FloatRect filterRegion() const = 0;
// SVG specific
- virtual void calculateEffectSubRegion(FilterEffect*) = 0;
- virtual bool effectBoundingBoxMode() = 0;
+ virtual void calculateEffectSubRegion(FilterEffect*) { }
+
+ virtual FloatSize maxImageSize() const = 0;
+ virtual bool effectBoundingBoxMode() const = 0;
private:
OwnPtr<ImageBuffer> m_sourceImage;
+ FloatSize m_filterResolution;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp
index 41e8a39..5583813 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -25,14 +25,11 @@
namespace WebCore {
FilterEffect::FilterEffect()
- : m_xBBoxMode(false)
- , m_yBBoxMode(false)
- , m_widthBBoxMode(false)
- , m_heightBBoxMode(false)
- , m_hasX(false)
+ : m_hasX(false)
, m_hasY(false)
, m_hasWidth(false)
, m_hasHeight(false)
+ , m_alphaImage(false)
{
}
@@ -59,16 +56,23 @@ FloatRect FilterEffect::calculateEffectRect(Filter* filter)
return subRegion();
}
+IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect)
+{
+ IntPoint location = roundedIntPoint(FloatPoint(scaledSubRegion().x() - effectRect.x(),
+ scaledSubRegion().y() - effectRect.y()));
+ return IntRect(location, resultImage()->size());
+}
+
FloatRect FilterEffect::calculateDrawingRect(const FloatRect& srcRect)
{
- FloatPoint startPoint = FloatPoint(srcRect.x() - subRegion().x(), srcRect.y() - subRegion().y());
+ FloatPoint startPoint = FloatPoint(srcRect.x() - scaledSubRegion().x(), srcRect.y() - scaledSubRegion().y());
FloatRect drawingRect = FloatRect(startPoint, srcRect.size());
return drawingRect;
}
GraphicsContext* FilterEffect::getEffectContext()
{
- IntRect bufferRect = enclosingIntRect(subRegion());
+ IntRect bufferRect = enclosingIntRect(scaledSubRegion());
m_effectBuffer = ImageBuffer::create(bufferRect.size(), LinearRGB);
return m_effectBuffer->context();
}
diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h
index 8dc6233..a46d795 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/WebCore/platform/graphics/filters/FilterEffect.h
@@ -38,24 +38,18 @@ namespace WebCore {
public:
virtual ~FilterEffect();
- bool xBoundingBoxMode() const { return m_xBBoxMode; }
- void setXBoundingBoxMode(bool bboxMode) { m_xBBoxMode = bboxMode; }
-
- bool yBoundingBoxMode() const { return m_yBBoxMode; }
- void setYBoundingBoxMode(bool bboxMode) { m_yBBoxMode = bboxMode; }
-
- bool widthBoundingBoxMode() const { return m_widthBBoxMode; }
- void setWidthBoundingBoxMode(bool bboxMode) { m_widthBBoxMode = bboxMode; }
-
- bool heightBoundingBoxMode() const { return m_heightBBoxMode; }
- void setHeightBoundingBoxMode(bool bboxMode) { m_heightBBoxMode = bboxMode; }
-
void setUnionOfChildEffectSubregions(const FloatRect& uniteRect) { m_unionOfChildEffectSubregions = uniteRect; }
FloatRect unionOfChildEffectSubregions() const { return m_unionOfChildEffectSubregions; }
FloatRect subRegion() const { return m_subRegion; }
void setSubRegion(const FloatRect& subRegion) { m_subRegion = subRegion; }
+ FloatRect scaledSubRegion() const { return m_scaledSubRegion; }
+ void setScaledSubRegion(const FloatRect& scaledSubRegion) { m_scaledSubRegion = scaledSubRegion; }
+
+ FloatRect effectBoundaries() const { return m_effectBoundaries; }
+ void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; }
+
bool hasX() { return m_hasX; }
void setHasX(bool value) { m_hasX = value; }
@@ -77,6 +71,11 @@ namespace WebCore {
GraphicsContext* getEffectContext();
FloatRect calculateDrawingRect(const FloatRect&);
+ IntRect calculateDrawingIntRect(const FloatRect&);
+
+ // black image with different alpha values
+ bool isAlphaImage() { return m_alphaImage; }
+ void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; }
virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return filter->filterRegion(); }
virtual FloatRect calculateEffectRect(Filter*);
@@ -101,7 +100,11 @@ namespace WebCore {
bool m_hasWidth : 1;
bool m_hasHeight : 1;
+ bool m_alphaImage;
+
+ FloatRect m_effectBoundaries;
FloatRect m_subRegion;
+ FloatRect m_scaledSubRegion;
FloatRect m_unionOfChildEffectSubregions;
mutable OwnPtr<ImageBuffer> m_effectBuffer;
diff --git a/WebCore/platform/graphics/filters/ImageBufferFilter.cpp b/WebCore/platform/graphics/filters/ImageBufferFilter.cpp
new file mode 100644
index 0000000..33953d6
--- /dev/null
+++ b/WebCore/platform/graphics/filters/ImageBufferFilter.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if ENABLE(FILTERS)
+#include "ImageBufferFilter.h"
+
+#include "FloatSize.h"
+
+namespace WebCore {
+
+ImageBufferFilter::ImageBufferFilter()
+ : Filter()
+{
+ setFilterResolution(FloatSize(1.f, 1.f));
+}
+
+PassRefPtr<ImageBufferFilter> ImageBufferFilter::create()
+{
+ return adoptRef(new ImageBufferFilter());
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/ImageBufferFilter.h b/WebCore/platform/graphics/filters/ImageBufferFilter.h
new file mode 100644
index 0000000..a2775ea
--- /dev/null
+++ b/WebCore/platform/graphics/filters/ImageBufferFilter.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ImageBufferFilter_h
+#define ImageBufferFilter_h
+
+#if ENABLE(FILTERS)
+#include "Filter.h"
+#include "FilterEffect.h"
+#include "FloatRect.h"
+#include "FloatSize.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class ImageBufferFilter : public Filter {
+public:
+ static PassRefPtr<ImageBufferFilter> create();
+
+ virtual FloatRect filterRegion() const { return FloatRect(); }
+ virtual FloatRect sourceImageRect() const { return FloatRect(); }
+
+ // SVG specific
+ virtual bool effectBoundingBoxMode() const { return false; }
+
+ virtual FloatSize maxImageSize() const { return FloatSize(); }
+ virtual void calculateEffectSubRegion(FilterEffect*) { }
+
+private:
+ ImageBufferFilter();
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
+
+#endif // ImageBufferFilter_h
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp
index 646a57b..539bb44 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.cpp
+++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -22,6 +22,7 @@
#if ENABLE(FILTERS)
#include "SourceAlpha.h"
+#include "Color.h"
#include "GraphicsContext.h"
#include "PlatformString.h"
#include "Filter.h"
@@ -41,8 +42,32 @@ const AtomicString& SourceAlpha::effectName()
return s_effectName;
}
-void SourceAlpha::apply(Filter*)
+FloatRect SourceAlpha::calculateEffectRect(Filter* filter)
{
+ FloatRect clippedSourceRect = filter->sourceImageRect();
+ if (filter->sourceImageRect().x() < filter->filterRegion().x())
+ clippedSourceRect.setX(filter->filterRegion().x());
+ if (filter->sourceImageRect().y() < filter->filterRegion().y())
+ clippedSourceRect.setY(filter->filterRegion().y());
+ setSubRegion(clippedSourceRect);
+ clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
+ setScaledSubRegion(clippedSourceRect);
+ return filter->filterRegion();
+}
+
+void SourceAlpha::apply(Filter* filter)
+{
+ GraphicsContext* filterContext = getEffectContext();
+ if (!filterContext)
+ return;
+
+ setIsAlphaImage(true);
+
+ FloatRect imageRect(FloatPoint(), filter->sourceImage()->image()->size());
+ filterContext->save();
+ filterContext->clipToImageBuffer(imageRect, filter->sourceImage());
+ filterContext->fillRect(imageRect, Color::black, DeviceColorSpace);
+ filterContext->restore();
}
void SourceAlpha::dump()
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.h b/WebCore/platform/graphics/filters/SourceAlpha.h
index 5341562..172d05a 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.h
+++ b/WebCore/platform/graphics/filters/SourceAlpha.h
@@ -35,7 +35,7 @@ namespace WebCore {
static const AtomicString& effectName();
virtual bool isSourceInput() { return true; }
- virtual FloatRect calculateEffectRect(Filter* filter) { return filter->sourceImageRect(); }
+ virtual FloatRect calculateEffectRect(Filter*);
void apply(Filter*);
void dump();
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp
index 023eeac..cc55618 100644
--- a/WebCore/platform/graphics/filters/SourceGraphic.cpp
+++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp
@@ -49,6 +49,8 @@ FloatRect SourceGraphic::calculateEffectRect(Filter* filter)
if (filter->sourceImageRect().y() < filter->filterRegion().y())
clippedSourceRect.setY(filter->filterRegion().y());
setSubRegion(clippedSourceRect);
+ clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
+ setScaledSubRegion(clippedSourceRect);
return filter->filterRegion();
}
@@ -58,7 +60,7 @@ void SourceGraphic::apply(Filter* filter)
if (!filterContext)
return;
- filterContext->drawImage(filter->sourceImage()->image(), IntPoint());
+ filterContext->drawImage(filter->sourceImage()->image(), DeviceColorSpace, IntPoint());
}
void SourceGraphic::dump()
diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp b/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp
new file mode 100644
index 0000000..567da74
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2009 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "DataSourceGStreamer.h"
+
+#include <gio/gio.h>
+#include <glib.h>
+#include <gst/gst.h>
+#include <gst/pbutils/missing-plugins.h>
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC(webkit_data_src_debug);
+#define GST_CAT_DEFAULT webkit_data_src_debug
+
+static void webkit_data_src_uri_handler_init(gpointer g_iface,
+ gpointer iface_data);
+
+static void webkit_data_src_finalize(WebkitDataSrc* src);
+static GstStateChangeReturn webkit_data_src_change_state(GstElement* element,
+ GstStateChange transition);
+
+static const GInterfaceInfo urihandler_info = {
+ webkit_data_src_uri_handler_init,
+ 0, 0
+};
+
+
+static void _do_init(GType datasrc_type)
+{
+ GST_DEBUG_CATEGORY_INIT(webkit_data_src_debug, "webkit_data_src", 0, "datasrc element");
+ g_type_add_interface_static(datasrc_type, GST_TYPE_URI_HANDLER,
+ &urihandler_info);
+}
+
+GST_BOILERPLATE_FULL(WebkitDataSrc, webkit_data_src, GstBin, GST_TYPE_BIN, _do_init);
+
+static void webkit_data_src_base_init(gpointer klass)
+{
+ GstElementClass* element_class = GST_ELEMENT_CLASS(klass);
+
+ gst_element_class_add_pad_template(element_class,
+ gst_static_pad_template_get(&src_template));
+ gst_element_class_set_details_simple(element_class, (gchar*) "WebKit data source element",
+ (gchar*) "Source",
+ (gchar*) "Handles data: uris",
+ (gchar*) "Philippe Normand <pnormand@igalia.com>");
+
+}
+
+static void webkit_data_src_class_init(WebkitDataSrcClass* klass)
+{
+ GObjectClass* oklass = G_OBJECT_CLASS(klass);
+ GstElementClass* eklass = GST_ELEMENT_CLASS(klass);
+
+ oklass->finalize = (GObjectFinalizeFunc) webkit_data_src_finalize;
+ eklass->change_state = webkit_data_src_change_state;
+}
+
+
+static gboolean webkit_data_src_reset(WebkitDataSrc* src)
+{
+ GstPad* targetpad;
+
+ if (src->kid) {
+ gst_element_set_state(src->kid, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(src), src->kid);
+ }
+
+ src->kid = gst_element_factory_make("giostreamsrc", "streamsrc");
+ if (!src->kid) {
+ GST_ERROR_OBJECT(src, "Failed to create giostreamsrc");
+ return FALSE;
+ }
+
+ gst_bin_add(GST_BIN(src), src->kid);
+
+ targetpad = gst_element_get_static_pad(src->kid, "src");
+ gst_ghost_pad_set_target(GST_GHOST_PAD(src->pad), targetpad);
+ gst_object_unref(targetpad);
+
+ return TRUE;
+}
+
+static void webkit_data_src_init(WebkitDataSrc* src,
+ WebkitDataSrcClass* g_class)
+{
+ GstPadTemplate* pad_template = gst_static_pad_template_get(&src_template);
+ src->pad = gst_ghost_pad_new_no_target_from_template("src",
+ pad_template);
+
+ gst_element_add_pad(GST_ELEMENT(src), src->pad);
+
+ webkit_data_src_reset(src);
+}
+
+static void webkit_data_src_finalize(WebkitDataSrc* src)
+{
+ g_free(src->uri);
+
+ if (src->kid) {
+ GST_DEBUG_OBJECT(src, "Removing giostreamsrc element");
+ gst_element_set_state(src->kid, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(src), src->kid);
+ src->kid = 0;
+ }
+
+ GST_CALL_PARENT(G_OBJECT_CLASS, finalize, ((GObject* )(src)));
+}
+
+static GstStateChangeReturn webkit_data_src_change_state(GstElement* element, GstStateChange transition)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ WebkitDataSrc* src = WEBKIT_DATA_SRC(element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ if (!src->kid) {
+ gst_element_post_message(element,
+ gst_missing_element_message_new(element, "giostreamsrc"));
+ GST_ELEMENT_ERROR(src, CORE, MISSING_PLUGIN, (0), ("no giostreamsrc"));
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
+ if (G_UNLIKELY(ret == GST_STATE_CHANGE_FAILURE))
+ return ret;
+
+ // Downwards state change code should be here, after chaining up
+ // to the parent class.
+
+ return ret;
+}
+
+/*** GSTURIHANDLER INTERFACE *************************************************/
+
+static GstURIType webkit_data_src_uri_get_type(void)
+{
+ return GST_URI_SRC;
+}
+
+static gchar** webkit_data_src_uri_get_protocols(void)
+{
+ static gchar* protocols[] = {(gchar*) "data", 0 };
+
+ return protocols;
+}
+
+static const gchar* webkit_data_src_uri_get_uri(GstURIHandler* handler)
+{
+ WebkitDataSrc* src = WEBKIT_DATA_SRC(handler);
+
+ return src->uri;
+}
+
+static gboolean webkit_data_src_uri_set_uri(GstURIHandler* handler, const gchar* uri)
+{
+ WebkitDataSrc* src = WEBKIT_DATA_SRC(handler);
+
+ // URI as defined in RFC2397:
+ // "data:" [ mediatype ] [ ";base64" ] "," data
+ // we parse URIs like this one:
+ // data:audio/3gpp;base64,AA...
+
+ gchar** scheme_and_remains = g_strsplit(uri, ":", 2);
+ gchar** mime_type_and_options = g_strsplit(scheme_and_remains[1], ";", 0);
+ gint options_size = g_strv_length(mime_type_and_options);
+ gchar* data = 0;
+ gchar* mime_type = 0;
+ gint ret = FALSE;
+
+ // we require uris with a specified mime-type and base64-encoded
+ // data. It doesn't make much sense anyway to play plain/text data
+ // with very few allowed characters (as per the RFC).
+
+ if (GST_STATE(src) >= GST_STATE_PAUSED) {
+ GST_ERROR_OBJECT(src, "Element already configured. Reset it and retry");
+ } else if (!options_size)
+ GST_ERROR_OBJECT(src, "A mime-type is needed in %s", uri);
+ else {
+ mime_type = mime_type_and_options[0];
+ data = mime_type_and_options[options_size-1];
+
+ guchar* decoded_data = 0;
+ gsize decoded_size;
+
+ if (!g_str_has_prefix(data, "base64"))
+ GST_ERROR_OBJECT(src, "Data has to be base64-encoded in %s", uri);
+ else {
+ decoded_data = g_base64_decode(data+7, &decoded_size);
+ GInputStream* stream = g_memory_input_stream_new_from_data(decoded_data,
+ decoded_size,
+ g_free);
+ g_object_set(src->kid, "stream", stream, NULL);
+ g_object_unref(stream);
+
+ if (src->uri) {
+ g_free(src->uri);
+ src->uri = 0;
+ }
+
+ src->uri = g_strdup(uri);
+ ret = TRUE;
+ }
+ }
+
+ g_strfreev(scheme_and_remains);
+ g_strfreev(mime_type_and_options);
+ return ret;
+}
+
+static void webkit_data_src_uri_handler_init(gpointer g_iface, gpointer iface_data)
+{
+ GstURIHandlerInterface* iface = (GstURIHandlerInterface *) g_iface;
+
+ iface->get_type = webkit_data_src_uri_get_type;
+ iface->get_protocols = webkit_data_src_uri_get_protocols;
+ iface->get_uri = webkit_data_src_uri_get_uri;
+ iface->set_uri = webkit_data_src_uri_set_uri;
+}
diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.h b/WebCore/platform/graphics/gtk/DataSourceGStreamer.h
new file mode 100644
index 0000000..3e88f63
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/DataSourceGStreamer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef DATA_SOURCE_GSTREAMER_H
+#define DATA_SOURCE_GSTREAMER_H
+
+#include <glib-object.h>
+#include <gst/base/gstbasesrc.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_DATA_SRC (webkit_data_src_get_type ())
+#define WEBKIT_DATA_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_DATA_SRC, WebkitDataSrc))
+#define WEBKIT_DATA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_DATA_SRC, WebkitDataSrcClass))
+#define WEBKIT_IS_DATA_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_DATA_SRC))
+#define WEBKIT_IS_DATA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_DATA_SRC))
+
+typedef struct _WebkitDataSrc WebkitDataSrc;
+typedef struct _WebkitDataSrcClass WebkitDataSrcClass;
+
+
+struct _WebkitDataSrc {
+ GstBin parent;
+
+ /* explicit pointers to stuff used */
+ GstElement* kid;
+ GstPad* pad;
+ gchar* uri;
+};
+
+struct _WebkitDataSrcClass {
+ GstBinClass parent_class;
+};
+
+GType webkit_data_src_get_type(void);
+
+G_END_DECLS
+
+#endif
diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp
index ee86f96..5c320e0 100644
--- a/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -259,7 +259,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
// Re-enable the platform shadow we disabled earlier
if (hasShadow)
- context->setShadow(shadowSize, shadowBlur, shadowColor);
+ context->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace);
// Pango sometimes leaves behind paths we don't want
cairo_new_path(cr);
diff --git a/WebCore/platform/graphics/gtk/FontPlatformData.h b/WebCore/platform/graphics/gtk/FontPlatformData.h
index 2a65f1e..d30b480 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformData.h
+++ b/WebCore/platform/graphics/gtk/FontPlatformData.h
@@ -87,7 +87,7 @@ public:
bool syntheticBold() const { return m_syntheticBold; }
bool syntheticOblique() const { return m_syntheticOblique; }
- void setFont(cairo_t*) const;
+ cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
unsigned hash() const
{
diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp b/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
index f2c5f0c..0b1280e 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
@@ -224,10 +224,8 @@ FontPlatformData::~FontPlatformData()
m_fallbacks = 0;
}
- if (m_scaledFont) {
+ if (m_scaledFont)
cairo_scaled_font_destroy(m_scaledFont);
- m_scaledFont = 0;
- }
}
bool FontPlatformData::isFixedPitch()
@@ -242,13 +240,6 @@ bool FontPlatformData::isFixedPitch()
return false;
}
-void FontPlatformData::setFont(cairo_t* cr) const
-{
- ASSERT(m_scaledFont);
-
- cairo_set_scaled_font(cr, m_scaledFont);
-}
-
bool FontPlatformData::operator==(const FontPlatformData& other) const
{
if (m_pattern == other.m_pattern)
diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp b/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp
index 9ea6811..8a1a5f1 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp
+++ b/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp
@@ -214,13 +214,6 @@ bool FontPlatformData::isFixedPitch()
return pango_font_family_is_monospace(family);
}
-void FontPlatformData::setFont(cairo_t* cr) const
-{
- ASSERT(m_scaledFont);
-
- cairo_set_scaled_font(cr, m_scaledFont);
-}
-
FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
{
// Check for self-assignment.
diff --git a/WebCore/platform/graphics/gtk/IconGtk.cpp b/WebCore/platform/graphics/gtk/IconGtk.cpp
index e08c1ab..3563a59 100644
--- a/WebCore/platform/graphics/gtk/IconGtk.cpp
+++ b/WebCore/platform/graphics/gtk/IconGtk.cpp
@@ -87,23 +87,25 @@ static String lookupIconName(String MIMEType)
return GTK_STOCK_FILE;
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
- if (!g_path_skip_root(filename.utf8().data()))
+ if (filenames.isEmpty())
return 0;
- String MIMEType = MIMETypeRegistry::getMIMETypeForPath(filename);
- String iconName = lookupIconName(MIMEType);
+ if (filenames.size() == 1) {
+ if (!g_path_skip_root(filenames[0].utf8().data()))
+ return 0;
- RefPtr<Icon> icon = adoptRef(new Icon);
- icon->m_icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), iconName.utf8().data(), 16, GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
- if (!icon->m_icon)
- return 0;
- return icon.release();
-}
+ String MIMEType = MIMETypeRegistry::getMIMETypeForPath(filenames[0]);
+ String iconName = lookupIconName(MIMEType);
+
+ RefPtr<Icon> icon = adoptRef(new Icon);
+ icon->m_icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), iconName.utf8().data(), 16, GTK_ICON_LOOKUP_USE_BUILTIN, 0);
+ if (!icon->m_icon)
+ return 0;
+ return icon.release();
+ }
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
-{
//FIXME: Implement this
return 0;
}
diff --git a/WebCore/platform/graphics/gtk/ImageGtk.cpp b/WebCore/platform/graphics/gtk/ImageGtk.cpp
index 0e92d6c..38da70d 100644
--- a/WebCore/platform/graphics/gtk/ImageGtk.cpp
+++ b/WebCore/platform/graphics/gtk/ImageGtk.cpp
@@ -88,26 +88,67 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name)
return img.release();
}
+static inline unsigned char* getCairoSurfacePixel(unsigned char* data, uint x, uint y, uint rowStride)
+{
+ return data + (y * rowStride) + x * 4;
+}
+
+static inline guchar* getGdkPixbufPixel(guchar* data, uint x, uint y, uint rowStride)
+{
+ return data + (y * rowStride) + x * 4;
+}
+
GdkPixbuf* BitmapImage::getGdkPixbuf()
{
int width = cairo_image_surface_get_width(frameAtIndex(currentFrame()));
int height = cairo_image_surface_get_height(frameAtIndex(currentFrame()));
-
- int bestDepth = gdk_visual_get_best_depth();
- GdkColormap* cmap = gdk_colormap_new(gdk_visual_get_best_with_depth(bestDepth), true);
-
- GdkPixmap* pixmap = gdk_pixmap_new(0, width, height, bestDepth);
- gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap), cmap);
- cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(pixmap));
- cairo_set_source_surface(cr, frameAtIndex(currentFrame()), 0, 0);
- cairo_paint(cr);
- cairo_destroy(cr);
-
- GdkPixbuf* pixbuf = gdk_pixbuf_get_from_drawable(0, GDK_DRAWABLE(pixmap), 0, 0, 0, 0, 0, width, height);
- g_object_unref(pixmap);
- g_object_unref(cmap);
-
- return pixbuf;
+ unsigned char* surfaceData = cairo_image_surface_get_data(frameAtIndex(currentFrame()));
+ int surfaceRowStride = cairo_image_surface_get_stride(frameAtIndex(currentFrame()));
+
+ GdkPixbuf* dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+ if (!dest)
+ return 0;
+
+ guchar* pixbufData = gdk_pixbuf_get_pixels(dest);
+ int pixbufRowStride = gdk_pixbuf_get_rowstride(dest);
+
+ /* From: http://cairographics.org/manual/cairo-image-surface.html#cairo-format-t
+ * "CAIRO_FORMAT_ARGB32: each pixel is a 32-bit quantity, with alpha in
+ * the upper 8 bits, then red, then green, then blue. The 32-bit
+ * quantities are stored native-endian. Pre-multiplied alpha is used.
+ * (That is, 50% transparent red is 0x80800000, not 0x80ff0000.)"
+ *
+ * See http://developer.gimp.org/api/2.0/gdk-pixbuf/gdk-pixbuf-gdk-pixbuf.html#GdkPixbuf
+ * for information on the structure of GdkPixbufs stored with GDK_COLORSPACE_RGB.
+ *
+ * RGB color channels in CAIRO_FORMAT_ARGB32 are stored based on the
+ * endianness of the machine and are also multiplied by the alpha channel.
+ * To properly transfer the data from the Cairo surface we must divide each
+ * of the RGB channels by the alpha channel and then reorder all channels
+ * if this machine is little-endian.
+ */
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ unsigned char* source = getCairoSurfacePixel(surfaceData, x, y, surfaceRowStride);
+ guchar* dest = getGdkPixbufPixel(pixbufData, x, y, pixbufRowStride);
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ guchar alpha = source[3];
+ dest[0] = alpha ? ((source[2] * 255) / alpha) : 0;
+ dest[1] = alpha ? ((source[1] * 255) / alpha) : 0;
+ dest[2] = alpha ? ((source[0] * 255) / alpha) : 0;
+ dest[3] = alpha;
+#else
+ guchar alpha = source[0];
+ dest[0] = alpha ? ((source[1] * 255) / alpha) : 0;
+ dest[1] = alpha ? ((source[2] * 255) / alpha) : 0;
+ dest[2] = alpha ? ((source[3] * 255) / alpha) : 0;
+ dest[3] = alpha;
+#endif
+ }
+ }
+
+ return dest;
}
}
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
index 4e4bda9..a023dae 100644
--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
@@ -2,6 +2,7 @@
* Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Collabora Ltd. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,7 +26,9 @@
#include "MediaPlayerPrivateGStreamer.h"
+
#include "CString.h"
+#include "DataSourceGStreamer.h"
#include "GraphicsContext.h"
#include "IntRect.h"
#include "KURL.h"
@@ -33,71 +36,100 @@
#include "MediaPlayer.h"
#include "NotImplemented.h"
#include "ScrollView.h"
+#include "TimeRanges.h"
#include "VideoSinkGStreamer.h"
#include "Widget.h"
-#include <gst/base/gstbasesrc.h>
#include <gst/gst.h>
#include <gst/interfaces/mixer.h>
#include <gst/interfaces/xoverlay.h>
#include <gst/video/video.h>
#include <limits>
#include <math.h>
-#include <wtf/GOwnPtr.h>
+#include <wtf/gtk/GOwnPtr.h>
using namespace std;
namespace WebCore {
-gboolean mediaPlayerPrivateErrorCallback(GstBus* bus, GstMessage* message, gpointer data)
+gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data)
{
- if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_ERROR) {
- GOwnPtr<GError> err;
- GOwnPtr<gchar> debug;
+ GOwnPtr<GError> err;
+ GOwnPtr<gchar> debug;
+ MediaPlayer::NetworkState error;
+ MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
+ gint percent = 0;
+ switch (GST_MESSAGE_TYPE(message)) {
+ case GST_MESSAGE_ERROR:
gst_message_parse_error(message, &err.outPtr(), &debug.outPtr());
- if (err->code == 3) {
- LOG_VERBOSE(Media, "File not found");
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
- if (mp)
- mp->loadingFailed();
- } else
- LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message);
- }
- return true;
-}
-
-gboolean mediaPlayerPrivateEOSCallback(GstBus* bus, GstMessage* message, gpointer data)
-{
- if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_EOS) {
+ LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message);
+
+ error = MediaPlayer::Empty;
+ if (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND
+ || err->code == GST_STREAM_ERROR_WRONG_TYPE
+ || err->code == GST_STREAM_ERROR_FAILED
+ || err->code == GST_CORE_ERROR_MISSING_PLUGIN
+ || err->code == GST_RESOURCE_ERROR_NOT_FOUND)
+ error = MediaPlayer::FormatError;
+ else if (err->domain == GST_STREAM_ERROR)
+ error = MediaPlayer::DecodeError;
+ else if (err->domain == GST_RESOURCE_ERROR)
+ error = MediaPlayer::NetworkError;
+
+ if (mp)
+ mp->loadingFailed(error);
+ break;
+ case GST_MESSAGE_EOS:
LOG_VERBOSE(Media, "End of Stream");
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
mp->didEnd();
- }
- return true;
-}
-
-gboolean mediaPlayerPrivateStateCallback(GstBus* bus, GstMessage* message, gpointer data)
-{
- if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_STATE_CHANGED) {
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
+ break;
+ case GST_MESSAGE_STATE_CHANGED:
mp->updateStates();
+ break;
+ case GST_MESSAGE_BUFFERING:
+ gst_message_parse_buffering(message, &percent);
+ LOG_VERBOSE(Media, "Buffering %d", percent);
+ break;
+ default:
+ LOG_VERBOSE(Media, "Unhandled GStreamer message type: %s",
+ GST_MESSAGE_TYPE_NAME(message));
+ break;
}
return true;
}
-gboolean mediaPlayerPrivateBufferingCallback(GstBus* bus, GstMessage* message, gpointer data)
+static float playbackPosition(GstElement* playbin)
{
- if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_BUFFERING) {
- gint percent = 0;
- gst_message_parse_buffering(message, &percent);
- LOG_VERBOSE(Media, "Buffering %d", percent);
+
+ float ret = 0.0;
+
+ GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
+ if (!gst_element_query(playbin, query)) {
+ LOG_VERBOSE(Media, "Position query failed...");
+ gst_query_unref(query);
+ return ret;
}
- return true;
+
+ gint64 position;
+ gst_query_parse_position(query, 0, &position);
+
+ // Position is available only if the pipeline is not in NULL or
+ // READY state.
+ if (position != static_cast<gint64>(GST_CLOCK_TIME_NONE))
+ ret = static_cast<float>(position) / static_cast<float>(GST_SECOND);
+
+ LOG_VERBOSE(Media, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
+
+ gst_query_unref(query);
+
+ return ret;
}
-static void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, MediaPlayerPrivate* playerPrivate)
+void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivate* playerPrivate)
{
+ g_return_if_fail(GST_IS_BUFFER(buffer));
+ gst_buffer_replace(&playerPrivate->m_buffer, buffer);
playerPrivate->repaint();
}
@@ -112,43 +144,74 @@ void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar)
registrar(create, getSupportedTypes, supportsType);
}
+static bool gstInitialized = false;
+
+static bool do_gst_init()
+{
+ // FIXME: We should pass the arguments from the command line
+ if (!gstInitialized) {
+ GOwnPtr<GError> error;
+ gstInitialized = gst_init_check(0, 0, &error.outPtr());
+ if (!gstInitialized)
+ LOG_VERBOSE(Media, "Could not initialize GStreamer: %s",
+ error ? error->message : "unknown error occurred");
+ else
+ gst_element_register(0, "webkitmediasrc", GST_RANK_PRIMARY,
+ WEBKIT_TYPE_DATA_SRC);
+
+ }
+ return gstInitialized;
+}
+
+bool MediaPlayerPrivate::isAvailable()
+{
+ if (!do_gst_init())
+ return false;
+
+ GstElementFactory* factory = gst_element_factory_find("playbin2");
+ if (factory) {
+ gst_object_unref(GST_OBJECT(factory));
+ return true;
+ }
+ return false;
+}
+
MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
: m_player(player)
, m_playBin(0)
, m_videoSink(0)
, m_source(0)
- , m_rate(1.0f)
+ , m_seekTime(0)
+ , m_changingRate(false)
, m_endTime(numeric_limits<float>::infinity())
- , m_isEndReached(false)
- , m_volume(0.5f)
, m_networkState(MediaPlayer::Empty)
, m_readyState(MediaPlayer::HaveNothing)
, m_startedPlaying(false)
, m_isStreaming(false)
, m_size(IntSize())
- , m_visible(true)
+ , m_buffer(0)
+ , m_paused(true)
+ , m_seeking(false)
+ , m_errorOccured(false)
{
-
- static bool gstInitialized = false;
- // FIXME: We should pass the arguments from the command line
- if (!gstInitialized) {
- gst_init(0, 0);
- gstInitialized = true;
- }
-
- // FIXME: The size shouldn't be fixed here, this is just a quick hack.
- m_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 640, 480);
+ do_gst_init();
}
MediaPlayerPrivate::~MediaPlayerPrivate()
{
- if (m_surface)
- cairo_surface_destroy(m_surface);
+ if (m_buffer)
+ gst_buffer_unref(m_buffer);
+ m_buffer = 0;
if (m_playBin) {
gst_element_set_state(m_playBin, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(m_playBin));
}
+
+ if (m_videoSink) {
+ g_object_unref(m_videoSink);
+ m_videoSink = 0;
+ }
}
void MediaPlayerPrivate::load(const String& url)
@@ -169,21 +232,26 @@ void MediaPlayerPrivate::load(const String& url)
void MediaPlayerPrivate::play()
{
- LOG_VERBOSE(Media, "Play");
- // When end reached, rewind for Test video-seek-past-end-playing
- if (m_isEndReached)
- seek(0);
- m_isEndReached = false;
+ GstState state;
+ GstState pending;
- gst_element_set_state(m_playBin, GST_STATE_PLAYING);
- m_startedPlaying = true;
+ gst_element_get_state(m_playBin, &state, &pending, 0);
+ if (state != GST_STATE_PLAYING && pending != GST_STATE_PLAYING) {
+ LOG_VERBOSE(Media, "Play");
+ gst_element_set_state(m_playBin, GST_STATE_PLAYING);
+ }
}
void MediaPlayerPrivate::pause()
{
- LOG_VERBOSE(Media, "Pause");
- gst_element_set_state(m_playBin, GST_STATE_PAUSED);
- m_startedPlaying = false;
+ GstState state;
+ GstState pending;
+
+ gst_element_get_state(m_playBin, &state, &pending, 0);
+ if (state != GST_STATE_PAUSED && pending != GST_STATE_PAUSED) {
+ LOG_VERBOSE(Media, "Pause");
+ gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ }
}
float MediaPlayerPrivate::duration() const
@@ -191,23 +259,20 @@ float MediaPlayerPrivate::duration() const
if (!m_playBin)
return 0.0;
+ if (m_errorOccured)
+ return 0.0;
+
GstFormat timeFormat = GST_FORMAT_TIME;
gint64 timeLength = 0;
- // FIXME: We try to get the duration, but we do not trust the
- // return value of the query function only; the problem we are
- // trying to work-around here is that pipelines in stream mode may
- // not be able to figure out the duration, but still return true!
- // See https://bugs.webkit.org/show_bug.cgi?id=24639.
- if (!gst_element_query_duration(m_playBin, &timeFormat, &timeLength) || timeLength <= 0) {
+ if (!gst_element_query_duration(m_playBin, &timeFormat, &timeLength) || timeFormat != GST_FORMAT_TIME || static_cast<guint64>(timeLength) == GST_CLOCK_TIME_NONE) {
LOG_VERBOSE(Media, "Time duration query failed.");
- m_isStreaming = true;
return numeric_limits<float>::infinity();
}
LOG_VERBOSE(Media, "Duration: %" GST_TIME_FORMAT, GST_TIME_ARGS(timeLength));
- return (float) (timeLength / 1000000000.0);
+ return (float) ((guint64) timeLength / 1000000000.0);
// FIXME: handle 3.14.9.5 properly
}
@@ -215,25 +280,15 @@ float MediaPlayerPrivate::currentTime() const
{
if (!m_playBin)
return 0;
- // Necessary as sometimes, gstreamer return 0:00 at the EOS
- if (m_isEndReached)
- return m_endTime;
- float ret;
+ if (m_errorOccured)
+ return 0;
- GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
- if (gst_element_query(m_playBin, query)) {
- gint64 position;
- gst_query_parse_position(query, 0, &position);
- ret = (float) (position / 1000000000.0);
- LOG_VERBOSE(Media, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
- } else {
- LOG_VERBOSE(Media, "Position query failed...");
- ret = 0.0;
- }
- gst_query_unref(query);
+ if (m_seeking)
+ return m_seekTime;
+
+ return playbackPosition(m_playBin);
- return ret;
}
void MediaPlayerPrivate::seek(float time)
@@ -246,35 +301,25 @@ void MediaPlayerPrivate::seek(float time)
if (m_isStreaming)
return;
+ if (m_errorOccured)
+ return;
+
LOG_VERBOSE(Media, "Seek: %" GST_TIME_FORMAT, GST_TIME_ARGS(sec));
- // FIXME: What happens when the seeked position is not available?
- if (!gst_element_seek( m_playBin, m_rate,
+ if (!gst_element_seek(m_playBin, m_player->rate(),
GST_FORMAT_TIME,
(GstSeekFlags)(GST_SEEK_FLAG_FLUSH),
GST_SEEK_TYPE_SET, sec,
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
LOG_VERBOSE(Media, "Seek to %f failed", time);
+ else {
+ m_seeking = true;
+ m_seekTime = sec;
+ }
}
void MediaPlayerPrivate::setEndTime(float time)
{
- if (!m_playBin)
- return;
- if (m_isStreaming)
- return;
- if (m_endTime != time) {
- m_endTime = time;
- GstClockTime start = (GstClockTime)(currentTime() * GST_SECOND);
- GstClockTime end = (GstClockTime)(time * GST_SECOND);
- LOG_VERBOSE(Media, "setEndTime: %" GST_TIME_FORMAT, GST_TIME_ARGS(end));
- // FIXME: What happens when the seeked position is not available?
- if (!gst_element_seek(m_playBin, m_rate,
- GST_FORMAT_TIME,
- (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
- GST_SEEK_TYPE_SET, start,
- GST_SEEK_TYPE_SET, end))
- LOG_VERBOSE(Media, "Seek to %f failed", time);
- }
+ notImplemented();
}
void MediaPlayerPrivate::startEndPointTimerIfNeeded()
@@ -294,12 +339,12 @@ void MediaPlayerPrivate::endPointTimerFired(Timer<MediaPlayerPrivate>*)
bool MediaPlayerPrivate::paused() const
{
- return !m_startedPlaying;
+ return m_paused;
}
bool MediaPlayerPrivate::seeking() const
{
- return false;
+ return m_seeking;
}
// Returns the size of the video
@@ -308,13 +353,31 @@ IntSize MediaPlayerPrivate::naturalSize() const
if (!hasVideo())
return IntSize();
- int x = 0, y = 0;
+ // TODO: handle possible clean aperture data. See
+ // https://bugzilla.gnome.org/show_bug.cgi?id=596571
+ // TODO: handle possible transformation matrix. See
+ // https://bugzilla.gnome.org/show_bug.cgi?id=596326
+ int width = 0, height = 0;
if (GstPad* pad = gst_element_get_static_pad(m_videoSink, "sink")) {
- gst_video_get_size(GST_PAD(pad), &x, &y);
+ GstCaps* caps = GST_PAD_CAPS(pad);
+ gfloat pixelAspectRatio;
+ gint pixelAspectRatioNumerator, pixelAspectRatioDenominator;
+
+ if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps)
+ || !gst_video_format_parse_caps(caps, 0, &width, &height)
+ || !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
+ &pixelAspectRatioDenominator)) {
+ gst_object_unref(GST_OBJECT(pad));
+ return IntSize();
+ }
+
+ pixelAspectRatio = (gfloat) pixelAspectRatioNumerator / (gfloat) pixelAspectRatioDenominator;
+ width *= pixelAspectRatio;
+ height /= pixelAspectRatio;
gst_object_unref(GST_OBJECT(pad));
}
- return IntSize(x, y);
+ return IntSize(width, height);
}
bool MediaPlayerPrivate::hasVideo() const
@@ -325,43 +388,68 @@ bool MediaPlayerPrivate::hasVideo() const
return currentVideo > -1;
}
-void MediaPlayerPrivate::setVolume(float volume)
+bool MediaPlayerPrivate::hasAudio() const
{
- m_volume = volume;
- LOG_VERBOSE(Media, "Volume to %f", volume);
- setMuted(false);
+ gint currentAudio = -1;
+ if (m_playBin)
+ g_object_get(G_OBJECT(m_playBin), "current-audio", &currentAudio, NULL);
+ return currentAudio > -1;
}
-void MediaPlayerPrivate::setMuted(bool b)
+void MediaPlayerPrivate::setVolume(float volume)
{
if (!m_playBin)
return;
- if (b) {
- g_object_get(G_OBJECT(m_playBin), "volume", &m_volume, NULL);
- g_object_set(G_OBJECT(m_playBin), "volume", (double)0.0, NULL);
- } else
- g_object_set(G_OBJECT(m_playBin), "volume", m_volume, NULL);
-
+ g_object_set(G_OBJECT(m_playBin), "volume", static_cast<double>(volume), NULL);
}
void MediaPlayerPrivate::setRate(float rate)
{
- if (rate == 0.0) {
- gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ GstState state;
+ GstState pending;
+
+ gst_element_get_state(m_playBin, &state, &pending, 0);
+ if ((state != GST_STATE_PLAYING && state != GST_STATE_PAUSED)
+ || (pending == GST_STATE_PAUSED))
return;
- }
+
if (m_isStreaming)
return;
- m_rate = rate;
+ m_changingRate = true;
+ float currentPosition = playbackPosition(m_playBin) * GST_SECOND;
+ GstSeekFlags flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH);
+ gint64 start, end;
+ bool mute = false;
+
LOG_VERBOSE(Media, "Set Rate to %f", rate);
- if (!gst_element_seek(m_playBin, rate,
- GST_FORMAT_TIME,
- (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
- GST_SEEK_TYPE_SET, (GstClockTime) (currentTime() * GST_SECOND),
- GST_SEEK_TYPE_SET, (GstClockTime) (m_endTime * GST_SECOND)))
- LOG_VERBOSE(Media, "Set Rate to %f failed", rate);
+ if (rate >= 0) {
+ // Mute the sound if the playback rate is too extreme.
+ // TODO: in other cases we should perform pitch adjustments.
+ mute = (bool) (rate < 0.8 || rate > 2);
+ start = currentPosition;
+ end = GST_CLOCK_TIME_NONE;
+ } else {
+ start = 0;
+ mute = true;
+
+ // If we are at beginning of media, start from the end to
+ // avoid immediate EOS.
+ if (currentPosition <= 0)
+ end = duration() * GST_SECOND;
+ else
+ end = currentPosition;
+ }
+
+ LOG_VERBOSE(Media, "Need to mute audio: %d", (int) mute);
+
+ if (!gst_element_seek(m_playBin, rate, GST_FORMAT_TIME, flags,
+ GST_SEEK_TYPE_SET, start,
+ GST_SEEK_TYPE_SET, end))
+ LOG_VERBOSE(Media, "Set rate to %f failed", rate);
+ else
+ g_object_set(m_playBin, "mute", mute, NULL);
}
int MediaPlayerPrivate::dataRate() const
@@ -380,16 +468,20 @@ MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const
return m_readyState;
}
-float MediaPlayerPrivate::maxTimeBuffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
- notImplemented();
- LOG_VERBOSE(Media, "maxTimeBuffered");
- // rtsp streams are not buffered
- return m_isStreaming ? 0 : maxTimeLoaded();
+ RefPtr<TimeRanges> timeRanges = TimeRanges::create();
+ float loaded = maxTimeLoaded();
+ if (!m_errorOccured && !m_isStreaming && loaded > 0)
+ timeRanges->add(0, loaded);
+ return timeRanges.release();
}
float MediaPlayerPrivate::maxTimeSeekable() const
{
+ if (m_errorOccured)
+ return 0.0;
+
// TODO
LOG_VERBOSE(Media, "maxTimeSeekable");
if (m_isStreaming)
@@ -400,6 +492,9 @@ float MediaPlayerPrivate::maxTimeSeekable() const
float MediaPlayerPrivate::maxTimeLoaded() const
{
+ if (m_errorOccured)
+ return 0.0;
+
// TODO
LOG_VERBOSE(Media, "maxTimeLoaded");
notImplemented();
@@ -416,34 +511,39 @@ unsigned MediaPlayerPrivate::bytesLoaded() const
float maxTime = maxTimeLoaded();
if (!dur)
return 0;*/
+
return 1;//totalBytes() * maxTime / dur;
}
bool MediaPlayerPrivate::totalBytesKnown() const
{
- notImplemented();
LOG_VERBOSE(Media, "totalBytesKnown");
return totalBytes() > 0;
}
unsigned MediaPlayerPrivate::totalBytes() const
{
- notImplemented();
LOG_VERBOSE(Media, "totalBytes");
- if (!m_playBin)
+ if (!m_source)
return 0;
- if (!m_source)
+ if (m_errorOccured)
return 0;
- // Do something with m_source to get the total bytes of the media
+ GstFormat fmt = GST_FORMAT_BYTES;
+ gint64 length = 0;
+ gst_element_query_duration(m_source, &fmt, &length);
- return 100;
+ return length;
}
void MediaPlayerPrivate::cancelLoad()
{
- notImplemented();
+ if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded)
+ return;
+
+ if (m_playBin)
+ gst_element_set_state(m_playBin, GST_STATE_NULL);
}
void MediaPlayerPrivate::updateStates()
@@ -452,27 +552,47 @@ void MediaPlayerPrivate::updateStates()
// the state of GStreamer, therefore, when in PAUSED state,
// we are sure we can display the first frame and go to play
+ if (!m_playBin)
+ return;
+
+ if (m_errorOccured)
+ return;
+
MediaPlayer::NetworkState oldNetworkState = m_networkState;
MediaPlayer::ReadyState oldReadyState = m_readyState;
GstState state;
GstState pending;
- if (!m_playBin)
- return;
-
GstStateChangeReturn ret = gst_element_get_state(m_playBin,
&state, &pending, 250 * GST_NSECOND);
+ bool shouldUpdateAfterSeek = false;
switch (ret) {
case GST_STATE_CHANGE_SUCCESS:
LOG_VERBOSE(Media, "State: %s, pending: %s",
gst_element_state_get_name(state),
gst_element_state_get_name(pending));
- if (state == GST_STATE_READY) {
+ if (state == GST_STATE_READY)
+ m_readyState = MediaPlayer::HaveNothing;
+ else if (state == GST_STATE_PAUSED)
m_readyState = MediaPlayer::HaveEnoughData;
- } else if (state == GST_STATE_PAUSED)
+
+ if (state == GST_STATE_PLAYING) {
m_readyState = MediaPlayer::HaveEnoughData;
+ m_paused = false;
+ } else
+ m_paused = true;
+
+ if (m_changingRate) {
+ m_player->rateChanged();
+ m_changingRate = false;
+ }
+
+ if (m_seeking) {
+ shouldUpdateAfterSeek = true;
+ m_seeking = false;
+ }
m_networkState = MediaPlayer::Loaded;
@@ -486,14 +606,20 @@ void MediaPlayerPrivate::updateStates()
gst_element_state_get_name(pending));
// Change in progress
return;
- break;
+ case GST_STATE_CHANGE_FAILURE:
+ LOG_VERBOSE(Media, "Failure: State: %s, pending: %s",
+ gst_element_state_get_name(state),
+ gst_element_state_get_name(pending));
+ // Change failed
+ return;
case GST_STATE_CHANGE_NO_PREROLL:
LOG_VERBOSE(Media, "No preroll: State: %s, pending: %s",
gst_element_state_get_name(state),
gst_element_state_get_name(pending));
- if (state == GST_STATE_READY) {
- m_readyState = MediaPlayer::HaveFutureData;
- } else if (state == GST_STATE_PAUSED)
+
+ if (state == GST_STATE_READY)
+ m_readyState = MediaPlayer::HaveNothing;
+ else if (state == GST_STATE_PAUSED)
m_readyState = MediaPlayer::HaveCurrentData;
m_networkState = MediaPlayer::Loading;
@@ -506,6 +632,9 @@ void MediaPlayerPrivate::updateStates()
if (seeking())
m_readyState = MediaPlayer::HaveNothing;
+ if (shouldUpdateAfterSeek)
+ timeChanged();
+
if (m_networkState != oldNetworkState) {
LOG_VERBOSE(Media, "Network State Changed from %u to %u",
oldNetworkState, m_networkState);
@@ -523,11 +652,6 @@ void MediaPlayerPrivate::loadStateChanged()
updateStates();
}
-void MediaPlayerPrivate::rateChanged()
-{
- updateStates();
-}
-
void MediaPlayerPrivate::sizeChanged()
{
notImplemented();
@@ -546,15 +670,14 @@ void MediaPlayerPrivate::volumeChanged()
void MediaPlayerPrivate::didEnd()
{
- m_isEndReached = true;
- pause();
timeChanged();
}
-void MediaPlayerPrivate::loadingFailed()
+void MediaPlayerPrivate::loadingFailed(MediaPlayer::NetworkState error)
{
- if (m_networkState != MediaPlayer::NetworkError) {
- m_networkState = MediaPlayer::NetworkError;
+ m_errorOccured = true;
+ if (m_networkState != error) {
+ m_networkState = error;
m_player->networkStateChanged();
}
if (m_readyState != MediaPlayer::HaveNothing) {
@@ -570,7 +693,6 @@ void MediaPlayerPrivate::setSize(const IntSize& size)
void MediaPlayerPrivate::setVisible(bool visible)
{
- m_visible = visible;
}
void MediaPlayerPrivate::repaint()
@@ -583,62 +705,199 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
if (context->paintingDisabled())
return;
- if (!m_visible)
+ if (!m_player->visible())
+ return;
+ if (!m_buffer)
return;
- //TODO: m_size vs rect?
+ int width = 0, height = 0;
+ GstCaps *caps = gst_buffer_get_caps(m_buffer);
+ GstVideoFormat format;
+
+ if (!gst_video_format_parse_caps(caps, &format, &width, &height)) {
+ gst_caps_unref(caps);
+ return;
+ }
+
+ cairo_format_t cairoFormat;
+ if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA)
+ cairoFormat = CAIRO_FORMAT_ARGB32;
+ else
+ cairoFormat = CAIRO_FORMAT_RGB24;
+
cairo_t* cr = context->platformContext();
+ cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(m_buffer),
+ cairoFormat,
+ width, height,
+ 4 * width);
cairo_save(cr);
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+
+ // translate and scale the context to correct size
cairo_translate(cr, rect.x(), rect.y());
- cairo_rectangle(cr, 0, 0, rect.width(), rect.height());
- cairo_set_source_surface(cr, m_surface, 0, 0);
+ cairo_scale(cr, static_cast<double>(rect.width()) / width, static_cast<double>(rect.height()) / height);
+
+ // And paint it.
+ cairo_set_source_surface(cr, src, 0, 0);
+ cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_PAD);
+ cairo_rectangle(cr, 0, 0, width, height);
cairo_fill(cr);
cairo_restore(cr);
+
+ cairo_surface_destroy(src);
+ gst_caps_unref(caps);
+}
+
+static HashSet<String> mimeTypeCache()
+{
+
+ do_gst_init();
+
+ static HashSet<String> cache;
+ static bool typeListInitialized = false;
+
+ if (!typeListInitialized) {
+ // Build a whitelist of mime-types known to be supported by
+ // GStreamer.
+ HashSet<String> handledApplicationSubtypes;
+ handledApplicationSubtypes.add(String("ogg"));
+ handledApplicationSubtypes.add(String("x-3gp"));
+ handledApplicationSubtypes.add(String("vnd.rn-realmedia"));
+ handledApplicationSubtypes.add(String("x-pn-realaudio"));
+
+ GList* factories = gst_type_find_factory_get_list();
+ for (GList* iterator = factories; iterator; iterator = iterator->next) {
+ GstTypeFindFactory* factory = GST_TYPE_FIND_FACTORY(iterator->data);
+ GstCaps* caps = gst_type_find_factory_get_caps(factory);
+
+ if (!caps)
+ continue;
+
+ for (guint structureIndex = 0; structureIndex < gst_caps_get_size(caps); structureIndex++) {
+ GstStructure* structure = gst_caps_get_structure(caps, structureIndex);
+ const gchar* name = gst_structure_get_name(structure);
+ bool cached = false;
+
+ // These formats are supported by GStreamer, but not
+ // correctly advertised.
+ if (g_str_equal(name, "video/x-h264")
+ || g_str_equal(name, "audio/x-m4a")) {
+ cache.add(String("video/mp4"));
+ cache.add(String("audio/aac"));
+ cached = true;
+ }
+
+ if (g_str_equal(name, "video/x-theora")) {
+ cache.add(String("video/ogg"));
+ cached = true;
+ }
+
+ if (g_str_equal(name, "audio/x-vorbis")) {
+ cache.add(String("audio/ogg"));
+ cached = true;
+ }
+
+ if (g_str_equal(name, "audio/x-wav")) {
+ cache.add(String("audio/wav"));
+ cached = true;
+ }
+
+ if (g_str_equal(name, "audio/mpeg")) {
+ cache.add(String(name));
+ cached = true;
+
+ // This is what we are handling:
+ // mpegversion=(int)1, layer=(int)[ 1, 3 ]
+ gint mpegVersion = 0;
+ if (gst_structure_get_int(structure, "mpegversion", &mpegVersion) && (mpegVersion == 1)) {
+ const GValue* layer = gst_structure_get_value(structure, "layer");
+ if (G_VALUE_TYPE(layer) == GST_TYPE_INT_RANGE) {
+ gint minLayer = gst_value_get_int_range_min(layer);
+ gint maxLayer = gst_value_get_int_range_max(layer);
+ if (minLayer <= 1 <= maxLayer)
+ cache.add(String("audio/mp1"));
+ if (minLayer <= 2 <= maxLayer)
+ cache.add(String("audio/mp2"));
+ if (minLayer <= 3 <= maxLayer)
+ cache.add(String("audio/mp3"));
+ }
+ }
+ }
+
+ if (!cached) {
+ // GStreamer plugins can be capable of supporting
+ // types which WebKit supports by default. In that
+ // case, we should not consider these types
+ // supportable by GStreamer. Examples of what
+ // GStreamer can support but should not be added:
+ // text/plain, text/html, image/jpeg,
+ // application/xml
+ gchar** mimetype = g_strsplit(name, "/", 2);
+ if (g_str_equal(mimetype[0], "audio")
+ || g_str_equal(mimetype[0], "video")
+ || (g_str_equal(mimetype[0], "application")
+ && handledApplicationSubtypes.contains(String(mimetype[1]))))
+ cache.add(String(name));
+
+ g_strfreev(mimetype);
+ }
+ }
+ }
+
+ gst_plugin_feature_list_free(factories);
+ typeListInitialized = true;
+ }
+
+ return cache;
}
void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
{
- // FIXME: query the engine to see what types are supported
- notImplemented();
- types.add(String("video/x-theora+ogg"));
+ types = mimeTypeCache();
}
MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
{
- // FIXME: query the engine to see what types are supported
- notImplemented();
- return type == "video/x-theora+ogg" ? (codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported) : MediaPlayer::IsNotSupported;
+ if (type.isNull() || type.isEmpty())
+ return MediaPlayer::IsNotSupported;
+
+ // spec says we should not return "probably" if the codecs string is empty
+ if (mimeTypeCache().contains(type))
+ return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
+ return MediaPlayer::IsNotSupported;
+}
+
+bool MediaPlayerPrivate::hasSingleSecurityOrigin() const
+{
+ return true;
+}
+
+bool MediaPlayerPrivate::supportsFullscreen() const
+{
+ return true;
}
void MediaPlayerPrivate::createGSTPlayBin(String url)
{
ASSERT(!m_playBin);
- m_playBin = gst_element_factory_make("playbin", "play");
+ m_playBin = gst_element_factory_make("playbin2", "play");
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(m_playBin));
gst_bus_add_signal_watch(bus);
- g_signal_connect(bus, "message::error", G_CALLBACK(mediaPlayerPrivateErrorCallback), this);
- g_signal_connect(bus, "message::eos", G_CALLBACK(mediaPlayerPrivateEOSCallback), this);
- g_signal_connect(bus, "message::state-changed", G_CALLBACK(mediaPlayerPrivateStateCallback), this);
- g_signal_connect(bus, "message::buffering", G_CALLBACK(mediaPlayerPrivateBufferingCallback), this);
+ g_signal_connect(bus, "message", G_CALLBACK(mediaPlayerPrivateMessageCallback), this);
gst_object_unref(bus);
- g_object_set(G_OBJECT(m_playBin), "uri", url.utf8().data(), NULL);
+ g_object_set(G_OBJECT(m_playBin), "uri", url.utf8().data(),
+ "volume", static_cast<double>(m_player->volume()), NULL);
- GstElement* audioSink = gst_element_factory_make("gconfaudiosink", 0);
- m_videoSink = webkit_video_sink_new(m_surface);
+ m_videoSink = webkit_video_sink_new();
- g_object_set(m_playBin, "audio-sink", audioSink, NULL);
+ g_object_ref_sink(m_videoSink);
g_object_set(m_playBin, "video-sink", m_videoSink, NULL);
g_signal_connect(m_videoSink, "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this);
-
- setVolume(m_volume);
}
}
#endif
-
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
index 8842f84..6ab8edb 100644
--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
@@ -29,9 +29,12 @@
#include <cairo.h>
#include <glib.h>
+#include <gst/gst.h>
-typedef struct _GstElement GstElement;
+typedef struct _WebKitVideoSink WebKitVideoSink;
+typedef struct _GstBuffer GstBuffer;
typedef struct _GstMessage GstMessage;
+typedef struct _GstElement GstElement;
typedef struct _GstBus GstBus;
namespace WebCore {
@@ -41,14 +44,11 @@ namespace WebCore {
class IntRect;
class String;
- gboolean mediaPlayerPrivateErrorCallback(GstBus* bus, GstMessage* message, gpointer data);
- gboolean mediaPlayerPrivateEOSCallback(GstBus* bus, GstMessage* message, gpointer data);
- gboolean mediaPlayerPrivateStateCallback(GstBus* bus, GstMessage* message, gpointer data);
+ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
- friend gboolean mediaPlayerPrivateErrorCallback(GstBus* bus, GstMessage* message, gpointer data);
- friend gboolean mediaPlayerPrivateEOSCallback(GstBus* bus, GstMessage* message, gpointer data);
- friend gboolean mediaPlayerPrivateStateCallback(GstBus* bus, GstMessage* message, gpointer data);
+ friend gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
+ friend void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivate* playerPrivate);
public:
static void registerMediaEngine(MediaEngineRegistrar);
@@ -56,6 +56,7 @@ namespace WebCore {
IntSize naturalSize() const;
bool hasVideo() const;
+ bool hasAudio() const;
void load(const String &url);
void cancelLoad();
@@ -73,14 +74,13 @@ namespace WebCore {
void setRate(float);
void setVolume(float);
- void setMuted(bool);
int dataRate() const;
MediaPlayer::NetworkState networkState() const;
MediaPlayer::ReadyState readyState() const;
- float maxTimeBuffered() const;
+ PassRefPtr<TimeRanges> buffered() const;
float maxTimeSeekable() const;
unsigned bytesLoaded() const;
bool totalBytesKnown() const;
@@ -90,23 +90,26 @@ namespace WebCore {
void setSize(const IntSize&);
void loadStateChanged();
- void rateChanged();
void sizeChanged();
void timeChanged();
void volumeChanged();
void didEnd();
- void loadingFailed();
+ void loadingFailed(MediaPlayer::NetworkState);
void repaint();
void paint(GraphicsContext*, const IntRect&);
+ bool hasSingleSecurityOrigin() const;
+
+ bool supportsFullscreen() const;
+
private:
MediaPlayerPrivate(MediaPlayer*);
static MediaPlayerPrivateInterface* create(MediaPlayer* player);
static void getSupportedTypes(HashSet<String>&);
static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
- static bool isAvailable() { return true; }
+ static bool isAvailable();
void updateStates();
void cancelSeek();
@@ -121,17 +124,20 @@ namespace WebCore {
GstElement* m_playBin;
GstElement* m_videoSink;
GstElement* m_source;
- float m_rate;
+ GstClockTime m_seekTime;
+ bool m_changingRate;
float m_endTime;
bool m_isEndReached;
- double m_volume;
MediaPlayer::NetworkState m_networkState;
MediaPlayer::ReadyState m_readyState;
bool m_startedPlaying;
mutable bool m_isStreaming;
IntSize m_size;
- bool m_visible;
- cairo_surface_t* m_surface;
+ GstBuffer* m_buffer;
+
+ bool m_paused;
+ bool m_seeking;
+ bool m_errorOccured;
};
}
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
index a77c1cf..df25393 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
@@ -39,8 +39,6 @@
#include "FontDescription.h"
#include "GlyphBuffer.h"
#include <cairo.h>
-#include <unicode/uchar.h>
-#include <unicode/unorm.h>
#include <wtf/MathExtras.h>
namespace WebCore {
@@ -50,9 +48,9 @@ void SimpleFontData::platformInit()
cairo_font_extents_t font_extents;
cairo_text_extents_t text_extents;
cairo_scaled_font_extents(m_platformData.m_scaledFont, &font_extents);
- m_ascent = static_cast<int>(font_extents.ascent);
- m_descent = static_cast<int>(font_extents.descent);
- m_lineSpacing = static_cast<int>(font_extents.height);
+ m_ascent = static_cast<int>(lroundf(font_extents.ascent));
+ m_descent = static_cast<int>(lroundf(font_extents.descent));
+ m_lineSpacing = static_cast<int>(lroundf(font_extents.height));
// There seems to be some rounding error in cairo (or in how we
// use cairo) with some fonts, like DejaVu Sans Mono, which makes
// cairo report a height smaller than ascent + descent, which is
@@ -63,7 +61,7 @@ void SimpleFontData::platformInit()
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, "x", &text_extents);
m_xHeight = text_extents.height;
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, " ", &text_extents);
- m_spaceWidth = static_cast<int>(text_extents.x_advance);
+ m_spaceWidth = static_cast<float>(text_extents.x_advance);
m_lineGap = m_lineSpacing - m_ascent - m_descent;
m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
}
@@ -130,10 +128,4 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
return w;
}
-void SimpleFontData::setFont(cairo_t* cr) const
-{
- ASSERT(cr);
- m_platformData.setFont(cr);
-}
-
}
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
index e57d9e6..975143e 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
@@ -49,9 +49,9 @@ void SimpleFontData::platformInit()
cairo_font_extents_t font_extents;
cairo_text_extents_t text_extents;
cairo_scaled_font_extents(m_platformData.m_scaledFont, &font_extents);
- m_ascent = static_cast<int>(font_extents.ascent);
- m_descent = static_cast<int>(font_extents.descent);
- m_lineSpacing = static_cast<int>(font_extents.height);
+ m_ascent = static_cast<int>(lroundf(font_extents.ascent));
+ m_descent = static_cast<int>(lroundf(font_extents.descent));
+ m_lineSpacing = static_cast<int>(lroundf(font_extents.height));
// There seems to be some rounding error in cairo (or in how we
// use cairo) with some fonts, like DejaVu Sans Mono, which makes
// cairo report a height smaller than ascent + descent, which is
@@ -62,7 +62,7 @@ void SimpleFontData::platformInit()
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, "x", &text_extents);
m_xHeight = text_extents.height;
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, " ", &text_extents);
- m_spaceWidth = static_cast<int>(text_extents.x_advance);
+ m_spaceWidth = static_cast<float>(text_extents.x_advance);
m_lineGap = m_lineSpacing - m_ascent - m_descent;
m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
}
@@ -133,10 +133,4 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
return w;
}
-void SimpleFontData::setFont(cairo_t* cr) const
-{
- ASSERT(cr);
- m_platformData.setFont(cr);
-}
-
}
diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
index f049998..5e0f8e2 100644
--- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
+++ b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
@@ -21,8 +21,9 @@
* SECTION:webkit-video-sink
* @short_description: GStreamer video sink
*
- * #WebKitVideoSink is a GStreamer sink element that sends
- * data to a #cairo_surface_t.
+ * #WebKitVideoSink is a GStreamer sink element that triggers
+ * repaints in the WebKit GStreamer media player for the
+ * current video buffer.
*/
#include "config.h"
@@ -33,40 +34,44 @@
#include <gst/video/video.h>
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE("sink",
- GST_PAD_SINK, GST_PAD_ALWAYS,
- GST_STATIC_CAPS(GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx));
+ GST_PAD_SINK, GST_PAD_ALWAYS,
+// CAIRO_FORMAT_RGB24 used to render the video buffers is little/big endian dependant.
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ GST_STATIC_CAPS(GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_BGRA)
+#else
+ GST_STATIC_CAPS(GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_ARGB)
+#endif
+);
GST_DEBUG_CATEGORY_STATIC(webkit_video_sink_debug);
#define GST_CAT_DEFAULT webkit_video_sink_debug
-static GstElementDetails webkit_video_sink_details =
- GST_ELEMENT_DETAILS((gchar*) "WebKit video sink",
- (gchar*) "Sink/Video",
- (gchar*) "Sends video data from a GStreamer pipeline to a Cairo surface",
- (gchar*) "Alp Toker <alp@atoker.com>");
-
enum {
REPAINT_REQUESTED,
LAST_SIGNAL
};
enum {
- PROP_0,
- PROP_SURFACE
+ PROP_0
};
static guint webkit_video_sink_signals[LAST_SIGNAL] = { 0, };
struct _WebKitVideoSinkPrivate {
- cairo_surface_t* surface;
- GAsyncQueue* async_queue;
- gboolean rgb_ordering;
- int width;
- int height;
- int fps_n;
- int fps_d;
- int par_n;
- int par_d;
+ GstBuffer* buffer;
+ guint timeout_id;
+ GMutex* buffer_mutex;
+ GCond* data_cond;
+
+ // If this is TRUE all processing should finish ASAP
+ // This is necessary because there could be a race between
+ // unlock() and render(), where unlock() wins, signals the
+ // GCond, then render() tries to render a frame although
+ // everything else isn't running anymore. This will lead
+ // to deadlocks because render() holds the stream lock.
+ //
+ // Protected by the buffer mutex
+ gboolean unlocked;
};
#define _do_init(bla) \
@@ -77,8 +82,8 @@ struct _WebKitVideoSinkPrivate {
GST_BOILERPLATE_FULL(WebKitVideoSink,
webkit_video_sink,
- GstBaseSink,
- GST_TYPE_BASE_SINK,
+ GstVideoSink,
+ GST_TYPE_VIDEO_SINK,
_do_init);
static void
@@ -87,7 +92,9 @@ webkit_video_sink_base_init(gpointer g_class)
GstElementClass* element_class = GST_ELEMENT_CLASS(g_class);
gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sinktemplate));
- gst_element_class_set_details(element_class, &webkit_video_sink_details);
+ gst_element_class_set_details_simple(element_class, "WebKit video sink",
+ "Sink/Video", "Sends video data from a GStreamer pipeline to a Cairo surface",
+ "Alp Toker <alp@atoker.com>");
}
static void
@@ -96,38 +103,32 @@ webkit_video_sink_init(WebKitVideoSink* sink, WebKitVideoSinkClass* klass)
WebKitVideoSinkPrivate* priv;
sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSinkPrivate);
- priv->async_queue = g_async_queue_new();
+ priv->data_cond = g_cond_new();
+ priv->buffer_mutex = g_mutex_new();
}
static gboolean
-webkit_video_sink_idle_func(gpointer data)
+webkit_video_sink_timeout_func(gpointer data)
{
- WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(data);
+ WebKitVideoSink* sink = reinterpret_cast<WebKitVideoSink*>(data);
WebKitVideoSinkPrivate* priv = sink->priv;
GstBuffer* buffer;
- if (!priv->async_queue)
- return FALSE;
+ g_mutex_lock(priv->buffer_mutex);
+ buffer = priv->buffer;
+ priv->buffer = 0;
+ priv->timeout_id = 0;
- buffer = (GstBuffer*)g_async_queue_try_pop(priv->async_queue);
- if (!buffer || G_UNLIKELY(!GST_IS_BUFFER(buffer)))
+ if (!buffer || priv->unlocked || G_UNLIKELY(!GST_IS_BUFFER(buffer))) {
+ g_cond_signal(priv->data_cond);
+ g_mutex_unlock(priv->buffer_mutex);
return FALSE;
+ }
- // TODO: consider priv->rgb_ordering?
- cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(buffer), CAIRO_FORMAT_RGB24, priv->width, priv->height, (4 * priv->width + 3) & ~3);
-
- // TODO: We copy the data twice right now. This could be easily improved.
- cairo_t* cr = cairo_create(priv->surface);
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
- cairo_set_source_surface(cr, src, 0, 0);
- cairo_surface_destroy(src);
- cairo_rectangle(cr, 0, 0, priv->width, priv->height);
- cairo_fill(cr);
- cairo_destroy(cr);
-
+ g_signal_emit(sink, webkit_video_sink_signals[REPAINT_REQUESTED], 0, buffer);
gst_buffer_unref(buffer);
-
- g_signal_emit(sink, webkit_video_sink_signals[REPAINT_REQUESTED], 0);
+ g_cond_signal(priv->data_cond);
+ g_mutex_unlock(priv->buffer_mutex);
return FALSE;
}
@@ -138,60 +139,89 @@ webkit_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer)
WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(bsink);
WebKitVideoSinkPrivate* priv = sink->priv;
- g_async_queue_push(priv->async_queue, gst_buffer_ref(buffer));
- g_idle_add_full(G_PRIORITY_HIGH_IDLE, webkit_video_sink_idle_func, sink, 0);
-
- return GST_FLOW_OK;
-}
-
-static gboolean
-webkit_video_sink_set_caps(GstBaseSink* bsink, GstCaps* caps)
-{
- WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(bsink);
- WebKitVideoSinkPrivate* priv = sink->priv;
- GstStructure* structure;
- gboolean ret;
- const GValue* fps;
- const GValue* par;
- gint width, height;
- int red_mask;
-
- GstCaps* intersection = gst_caps_intersect(gst_static_pad_template_get_caps(&sinktemplate), caps);
+ g_mutex_lock(priv->buffer_mutex);
- if (gst_caps_is_empty(intersection))
- return FALSE;
-
- gst_caps_unref(intersection);
-
- structure = gst_caps_get_structure(caps, 0);
-
- ret = gst_structure_get_int(structure, "width", &width);
- ret &= gst_structure_get_int(structure, "height", &height);
- fps = gst_structure_get_value(structure, "framerate");
- ret &= (fps != 0);
-
- par = gst_structure_get_value(structure, "pixel-aspect-ratio");
+ if (priv->unlocked) {
+ g_mutex_unlock(priv->buffer_mutex);
+ return GST_FLOW_OK;
+ }
- if (!ret)
- return FALSE;
+ priv->buffer = gst_buffer_ref(buffer);
- priv->width = width;
- priv->height = height;
+ // For the unlikely case where the buffer has no caps, the caps
+ // are implicitely the caps of the pad. This shouldn't happen.
+ if (G_UNLIKELY(!GST_BUFFER_CAPS(buffer))) {
+ buffer = priv->buffer = gst_buffer_make_metadata_writable(priv->buffer);
+ gst_buffer_set_caps(priv->buffer, GST_PAD_CAPS(GST_BASE_SINK_PAD(bsink)));
+ }
- /* We dont yet use fps or pixel aspect into but handy to have */
- priv->fps_n = gst_value_get_fraction_numerator(fps);
- priv->fps_d = gst_value_get_fraction_denominator(fps);
+ GstCaps *caps = GST_BUFFER_CAPS(buffer);
+ GstVideoFormat format;
+ int width, height;
+ if (G_UNLIKELY(!gst_video_format_parse_caps(caps, &format, &width, &height))) {
+ gst_buffer_unref(buffer);
+ g_mutex_unlock(priv->buffer_mutex);
+ return GST_FLOW_ERROR;
+ }
- if (par) {
- priv->par_n = gst_value_get_fraction_numerator(par);
- priv->par_d = gst_value_get_fraction_denominator(par);
- } else
- priv->par_n = priv->par_d = 1;
+ // Cairo's ARGB has pre-multiplied alpha while GStreamer's doesn't.
+ // Here we convert to Cairo's ARGB.
+ if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA) {
+ // Because GstBaseSink::render() only owns the buffer reference in the
+ // method scope we can't use gst_buffer_make_writable() here. Also
+ // The buffer content should not be changed here because the same buffer
+ // could be passed multiple times to this method (in theory)
+ GstBuffer *newBuffer = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(buffer));
+
+ // Check if allocation failed
+ if (G_UNLIKELY(!newBuffer)) {
+ gst_buffer_unref(buffer);
+ g_mutex_unlock(priv->buffer_mutex);
+ return GST_FLOW_ERROR;
+ }
+
+ gst_buffer_copy_metadata(newBuffer, buffer, (GstBufferCopyFlags) GST_BUFFER_COPY_ALL);
+
+ // We don't use Color::premultipliedARGBFromColor() here because
+ // one function call per video pixel is just too expensive:
+ // For 720p/PAL for example this means 1280*720*25=23040000
+ // function calls per second!
+ unsigned short alpha;
+ const guint8 *source = GST_BUFFER_DATA(buffer);
+ guint8 *destination = GST_BUFFER_DATA(newBuffer);
+
+ for (int x = 0; x < height; x++) {
+ for (int y = 0; y < width; y++) {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ alpha = source[3];
+ destination[0] = (source[0] * alpha + 128) / 255;
+ destination[1] = (source[1] * alpha + 128) / 255;
+ destination[2] = (source[2] * alpha + 128) / 255;
+ destination[3] = alpha;
+#else
+ alpha = source[0];
+ destination[0] = alpha;
+ destination[1] = (source[1] * alpha + 128) / 255;
+ destination[2] = (source[2] * alpha + 128) / 255;
+ destination[3] = (source[3] * alpha + 128) / 255;
+#endif
+ source += 4;
+ destination += 4;
+ }
+ }
+ gst_buffer_unref(buffer);
+ buffer = priv->buffer = newBuffer;
+ }
- gst_structure_get_int(structure, "red_mask", &red_mask);
- priv->rgb_ordering = (red_mask == static_cast<int>(0xff000000));
+ // Use HIGH_IDLE+20 priority, like Gtk+ for redrawing operations.
+ priv->timeout_id = g_timeout_add_full(G_PRIORITY_HIGH_IDLE + 20, 0,
+ webkit_video_sink_timeout_func,
+ gst_object_ref(sink),
+ (GDestroyNotify)gst_object_unref);
- return TRUE;
+ g_cond_wait(priv->data_cond, priv->buffer_mutex);
+ g_mutex_unlock(priv->buffer_mutex);
+ return GST_FLOW_OK;
}
static void
@@ -200,56 +230,58 @@ webkit_video_sink_dispose(GObject* object)
WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
WebKitVideoSinkPrivate* priv = sink->priv;
- if (priv->surface) {
- cairo_surface_destroy(priv->surface);
- priv->surface = 0;
+ if (priv->data_cond) {
+ g_cond_free(priv->data_cond);
+ priv->data_cond = 0;
}
- if (priv->async_queue) {
- g_async_queue_unref(priv->async_queue);
- priv->async_queue = 0;
+ if (priv->buffer_mutex) {
+ g_mutex_free(priv->buffer_mutex);
+ priv->buffer_mutex = 0;
}
G_OBJECT_CLASS(parent_class)->dispose(object);
}
static void
-webkit_video_sink_finalize(GObject* object)
+unlock_buffer_mutex(WebKitVideoSinkPrivate* priv)
{
- G_OBJECT_CLASS(parent_class)->finalize(object);
+ g_mutex_lock(priv->buffer_mutex);
+
+ if (priv->buffer) {
+ gst_buffer_unref(priv->buffer);
+ priv->buffer = 0;
+ }
+
+ priv->unlocked = TRUE;
+
+ g_cond_signal(priv->data_cond);
+ g_mutex_unlock(priv->buffer_mutex);
}
-static void
-webkit_video_sink_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
+static gboolean
+webkit_video_sink_unlock(GstBaseSink* object)
{
WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
- WebKitVideoSinkPrivate* priv = sink->priv;
- switch (prop_id) {
- case PROP_SURFACE:
- if (priv->surface)
- cairo_surface_destroy(priv->surface);
- priv->surface = cairo_surface_reference((cairo_surface_t*)g_value_get_pointer(value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
+ unlock_buffer_mutex(sink->priv);
+
+ return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock,
+ (object), TRUE);
}
-static void
-webkit_video_sink_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
+static gboolean
+webkit_video_sink_unlock_stop(GstBaseSink* object)
{
WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
+ WebKitVideoSinkPrivate* priv = sink->priv;
- switch (prop_id) {
- case PROP_SURFACE:
- g_value_set_pointer(value, sink->priv->surface);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
+ g_mutex_lock(priv->buffer_mutex);
+ priv->unlocked = FALSE;
+ g_mutex_unlock(priv->buffer_mutex);
+
+ return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock_stop,
+ (object), TRUE);
}
static gboolean
@@ -257,18 +289,46 @@ webkit_video_sink_stop(GstBaseSink* base_sink)
{
WebKitVideoSinkPrivate* priv = WEBKIT_VIDEO_SINK(base_sink)->priv;
- g_async_queue_lock(priv->async_queue);
-
- /* Remove all remaining objects from the queue */
- while (GstBuffer* buffer = (GstBuffer*)g_async_queue_try_pop_unlocked(priv->async_queue))
- gst_buffer_unref(buffer);
+ unlock_buffer_mutex(priv);
+ return TRUE;
+}
- g_async_queue_unlock(priv->async_queue);
+static gboolean
+webkit_video_sink_start(GstBaseSink* base_sink)
+{
+ WebKitVideoSinkPrivate* priv = WEBKIT_VIDEO_SINK(base_sink)->priv;
+ g_mutex_lock(priv->buffer_mutex);
+ priv->unlocked = FALSE;
+ g_mutex_unlock(priv->buffer_mutex);
return TRUE;
}
static void
+marshal_VOID__MINIOBJECT(GClosure * closure, GValue * return_value,
+ guint n_param_values, const GValue * param_values,
+ gpointer invocation_hint, gpointer marshal_data)
+{
+ typedef void (*marshalfunc_VOID__MINIOBJECT) (gpointer obj, gpointer arg1, gpointer data2);
+ marshalfunc_VOID__MINIOBJECT callback;
+ GCClosure *cc = (GCClosure *) closure;
+ gpointer data1, data2;
+
+ g_return_if_fail(n_param_values == 2);
+
+ if (G_CCLOSURE_SWAP_DATA(closure)) {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer(param_values + 0);
+ } else {
+ data1 = g_value_peek_pointer(param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : cc->callback);
+
+ callback(data1, gst_value_get_mini_object(param_values + 1), data2);
+}
+
+static void
webkit_video_sink_class_init(WebKitVideoSinkClass* klass)
{
GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
@@ -276,16 +336,14 @@ webkit_video_sink_class_init(WebKitVideoSinkClass* klass)
g_type_class_add_private(klass, sizeof(WebKitVideoSinkPrivate));
- gobject_class->set_property = webkit_video_sink_set_property;
- gobject_class->get_property = webkit_video_sink_get_property;
-
gobject_class->dispose = webkit_video_sink_dispose;
- gobject_class->finalize = webkit_video_sink_finalize;
+ gstbase_sink_class->unlock = webkit_video_sink_unlock;
+ gstbase_sink_class->unlock_stop = webkit_video_sink_unlock_stop;
gstbase_sink_class->render = webkit_video_sink_render;
gstbase_sink_class->preroll = webkit_video_sink_render;
gstbase_sink_class->stop = webkit_video_sink_stop;
- gstbase_sink_class->set_caps = webkit_video_sink_set_caps;
+ gstbase_sink_class->start = webkit_video_sink_start;
webkit_video_sink_signals[REPAINT_REQUESTED] = g_signal_new("repaint-requested",
G_TYPE_FROM_CLASS(klass),
@@ -293,37 +351,20 @@ webkit_video_sink_class_init(WebKitVideoSinkClass* klass)
0,
0,
0,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_object_class_install_property(
- gobject_class, PROP_SURFACE,
- g_param_spec_pointer("surface", "surface", "Target cairo_surface_t*",
- (GParamFlags)(G_PARAM_READWRITE)));
+ marshal_VOID__MINIOBJECT,
+ G_TYPE_NONE, 1, GST_TYPE_BUFFER);
}
/**
* webkit_video_sink_new:
- * @surface: a #cairo_surface_t
*
- * Creates a new GStreamer video sink which uses @surface as the target
- * for sinking a video stream from GStreamer.
+ * Creates a new GStreamer video sink.
*
* Return value: a #GstElement for the newly created video sink
*/
GstElement*
-webkit_video_sink_new(cairo_surface_t* surface)
+webkit_video_sink_new(void)
{
- return (GstElement*)g_object_new(WEBKIT_TYPE_VIDEO_SINK, "surface", surface, 0);
+ return (GstElement*)g_object_new(WEBKIT_TYPE_VIDEO_SINK, 0);
}
-void
-webkit_video_sink_set_surface(WebKitVideoSink* sink, cairo_surface_t* surface)
-{
- WebKitVideoSinkPrivate* priv;
-
- sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSinkPrivate);
- if (priv->surface)
- cairo_surface_destroy(priv->surface);
- priv->surface = cairo_surface_reference(surface);
-}
diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h
index be2c94c..7ea7d91 100644
--- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h
+++ b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h
@@ -22,7 +22,7 @@
#include <cairo.h>
#include <glib-object.h>
-#include <gst/base/gstbasesink.h>
+#include <gst/video/gstvideosink.h>
G_BEGIN_DECLS
@@ -54,13 +54,13 @@ typedef struct _WebKitVideoSinkPrivate WebKitVideoSinkPrivate;
struct _WebKitVideoSink {
/*< private >*/
- GstBaseSink parent;
+ GstVideoSink parent;
WebKitVideoSinkPrivate *priv;
};
struct _WebKitVideoSinkClass {
/*< private >*/
- GstBaseSinkClass parent_class;
+ GstVideoSinkClass parent_class;
/* Future padding */
void (* _webkit_reserved1)(void);
@@ -72,9 +72,7 @@ struct _WebKitVideoSinkClass {
};
GType webkit_video_sink_get_type(void) G_GNUC_CONST;
-GstElement *webkit_video_sink_new(cairo_surface_t *surface);
-
-void webkit_video_sink_set_surface(WebKitVideoSink *sink, cairo_surface_t *surface);
+GstElement *webkit_video_sink_new(void);
G_END_DECLS
diff --git a/WebCore/platform/graphics/haiku/ColorHaiku.cpp b/WebCore/platform/graphics/haiku/ColorHaiku.cpp
new file mode 100644
index 0000000..a9ac186
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/ColorHaiku.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Color.h"
+
+#include <InterfaceDefs.h>
+
+
+namespace WebCore {
+
+Color::Color(const rgb_color& color)
+ : m_color(makeRGBA(color.red, color.green, color.blue, color.alpha))
+ , m_valid(true)
+{
+}
+
+Color::operator rgb_color() const
+{
+ return make_color(red(), green(), blue(), alpha());
+}
+
+
+Color focusRingColor()
+{
+ return Color(keyboard_navigation_color());
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FloatPointHaiku.cpp b/WebCore/platform/graphics/haiku/FloatPointHaiku.cpp
new file mode 100644
index 0000000..0f50898
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FloatPointHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FloatPoint.h"
+
+#include <Point.h>
+
+
+namespace WebCore {
+
+FloatPoint::FloatPoint(const BPoint& point)
+ : m_x(point.x)
+ , m_y(point.y)
+{
+}
+
+FloatPoint::operator BPoint() const
+{
+ return BPoint(m_x, m_y);
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp b/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp
new file mode 100644
index 0000000..67af3af
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FloatRect.h"
+
+#include <Rect.h>
+
+
+namespace WebCore {
+
+FloatRect::FloatRect(const BRect& rect)
+ : m_location(rect.LeftTop())
+ , m_size(rect.Width(), rect.Height())
+{
+}
+
+FloatRect::operator BRect() const
+{
+ return BRect(BPoint(x(), y()), BSize(width(), height()));
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp
new file mode 100644
index 0000000..b99bf42
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 "FontCache.h"
+
+#include "Font.h"
+#include "FontData.h"
+#include "FontPlatformData.h"
+#include "NotImplemented.h"
+#include <String.h>
+
+
+namespace WebCore {
+
+void FontCache::platformInit()
+{
+}
+
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
+{
+ FontPlatformData data(font.fontDescription(), font.family().family());
+ return getCachedFontData(&data);
+}
+
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ notImplemented();
+ return 0;
+}
+
+FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
+{
+ // 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 defaultString("DejaVu Serif");
+ return getCachedFontPlatformData(fontDescription, defaultString);
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+ return new FontPlatformData(fontDescription, family);
+}
+
+void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp b/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp
new file mode 100644
index 0000000..6008bb1
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 Alp Toker <alp@atoker.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 "FontCustomPlatformData.h"
+
+#include "SharedBuffer.h"
+#include "FontPlatformData.h"
+
+
+namespace WebCore {
+
+FontCustomPlatformData::~FontCustomPlatformData()
+{
+}
+
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontRenderingMode)
+{
+ return FontPlatformData(size, bold, italic);
+}
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
+{
+ // FIXME: We need support in Haiku to read fonts from memory to implement this.
+ return 0;
+}
+
+}
diff --git a/WebCore/platform/graphics/haiku/FontCustomPlatformData.h b/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
new file mode 100644
index 0000000..c5a814e
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 Alp Toker <alp@atoker.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 FontCustomPlatformData_h
+#define FontCustomPlatformData_h
+
+#include "FontRenderingMode.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+ class FontPlatformData;
+ class SharedBuffer;
+
+ struct FontCustomPlatformData : Noncopyable {
+ public:
+ FontCustomPlatformData() { }
+ ~FontCustomPlatformData();
+
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode);
+ };
+
+ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/haiku/FontHaiku.cpp b/WebCore/platform/graphics/haiku/FontHaiku.cpp
new file mode 100644
index 0000000..48744d9
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontHaiku.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Font.h"
+
+#include "FontData.h"
+#include "FontDescription.h"
+#include "FontSelector.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include <Font.h>
+#include <String.h>
+#include <View.h>
+
+
+// FIXME: Temp routine to convert unicode character to UTF8.
+int charUnicodeToUTF8HACK(unsigned short glyph, char* out)
+{
+ int i = 0;
+
+ if (glyph < 0x0080)
+ out[i++] = static_cast<char>(glyph);
+ else if (glyph < 0x0800) { // 2 bytes
+ out[i++] = 0xc0 | (glyph >> 6);
+ out[i++] = 0x80 | (glyph & 0x3F);
+ } else if (glyph > 0x0800) { // 3 bytes
+ out[i++] = 0xe0 | (glyph >> 12);
+ out[i++] = 0x80 | ((glyph >> 6) & 0x3F);
+ out[i++] = 0x80 | (glyph & 0x3F);
+ }
+
+ out[i] = '\0';
+ return i;
+}
+
+namespace WebCore {
+
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
+void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
+{
+ Color color = graphicsContext->fillColor();
+ BView* view = graphicsContext->platformContext();
+ BFont* m_font = font->platformData().font();
+
+ graphicsContext->setCompositeOperation(CompositeSourceOver);
+ view->SetHighColor(color);
+ view->SetFont(m_font);
+
+ GlyphBufferGlyph* glyphs = const_cast<GlyphBufferGlyph*>(glyphBuffer.glyphs(from));
+ float offset = point.x();
+ for (int i = 0; i < numGlyphs; i++) {
+ char out[4];
+ charUnicodeToUTF8HACK(glyphs[i], out);
+
+ view->DrawString(out, sizeof(out), BPoint(offset, point.y()));
+ offset += glyphBuffer.advanceAt(from + i);
+ }
+}
+
+void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point,
+ int from, int to) const
+{
+ notImplemented();
+}
+
+
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+{
+ notImplemented();
+ return 0;
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun&, const IntPoint&, int, int, int) const
+{
+ notImplemented();
+ return FloatRect();
+}
+
+int Font::offsetForPositionForComplexText(const TextRun&, int, bool) const
+{
+ notImplemented();
+ return 0;
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FontPlatformData.h b/WebCore/platform/graphics/haiku/FontPlatformData.h
new file mode 100644
index 0000000..9feab8e
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontPlatformData.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef FontPlatformData_H
+#define FontPlatformData_H
+
+#include "FontDescription.h"
+#include "GlyphBuffer.h"
+#include <interface/Font.h>
+
+namespace WebCore {
+
+ class FontPlatformData {
+ public:
+ FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_font(hashTableDeletedFontValue())
+ { }
+
+ FontPlatformData()
+ : m_font(0)
+ { }
+
+ FontPlatformData(const FontDescription&, const AtomicString& family);
+ FontPlatformData(float size, bool bold, bool oblique);
+ FontPlatformData(const FontPlatformData&);
+
+ ~FontPlatformData();
+
+ BFont* font() const { return m_font; }
+
+ bool isFixedPitch();
+ float size() const { return m_size; }
+ bool bold() const { return m_bold; }
+ bool oblique() const { return m_oblique; }
+
+ unsigned hash() const;
+ bool isHashTableDeletedValue() const;
+
+ bool operator==(const FontPlatformData&) const;
+
+#ifndef NDEBUG
+ String description() const;
+#endif
+
+ BFont* m_font;
+ float m_size;
+ bool m_bold;
+ bool m_oblique;
+
+ private:
+ static BFont* hashTableDeletedFontValue() { return reinterpret_cast<BFont*>(-1); }
+ };
+
+} // namespace WebCore
+
+#endif
+
diff --git a/WebCore/platform/graphics/haiku/GradientHaiku.cpp b/WebCore/platform/graphics/haiku/GradientHaiku.cpp
new file mode 100644
index 0000000..469a17f
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/GradientHaiku.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Kevin Ollivier <kevino@theolliviers.com> All rights reserved.
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@theolliviers.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "Gradient.h"
+
+#include "CSSParser.h"
+#include "NotImplemented.h"
+
+
+namespace WebCore {
+
+void Gradient::platformDestroy()
+{
+ notImplemented();
+}
+
+PlatformGradient Gradient::platformGradient()
+{
+ notImplemented();
+ return 0;
+}
+
+void Gradient::fill(GraphicsContext*, const FloatRect&)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
new file mode 100644
index 0000000..4728d56
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GraphicsContext.h"
+
+#include "CString.h"
+#include "Color.h"
+#include "Font.h"
+#include "FontData.h"
+#include "NotImplemented.h"
+#include "Path.h"
+#include "Pen.h"
+#include "TransformationMatrix.h"
+#include <GraphicsDefs.h>
+#include <Region.h>
+#include <View.h>
+#include <Window.h>
+#include <stdio.h>
+
+
+namespace WebCore {
+
+class GraphicsContextPlatformPrivate {
+public:
+ GraphicsContextPlatformPrivate(BView* view);
+ ~GraphicsContextPlatformPrivate();
+
+ BView* m_view;
+};
+
+GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(BView* view)
+ : m_view(view)
+{
+}
+
+GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
+{
+}
+
+GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
+ : m_common(createGraphicsContextPrivate())
+ , m_data(new GraphicsContextPlatformPrivate(context))
+{
+ setPaintingDisabled(!context);
+}
+
+GraphicsContext::~GraphicsContext()
+{
+ destroyGraphicsContextPrivate(m_common);
+ delete m_data;
+}
+
+PlatformGraphicsContext* GraphicsContext::platformContext() const
+{
+ return m_data->m_view;
+}
+
+void GraphicsContext::savePlatformState()
+{
+ m_data->m_view->PushState();
+}
+
+void GraphicsContext::restorePlatformState()
+{
+ m_data->m_view->PopState();
+}
+
+// Draws a filled rectangle with a stroked border.
+void GraphicsContext::drawRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->FillRect(rect);
+ if (strokeStyle() != NoStroke)
+ m_data->m_view->StrokeRect(rect, getHaikuStrokeStyle());
+}
+
+// This is only used to draw borders.
+void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
+{
+ if (paintingDisabled())
+ return;
+
+ if (strokeStyle() == NoStroke)
+ return;
+
+ m_data->m_view->StrokeLine(point1, point2, getHaikuStrokeStyle());
+}
+
+// This method is only used to draw the little circles used in lists.
+void GraphicsContext::drawEllipse(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->FillEllipse(rect);
+ if (strokeStyle() != NoStroke)
+ m_data->m_view->StrokeEllipse(rect, getHaikuStrokeStyle());
+}
+
+void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->StrokeArc(rect, startAngle, angleSpan, getHaikuStrokeStyle());
+}
+
+void GraphicsContext::strokePath()
+{
+ notImplemented();
+}
+
+void GraphicsContext::drawConvexPolygon(size_t pointsLength, const FloatPoint* points, bool shouldAntialias)
+{
+ if (paintingDisabled())
+ return;
+
+ BPoint bPoints[pointsLength];
+ for (size_t i = 0; i < pointsLength; i++)
+ bPoints[i] = points[i];
+
+ m_data->m_view->FillPolygon(bPoints, pointsLength);
+ if (strokeStyle() != NoStroke)
+ // Stroke with low color
+ m_data->m_view->StrokePolygon(bPoints, pointsLength, true, getHaikuStrokeStyle());
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
+{
+ if (paintingDisabled())
+ return;
+
+ rgb_color oldColor = m_data->m_view->HighColor();
+ m_data->m_view->SetHighColor(color);
+ m_data->m_view->FillRect(rect);
+ m_data->m_view->SetHighColor(oldColor);
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+}
+
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
+{
+ if (paintingDisabled() || !color.alpha())
+ return;
+
+ notImplemented();
+ // FIXME: A simple implementation could just use FillRoundRect if all
+ // the sizes are the same, or even if they are not. Otherwise several
+ // FillRect and FillArc calls are needed.
+}
+
+void GraphicsContext::fillPath()
+{
+ notImplemented();
+}
+
+void GraphicsContext::beginPath()
+{
+ notImplemented();
+}
+
+void GraphicsContext::addPath(const Path& path)
+{
+ notImplemented();
+}
+
+void GraphicsContext::clip(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ BRegion region(rect);
+ m_data->m_view->ConstrainClippingRegion(&region);
+}
+
+void GraphicsContext::drawFocusRing(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ const Vector<IntRect>& rects = focusRingRects();
+ unsigned rectCount = rects.size();
+
+ // FIXME: maybe we should implement this with BShape?
+
+ if (rects.size() > 1) {
+ BRegion region;
+ for (int i = 0; i < rectCount; ++i)
+ region.Include(BRect(rects[i]));
+
+ m_data->m_view->SetHighColor(color);
+ m_data->m_view->StrokeRect(region.Frame(), B_MIXED_COLORS);
+ }
+}
+
+void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
+{
+ if (paintingDisabled())
+ return;
+
+ IntPoint endPoint = origin + IntSize(width, 0);
+ drawLine(origin, endPoint);
+}
+
+void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int width, bool grammar)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
+{
+ notImplemented();
+ return rect;
+}
+
+void GraphicsContext::beginTransparencyLayer(float opacity)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::clearRect(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::strokeRect(const FloatRect& rect, float width)
+{
+ if (paintingDisabled())
+ return;
+
+ float oldSize = m_data->m_view->PenSize();
+ m_data->m_view->SetPenSize(width);
+ m_data->m_view->StrokeRect(rect, getHaikuStrokeStyle());
+ m_data->m_view->SetPenSize(oldSize);
+}
+
+void GraphicsContext::setLineCap(LineCap lineCap)
+{
+ if (paintingDisabled())
+ return;
+
+ cap_mode mode = B_BUTT_CAP;
+ switch (lineCap) {
+ case RoundCap:
+ mode = B_ROUND_CAP;
+ break;
+ case SquareCap:
+ mode = B_SQUARE_CAP;
+ break;
+ case ButtCap:
+ default:
+ break;
+ }
+
+ m_data->m_view->SetLineMode(mode, m_data->m_view->LineJoinMode(), m_data->m_view->LineMiterLimit());
+}
+
+void GraphicsContext::setLineJoin(LineJoin lineJoin)
+{
+ if (paintingDisabled())
+ return;
+
+ join_mode mode = B_MITER_JOIN;
+ switch (lineJoin) {
+ case RoundJoin:
+ mode = B_ROUND_JOIN;
+ break;
+ case BevelJoin:
+ mode = B_BEVEL_JOIN;
+ break;
+ case MiterJoin:
+ default:
+ break;
+ }
+
+ m_data->m_view->SetLineMode(m_data->m_view->LineCapMode(), mode, m_data->m_view->LineMiterLimit());
+}
+
+void GraphicsContext::setMiterLimit(float limit)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->SetLineMode(m_data->m_view->LineCapMode(), m_data->m_view->LineJoinMode(), limit);
+}
+
+void GraphicsContext::setAlpha(float opacity)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::setCompositeOperation(CompositeOperator op)
+{
+ if (paintingDisabled())
+ return;
+
+ drawing_mode mode = B_OP_COPY;
+ switch (op) {
+ case CompositeClear:
+ case CompositeCopy:
+ // Use the default above
+ break;
+ case CompositeSourceOver:
+ mode = B_OP_OVER;
+ break;
+ default:
+ printf("GraphicsContext::setCompositeOperation: Unsupported composite operation %s\n",
+ compositeOperatorName(op).utf8().data());
+ }
+ m_data->m_view->SetDrawingMode(mode);
+}
+
+void GraphicsContext::clip(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->ConstrainClippingRegion(path.platformPath());
+}
+
+void GraphicsContext::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
+void GraphicsContext::clipOut(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
+{
+ notImplemented();
+}
+
+TransformationMatrix GraphicsContext::getCTM() const
+{
+ notImplemented();
+ return TransformationMatrix();
+}
+
+void GraphicsContext::translate(float x, float y)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+IntPoint GraphicsContext::origin()
+{
+ notImplemented();
+ return IntPoint(0, 0);
+}
+
+void GraphicsContext::rotate(float radians)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::scale(const FloatSize& size)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::clipOut(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::concatCTM(const TransformationMatrix& transform)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformShouldAntialias(bool enable)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
+{
+}
+
+void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformFont(const Font& font)
+{
+ m_data->m_view->SetFont(font.primaryFont()->platformData().font());
+}
+
+void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->SetHighColor(color);
+}
+
+pattern GraphicsContext::getHaikuStrokeStyle()
+{
+ switch (strokeStyle()) {
+ case SolidStroke:
+ return B_SOLID_HIGH;
+ break;
+ case DottedStroke:
+ return B_MIXED_COLORS;
+ break;
+ case DashedStroke:
+ // FIXME: use a better dashed stroke!
+ notImplemented();
+ return B_MIXED_COLORS;
+ break;
+ default:
+ return B_SOLID_LOW;
+ break;
+ }
+}
+
+void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
+{
+ // FIXME: see getHaikuStrokeStyle.
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformStrokeThickness(float thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->SetPenSize(thickness);
+}
+
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->SetHighColor(color);
+}
+
+void GraphicsContext::clearPlatformShadow()
+{
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&, ColorSpace)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/IconHaiku.cpp b/WebCore/platform/graphics/haiku/IconHaiku.cpp
new file mode 100644
index 0000000..3663ee2
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/IconHaiku.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+#include "Icon.h"
+
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+
+
+namespace WebCore {
+
+Icon::~Icon()
+{
+ notImplemented();
+}
+
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
+{
+ notImplemented();
+ return 0;
+}
+
+void Icon::paint(GraphicsContext*, const IntRect&)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/ImageBufferData.h b/WebCore/platform/graphics/haiku/ImageBufferData.h
new file mode 100644
index 0000000..f978c34
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/ImageBufferData.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ImageBufferData_h
+#define ImageBufferData_h
+
+namespace WebCore {
+
+ class IntSize;
+
+ class ImageBufferData {
+ public:
+ ImageBufferData(const IntSize&);
+ };
+
+} // namespace WebCore
+
+#endif // ImageBufferData_h
+
diff --git a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
new file mode 100644
index 0000000..276c968
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ImageBuffer.h"
+
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include "NotImplemented.h"
+
+
+namespace WebCore {
+
+ImageBufferData::ImageBufferData(const IntSize&)
+{
+}
+
+ImageBuffer::ImageBuffer(const IntSize&, ImageColorSpace imageColorSpace, bool& success)
+ : m_data(IntSize())
+{
+ notImplemented();
+ success = false;
+}
+
+ImageBuffer::~ImageBuffer()
+{
+}
+
+GraphicsContext* ImageBuffer::context() const
+{
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ notImplemented();
+ return 0;
+}
+
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ notImplemented();
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ notImplemented();
+}
+
+String ImageBuffer::toDataURL(const String&) const
+{
+ notImplemented();
+ return String();
+}
+
+Image* ImageBuffer::image() const
+{
+ notImplemented();
+ return 0;
+}
+
+void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/ImageHaiku.cpp b/WebCore/platform/graphics/haiku/ImageHaiku.cpp
new file mode 100644
index 0000000..df08822
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/ImageHaiku.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ * Copyright (C) 2008 Andrea Anzani <andrea.anzani@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Image.h"
+
+#include "BitmapImage.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+#include <Application.h>
+#include <Bitmap.h>
+#include <View.h>
+
+
+// This function loads resources from WebKit
+Vector<char> loadResourceIntoArray(const char*);
+
+
+namespace WebCore {
+
+bool FrameData::clear(bool clearMetadata)
+{
+ if (clearMetadata)
+ m_haveMetadata = false;
+
+ if (m_frame) {
+ delete m_frame;
+ m_frame = 0;
+ m_duration = 0.0f;
+ m_hasAlpha = true;
+ return true;
+ }
+
+ return false;
+}
+
+WTF::PassRefPtr<Image> Image::loadPlatformResource(const char* name)
+{
+ Vector<char> array = loadResourceIntoArray(name);
+ WTF::PassRefPtr<BitmapImage> image = BitmapImage::create();
+ RefPtr<SharedBuffer> buffer = SharedBuffer::create(array.data(), array.size());
+ image->setData(buffer, true);
+
+ return image;
+}
+
+void BitmapImage::initPlatformData()
+{
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+}
+
+// Drawing Routines
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
+{
+ startAnimation();
+
+ BBitmap* image = nativeImageForCurrentFrame();
+ if (!image || !image->IsValid()) // If the image hasn't fully loaded.
+ return;
+
+ if (mayFillWithSolidColor()) {
+ fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
+ return;
+ }
+
+ ctxt->save();
+ ctxt->setCompositeOperation(op);
+
+ BRect srcRect(src);
+ BRect dstRect(dst);
+
+ // Test using example site at
+ // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
+ ctxt->platformContext()->SetDrawingMode(B_OP_ALPHA);
+ ctxt->platformContext()->DrawBitmap(image, srcRect & image->Bounds(), dstRect);
+ ctxt->restore();
+}
+
+void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform, const FloatPoint& srcPoint, ColorSpace, CompositeOperator op, const FloatRect& dstRect)
+{
+ // FIXME: finish this to support also phased position (srcPoint)
+ startAnimation();
+
+ BBitmap* image = nativeImageForCurrentFrame();
+ if (!image || !image->IsValid()) // If the image hasn't fully loaded.
+ return;
+
+ float currentW = 0;
+ float currentH = 0;
+
+ context->save();
+ context->platformContext()->SetDrawingMode(B_OP_ALPHA);
+ context->clip(enclosingIntRect(dstRect));
+
+ while (currentW < dstRect.width()) {
+ while (currentH < dstRect.height()) {
+ context->platformContext()->DrawBitmap(image, BPoint(dstRect.x() + currentW, dstRect.y() + currentH));
+ currentH += tileRect.height();
+ }
+ currentW += tileRect.width();
+ currentH = 0;
+ }
+ context->restore();
+}
+
+void BitmapImage::checkForSolidColor()
+{
+ // FIXME: need to check the RGBA32 buffer to see if it is 1x1.
+ m_isSolidColor = false;
+ m_checkedForSolidColor = true;
+}
+
+BBitmap* BitmapImage::getBBitmap() const
+{
+ return const_cast<BitmapImage*>(this)->frameAtIndex(0);
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/IntPointHaiku.cpp b/WebCore/platform/graphics/haiku/IntPointHaiku.cpp
new file mode 100644
index 0000000..327e503
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/IntPointHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IntPoint.h"
+
+#include <Point.h>
+
+
+namespace WebCore {
+
+IntPoint::IntPoint(const BPoint& point)
+ : m_x(static_cast<int>(point.x))
+ , m_y(static_cast<int>(point.y))
+{
+}
+
+IntPoint::operator BPoint() const
+{
+ return BPoint(m_x, m_y);
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/IntRectHaiku.cpp b/WebCore/platform/graphics/haiku/IntRectHaiku.cpp
new file mode 100644
index 0000000..74a0b9d
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/IntRectHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IntRect.h"
+
+#include <Rect.h>
+
+
+namespace WebCore {
+
+IntRect::IntRect(const BRect& rect)
+ : m_location(rect.LeftTop())
+ , m_size(rect.IntegerWidth(), rect.IntegerHeight())
+{
+}
+
+IntRect::operator BRect() const
+{
+ return BRect(BPoint(x(), y()), BSize(width(), height()));
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/IntSizeHaiku.cpp b/WebCore/platform/graphics/haiku/IntSizeHaiku.cpp
new file mode 100644
index 0000000..08c3a9d
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/IntSizeHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IntSize.h"
+
+#include <Size.h>
+
+
+namespace WebCore {
+
+IntSize::IntSize(const BSize& size)
+ : m_width(size.IntegerWidth())
+ , m_height(size.IntegerHeight())
+{
+}
+
+IntSize::operator BSize() const
+{
+ return BSize(width(), height());
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/PathHaiku.cpp b/WebCore/platform/graphics/haiku/PathHaiku.cpp
new file mode 100644
index 0000000..d0da025
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/PathHaiku.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Path.h"
+
+#include "FloatRect.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+#include <Region.h>
+
+
+namespace WebCore {
+
+Path::Path()
+ : m_path(new BRegion())
+{
+}
+
+Path::~Path()
+{
+ delete m_path;
+}
+
+Path::Path(const Path& other)
+ : m_path(new BRegion(*other.platformPath()))
+{
+}
+
+Path& Path::operator=(const Path& other)
+{
+ if (&other != this)
+ m_path = other.platformPath();
+
+ return *this;
+}
+
+bool Path::hasCurrentPoint() const
+{
+ return !isEmpty();
+}
+
+bool Path::contains(const FloatPoint& point, WindRule rule) const
+{
+ return m_path->Contains(point);
+}
+
+void Path::translate(const FloatSize& size)
+{
+ notImplemented();
+}
+
+FloatRect Path::boundingRect() const
+{
+ return m_path->Frame();
+}
+
+void Path::moveTo(const FloatPoint& point)
+{
+ // FIXME: Use OffsetBy?
+ notImplemented();
+}
+
+void Path::addLineTo(const FloatPoint& p)
+{
+ notImplemented();
+}
+
+void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+{
+ notImplemented();
+}
+
+void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+{
+ notImplemented();
+}
+
+void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
+{
+ notImplemented();
+}
+
+void Path::closeSubpath()
+{
+ notImplemented();
+}
+
+void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool anticlockwise)
+{
+ notImplemented();
+}
+
+void Path::addRect(const FloatRect& r)
+{
+ m_path->Include(r);
+}
+
+void Path::addEllipse(const FloatRect& r)
+{
+ notImplemented();
+}
+
+void Path::clear()
+{
+ m_path->MakeEmpty();
+}
+
+bool Path::isEmpty() const
+{
+ return !m_path->Frame().IsValid();
+}
+
+String Path::debugString() const
+{
+ notImplemented();
+ return String();
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ notImplemented();
+}
+
+void Path::transform(const TransformationMatrix& transform)
+{
+ notImplemented();
+}
+
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+{
+ notImplemented();
+ return FloatRect();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
new file mode 100644
index 0000000..adb7573
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com> All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 "SimpleFontData.h"
+
+#include "FloatRect.h"
+#include "FontCache.h"
+#include "FontDescription.h"
+#include "NotImplemented.h"
+#include <Rect.h>
+#include <unicode/uchar.h>
+#include <unicode/unorm.h>
+
+
+extern int charUnicodeToUTF8HACK(unsigned short, char*);
+
+namespace WebCore {
+
+void SimpleFontData::platformInit()
+{
+ BFont* font = m_platformData.font();
+ if (!font)
+ return;
+
+ font_height height;
+ font->GetHeight(&height);
+ m_ascent = static_cast<int>(height.ascent);
+ m_descent = static_cast<int>(height.descent);
+ m_lineSpacing = m_ascent + m_descent;
+ m_xHeight = height.ascent * 0.56f; // Hack taken from the win port.
+ m_lineGap = height.leading;
+}
+
+void SimpleFontData::platformCharWidthInit()
+{
+ m_avgCharWidth = 0.f;
+ m_maxCharWidth = 0.f;
+ initCharWidths();
+}
+
+void SimpleFontData::platformDestroy()
+{
+ delete m_smallCapsFontData;
+ m_smallCapsFontData = 0;
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_smallCapsFontData) {
+ FontDescription desc = FontDescription(fontDescription);
+ desc.setSpecifiedSize(0.70f * fontDescription.computedSize());
+ const FontPlatformData* fontPlatformData = new FontPlatformData(desc, desc.family().family());
+ m_smallCapsFontData = new SimpleFontData(*fontPlatformData);
+ }
+ return m_smallCapsFontData;
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ // FIXME: We will need to implement this to load non-ASCII encoding sites
+ return true;
+}
+
+void SimpleFontData::determinePitch()
+{
+ m_treatAsFixedPitch = m_platformData.font() && m_platformData.font()->IsFixed();
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ if (!m_platformData.font())
+ return 0;
+
+ char charArray[4];
+ float escapements[1];
+
+ charUnicodeToUTF8HACK(glyph, charArray);
+ m_platformData.font()->GetEscapements(charArray, 1, escapements);
+ return escapements[0] * m_platformData.font()->Size();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.h b/WebCore/platform/graphics/mac/Canvas3DLayer.h
new file mode 100644
index 0000000..122ef39
--- /dev/null
+++ b/WebCore/platform/graphics/mac/Canvas3DLayer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 Canvas3DLayer_h
+#define Canvas3DLayer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#import "WebLayer.h"
+
+namespace WebCore {
+ class GraphicsLayer;
+}
+
+@interface Canvas3DLayer : CAOpenGLLayer
+{
+ WebCore::GraphicsLayer* m_layerOwner;
+ CGLContextObj m_contextObj;
+ GLuint m_texture;
+}
+
+- (id)initWithContext:(CGLContextObj)context texture:(GLuint)texture;
+
+- (CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace;
+
+@end
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // Canvas3DLayer_h
diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.mm b/WebCore/platform/graphics/mac/Canvas3DLayer.mm
new file mode 100644
index 0000000..94819d4
--- /dev/null
+++ b/WebCore/platform/graphics/mac/Canvas3DLayer.mm
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#if ENABLE(3D_CANVAS)
+
+#import "Canvas3DLayer.h"
+
+#import "GraphicsLayer.h"
+#import <QuartzCore/QuartzCore.h>
+#import <OpenGL/OpenGL.h>
+#import <wtf/RetainPtr.h>
+#include <wtf/FastMalloc.h>
+
+using namespace WebCore;
+
+@implementation Canvas3DLayer
+
+-(id)initWithContext:(CGLContextObj)context texture:(GLuint)texture
+{
+ m_contextObj = context;
+ m_texture = texture;
+ self = [super init];
+ return self;
+}
+
+-(CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
+{
+ // FIXME: The mask param tells you which display (on a multi-display system)
+ // is to be used. But since we are now getting the pixel format from the
+ // Canvas CGL context, we don't use it. This seems to do the right thing on
+ // one multi-display system. But there may be cases where this is not the case.
+ // If needed we will have to set the display mask in the Canvas CGLContext and
+ // make sure it matches.
+ UNUSED_PARAM(mask);
+ return CGLRetainPixelFormat(CGLGetPixelFormat(m_contextObj));
+}
+
+-(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
+{
+ CGLContextObj contextObj;
+ CGLCreateContext(pixelFormat, m_contextObj, &contextObj);
+ return contextObj;
+}
+
+-(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
+{
+ CGLSetCurrentContext(m_contextObj);
+ glFinish();
+ CGLSetCurrentContext(glContext);
+
+ CGRect frame = [self frame];
+
+ // draw the FBO into the layer
+ glViewport(0, 0, frame.size.width, frame.size.height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-1, 1, -1, 1, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+
+ glBegin(GL_TRIANGLE_FAN);
+ glTexCoord2f(0, 0);
+ glVertex2f(-1, -1);
+ glTexCoord2f(1, 0);
+ glVertex2f(1, -1);
+ glTexCoord2f(1, 1);
+ glVertex2f(1, 1);
+ glTexCoord2f(0, 1);
+ glVertex2f(-1, 1);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ // Call super to finalize the drawing. By default all it does is call glFlush().
+ [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];
+}
+
+static void freeData(void *, const void *data, size_t /* size */)
+{
+ fastFree(const_cast<void *>(data));
+}
+
+-(CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace
+{
+ CGLSetCurrentContext(m_contextObj);
+
+ RetainPtr<CGColorSpaceRef> imageColorSpace = colorSpace;
+ if (!imageColorSpace)
+ imageColorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
+
+ CGRect layerBounds = CGRectIntegral([self bounds]);
+
+ size_t width = layerBounds.size.width;
+ size_t height = layerBounds.size.height;
+
+ size_t rowBytes = (width * 4 + 15) & ~15;
+ size_t dataSize = rowBytes * height;
+ void* data = fastMalloc(dataSize);
+ if (!data)
+ return 0;
+
+ glPixelStorei(GL_PACK_ROW_LENGTH, rowBytes / 4);
+ glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
+
+ CGDataProviderRef provider = CGDataProviderCreateWithData(0, data, dataSize, freeData);
+ CGImageRef image = CGImageCreate(width, height, 8, 32, rowBytes, imageColorSpace.get(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ provider, 0, true,
+ kCGRenderingIntentDefault);
+ CGDataProviderRelease(provider);
+ return image;
+}
+
+@end
+
+@implementation Canvas3DLayer(WebLayerAdditions)
+
+-(void)setLayerOwner:(GraphicsLayer*)aLayer
+{
+ m_layerOwner = aLayer;
+}
+
+-(GraphicsLayer*)layerOwner
+{
+ return m_layerOwner;
+}
+
+@end
+
+#endif // ENABLE(3D_CANVAS)
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/mac/CoreTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp
index 05f29b5..265b2c3 100644
--- a/WebCore/platform/graphics/mac/CoreTextController.cpp
+++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,30 +10,24 @@
* 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.
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
-#include "CoreTextController.h"
-
-#if USE(CORE_TEXT)
+#include "ComplexTextController.h"
#include "CharacterNames.h"
#include "Font.h"
-#include "FontCache.h"
-#include "SimpleFontData.h"
#include "TextBreakIterator.h"
-#include <wtf/MathExtras.h>
using namespace std;
@@ -53,54 +47,7 @@ static inline CGFloat ceilCGFloat(CGFloat f)
return static_cast<CGFloat>(ceil(f));
}
-CoreTextController::CoreTextRun::CoreTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
- : m_CTRun(ctRun)
- , m_fontData(fontData)
- , m_characters(characters)
- , m_stringLocation(stringLocation)
- , m_stringLength(stringLength)
-{
- m_glyphCount = CTRunGetGlyphCount(ctRun);
- m_indices = CTRunGetStringIndicesPtr(ctRun);
- if (!m_indices) {
- m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
- CFDataIncreaseLength(m_indicesData.get(), m_glyphCount * sizeof(CFIndex));
- m_indices = reinterpret_cast<const CFIndex*>(CFDataGetMutableBytePtr(m_indicesData.get()));
- CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), const_cast<CFIndex*>(m_indices));
- }
-}
-
-// Missing glyphs run constructor. Core Text will not generate a run of missing glyphs, instead falling back on
-// glyphs from LastResort. We want to use the primary font's missing glyph in order to match the fast text code path.
-CoreTextController::CoreTextRun::CoreTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
- : m_fontData(fontData)
- , m_characters(characters)
- , m_stringLocation(stringLocation)
- , m_stringLength(stringLength)
-{
- Vector<CFIndex, 16> indices;
- unsigned r = 0;
- while (r < stringLength) {
- indices.append(r);
- if (U_IS_SURROGATE(characters[r])) {
- ASSERT(r + 1 < stringLength);
- ASSERT(U_IS_SURROGATE_LEAD(characters[r]));
- ASSERT(U_IS_TRAIL(characters[r + 1]));
- r += 2;
- } else
- r++;
- }
- m_glyphCount = indices.size();
- if (!ltr) {
- for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
- std::swap(indices[r], indices[end]);
- }
- m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
- CFDataAppendBytes(m_indicesData.get(), reinterpret_cast<const UInt8*>(indices.data()), m_glyphCount * sizeof(CFIndex));
- m_indices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_indicesData.get()));
-}
-
-CoreTextController::CoreTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts)
+ComplexTextController::ComplexTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts)
: m_font(*font)
, m_run(run)
, m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
@@ -111,6 +58,7 @@ CoreTextController::CoreTextController(const Font* font, const TextRun& run, boo
, m_numGlyphsSoFar(0)
, m_currentRun(0)
, m_glyphInCurrentRun(0)
+ , m_characterInCurrentGlyph(0)
, m_finalRoundingWidth(0)
, m_fallbackFonts(fallbackFonts)
, m_lastRoundingGlyph(0)
@@ -130,16 +78,12 @@ CoreTextController::CoreTextController(const Font* font, const TextRun& run, boo
m_padPerSpace = ceilf(m_run.padding() / numSpaces);
}
- collectCoreTextRuns();
+ collectComplexTextRuns();
adjustGlyphsAndAdvances();
}
-int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
+int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs)
{
- // FIXME: For positions occurring within a ligature, we should return the closest "ligature caret" or
- // approximate it by dividing the width of the ligature by the number of characters it encompasses.
- // However, Core Text does not expose a low-level API for directly finding
- // out how many characters a ligature encompasses (the "attachment count").
if (h >= m_totalWidth)
return m_run.ltr() ? m_end : 0;
if (h < 0)
@@ -147,17 +91,27 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
CGFloat x = h;
- size_t runCount = m_coreTextRuns.size();
+ size_t runCount = m_complexTextRuns.size();
size_t offsetIntoAdjustedGlyphs = 0;
for (size_t r = 0; r < runCount; ++r) {
- const CoreTextRun& coreTextRun = m_coreTextRuns[r];
- for (unsigned j = 0; j < coreTextRun.glyphCount(); ++j) {
+ const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
+ for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) {
CGFloat adjustedAdvance = m_adjustedAdvances[offsetIntoAdjustedGlyphs + j].width;
- if (x <= adjustedAdvance) {
- CFIndex hitIndex = coreTextRun.indexAt(j);
- int stringLength = coreTextRun.stringLength();
- TextBreakIterator* cursorPositionIterator = cursorMovementIterator(coreTextRun.characters(), stringLength);
+ if (x < adjustedAdvance) {
+ CFIndex hitGlyphStart = complexTextRun.indexAt(j);
+ CFIndex hitGlyphEnd;
+ if (m_run.ltr())
+ hitGlyphEnd = max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : complexTextRun.stringLength());
+ else
+ hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : complexTextRun.stringLength());
+
+ // FIXME: Instead of dividing the glyph's advance equially between the characters, this
+ // could use the glyph's "ligature carets". However, there is no Core Text API to get the
+ // ligature carets.
+ CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance);
+ int stringLength = complexTextRun.stringLength();
+ TextBreakIterator* cursorPositionIterator = cursorMovementIterator(complexTextRun.characters(), stringLength);
int clusterStart;
if (isTextBreak(cursorPositionIterator, hitIndex))
clusterStart = hitIndex;
@@ -168,45 +122,49 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
}
if (!includePartialGlyphs)
- return coreTextRun.stringLocation() + clusterStart;
+ return complexTextRun.stringLocation() + clusterStart;
int clusterEnd = textBreakFollowing(cursorPositionIterator, hitIndex);
if (clusterEnd == TextBreakDone)
clusterEnd = stringLength;
- CGFloat clusterWidth = adjustedAdvance;
- // FIXME: The search stops at the boundaries of coreTextRun. In theory, it should go on into neighboring CoreTextRuns
+ CGFloat clusterWidth;
+ // FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns
// derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no
// reordering and on font fallback should occur within a CTLine.
if (clusterEnd - clusterStart > 1) {
+ clusterWidth = adjustedAdvance;
int firstGlyphBeforeCluster = j - 1;
- while (firstGlyphBeforeCluster >= 0 && coreTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
+ while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
clusterWidth += width;
x += width;
firstGlyphBeforeCluster--;
}
unsigned firstGlyphAfterCluster = j + 1;
- while (firstGlyphAfterCluster < coreTextRun.glyphCount() && coreTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
+ while (firstGlyphAfterCluster < complexTextRun.glyphCount() && complexTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
firstGlyphAfterCluster++;
}
+ } else {
+ clusterWidth = adjustedAdvance / (hitGlyphEnd - hitGlyphStart);
+ x -= clusterWidth * (m_run.ltr() ? hitIndex - hitGlyphStart : hitGlyphEnd - hitIndex - 1);
}
if (x <= clusterWidth / 2)
- return coreTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
+ return complexTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
else
- return coreTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart);
+ return complexTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart);
}
x -= adjustedAdvance;
}
- offsetIntoAdjustedGlyphs += coreTextRun.glyphCount();
+ offsetIntoAdjustedGlyphs += complexTextRun.glyphCount();
}
ASSERT_NOT_REACHED();
return 0;
}
-void CoreTextController::collectCoreTextRuns()
+void ComplexTextController::collectComplexTextRuns()
{
if (!m_end)
return;
@@ -227,7 +185,7 @@ void CoreTextController::collectCoreTextRuns()
static const UChar hyphen = '-';
if (hasTrailingSoftHyphen && m_run.rtl()) {
- collectCoreTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
+ collectComplexTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
indexOfFontTransition--;
curr--;
}
@@ -290,7 +248,7 @@ void CoreTextController::collectCoreTextRuns()
if (nextGlyphData.fontData != glyphData.fontData || nextIsSmallCaps != isSmallCaps || !nextGlyphData.glyph != !glyphData.glyph) {
int itemStart = m_run.rtl() ? index + 1 : indexOfFontTransition;
int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition;
- collectCoreTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, glyphData.glyph ? glyphData.fontData : 0);
+ collectComplexTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, glyphData.glyph ? glyphData.fontData : 0);
indexOfFontTransition = index;
}
}
@@ -298,19 +256,15 @@ void CoreTextController::collectCoreTextRuns()
int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : m_end - indexOfFontTransition - (hasTrailingSoftHyphen ? 1 : 0);
if (itemLength) {
int itemStart = m_run.rtl() ? 0 : indexOfFontTransition;
- collectCoreTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, nextGlyphData.glyph ? nextGlyphData.fontData : 0);
+ collectComplexTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, nextGlyphData.glyph ? nextGlyphData.fontData : 0);
}
if (hasTrailingSoftHyphen && m_run.ltr())
- collectCoreTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
+ collectComplexTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
}
-void CoreTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
+void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
{
- // FIXME: For offsets falling inside a ligature, we should advance only as far as the appropriate "ligature caret"
- // or divide the width of the ligature by the number of offsets it encompasses and make an advance proportional
- // to the offsets into the ligature. However, Core Text does not expose a low-level API for
- // directly finding out how many characters a ligature encompasses (the "attachment count").
if (static_cast<int>(offset) > m_end)
offset = m_end;
@@ -319,24 +273,44 @@ void CoreTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
m_currentCharacter = offset;
- size_t runCount = m_coreTextRuns.size();
+ size_t runCount = m_complexTextRuns.size();
bool ltr = m_run.ltr();
unsigned k = ltr ? m_numGlyphsSoFar : m_adjustedGlyphs.size() - 1 - m_numGlyphsSoFar;
while (m_currentRun < runCount) {
- const CoreTextRun& coreTextRun = m_coreTextRuns[ltr ? m_currentRun : runCount - 1 - m_currentRun];
- size_t glyphCount = coreTextRun.glyphCount();
+ const ComplexTextRun& complexTextRun = *m_complexTextRuns[ltr ? m_currentRun : runCount - 1 - m_currentRun];
+ size_t glyphCount = complexTextRun.glyphCount();
unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
while (m_glyphInCurrentRun < glyphCount) {
- if (coreTextRun.indexAt(g) + coreTextRun.stringLocation() >= m_currentCharacter)
- return;
+ unsigned glyphStartOffset = complexTextRun.indexAt(g);
+ unsigned glyphEndOffset;
+ if (ltr)
+ glyphEndOffset = max<unsigned>(glyphStartOffset, g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.stringLength());
+ else
+ glyphEndOffset = max<unsigned>(glyphStartOffset, g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.stringLength());
+
CGSize adjustedAdvance = m_adjustedAdvances[k];
- if (glyphBuffer)
- glyphBuffer->add(m_adjustedGlyphs[k], coreTextRun.fontData(), adjustedAdvance);
- m_runWidthSoFar += adjustedAdvance.width;
+
+ if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter)
+ return;
+
+ if (glyphBuffer && !m_characterInCurrentGlyph)
+ glyphBuffer->add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance);
+
+ unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
+ m_characterInCurrentGlyph = min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
+ // FIXME: Instead of dividing the glyph's advance equially between the characters, this
+ // could use the glyph's "ligature carets". However, there is no Core Text API to get the
+ // ligature carets.
+ m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset);
+
+ if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter)
+ return;
+
m_numGlyphsSoFar++;
m_glyphInCurrentRun++;
+ m_characterInCurrentGlyph = 0;
if (ltr) {
g++;
k++;
@@ -352,100 +326,35 @@ void CoreTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
m_runWidthSoFar += m_finalRoundingWidth;
}
-void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
-{
- if (!fontData) {
- // Create a run of missing glyphs from the primary font.
- m_coreTextRuns.append(CoreTextRun(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
- return;
- }
-
- if (m_fallbackFonts && fontData != m_font.primaryFont())
- m_fallbackFonts->add(fontData);
-
- RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
-
- RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes()));
-
- RetainPtr<CTTypesetterRef> typesetter;
-
- if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) {
- static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
- static const void* ltrOptionValues[] = { kCFBooleanFalse };
- static const void* rtlOptionValues[] = { kCFBooleanTrue };
- 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()));
-
- RetainPtr<CTLineRef> line(AdoptCF, CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0)));
-
- CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
-
- CFIndex runCount = CFArrayGetCount(runArray);
-
- for (CFIndex r = 0; r < runCount; r++) {
- CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
- ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
- m_coreTextRuns.append(CoreTextRun(ctRun, fontData, cp, stringLocation, length));
- }
-}
-
-void CoreTextController::adjustGlyphsAndAdvances()
+void ComplexTextController::adjustGlyphsAndAdvances()
{
- size_t runCount = m_coreTextRuns.size();
+ size_t runCount = m_complexTextRuns.size();
for (size_t r = 0; r < runCount; ++r) {
- const CoreTextRun& coreTextRun = m_coreTextRuns[r];
- unsigned glyphCount = coreTextRun.glyphCount();
- const SimpleFontData* fontData = coreTextRun.fontData();
-
- Vector<CGGlyph, 256> glyphsVector;
- const CGGlyph* glyphs;
-
- Vector<CGSize, 256> advancesVector;
- const CGSize* advances;
-
- if (coreTextRun.ctRun()) {
- glyphs = CTRunGetGlyphsPtr(coreTextRun.ctRun());
- if (!glyphs) {
- glyphsVector.grow(glyphCount);
- CTRunGetGlyphs(coreTextRun.ctRun(), CFRangeMake(0, 0), glyphsVector.data());
- glyphs = glyphsVector.data();
- }
+ const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
+ unsigned glyphCount = complexTextRun.glyphCount();
+ const SimpleFontData* fontData = complexTextRun.fontData();
- advances = CTRunGetAdvancesPtr(coreTextRun.ctRun());
- if (!advances) {
- advancesVector.grow(glyphCount);
- CTRunGetAdvances(coreTextRun.ctRun(), CFRangeMake(0, 0), advancesVector.data());
- advances = advancesVector.data();
- }
- } else {
- // Synthesize a run of missing glyphs.
- glyphsVector.fill(0, glyphCount);
- glyphs = glyphsVector.data();
- advancesVector.fill(CGSizeMake(fontData->widthForGlyph(0), 0), glyphCount);
- advances = advancesVector.data();
- }
+ const CGGlyph* glyphs = complexTextRun.glyphs();
+ const CGSize* advances = complexTextRun.advances();
bool lastRun = r + 1 == runCount;
- const UChar* cp = coreTextRun.characters();
+ const UChar* cp = complexTextRun.characters();
CGFloat roundedSpaceWidth = roundCGFloat(fontData->spaceWidth());
bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();
bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled();
for (unsigned i = 0; i < glyphCount; i++) {
- CFIndex characterIndex = coreTextRun.indexAt(i);
+ CFIndex characterIndex = complexTextRun.indexAt(i);
UChar ch = *(cp + characterIndex);
bool lastGlyph = lastRun && i + 1 == glyphCount;
UChar nextCh;
if (lastGlyph)
nextCh = ' ';
else if (i + 1 < glyphCount)
- nextCh = *(cp + coreTextRun.indexAt(i + 1));
+ nextCh = *(cp + complexTextRun.indexAt(i + 1));
else
- nextCh = *(m_coreTextRuns[r + 1].characters() + m_coreTextRuns[r + 1].indexAt(0));
+ nextCh = *(m_complexTextRuns[r + 1]->characters() + m_complexTextRuns[r + 1]->indexAt(0));
bool treatAsSpace = Font::treatAsSpace(ch);
CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i];
@@ -533,5 +442,3 @@ void CoreTextController::adjustGlyphsAndAdvances()
}
} // namespace WebCore
-
-#endif // USE(CORE_TEXT)
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h
new file mode 100644
index 0000000..7a915e2
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextController.h
@@ -0,0 +1,162 @@
+/*
+ * 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ComplexTextController_h
+#define ComplexTextController_h
+
+#include "GlyphBuffer.h"
+#include <wtf/HashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+class Font;
+class SimpleFontData;
+class TextRun;
+
+class ComplexTextController {
+public:
+ ComplexTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0);
+
+ // Advance and emit glyphs up to the specified character.
+ void advance(unsigned to, GlyphBuffer* = 0);
+
+ // Compute the character offset for a given x coordinate.
+ int offsetForPosition(int x, bool includePartialGlyphs);
+
+ // Returns the width of everything we've consumed so far.
+ float runWidthSoFar() const { return m_runWidthSoFar; }
+
+ float totalWidth() const { return m_totalWidth; }
+
+ // Extra width to the left of the leftmost glyph.
+ float finalRoundingWidth() const { return m_finalRoundingWidth; }
+
+private:
+ class ComplexTextRun : public RefCounted<ComplexTextRun> {
+ public:
+#if USE(CORE_TEXT)
+ static PassRefPtr<ComplexTextRun> create(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
+ {
+ return adoptRef(new ComplexTextRun(ctRun, fontData, characters, stringLocation, stringLength));
+ }
+#elif USE(ATSUI)
+ static PassRefPtr<ComplexTextRun> create(ATSUTextLayout atsuTextLayout, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride)
+ {
+ return adoptRef(new ComplexTextRun(atsuTextLayout, fontData, characters, stringLocation, stringLength, ltr, directionalOverride));
+ }
+#endif
+ static PassRefPtr<ComplexTextRun> create(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
+ {
+ return adoptRef(new ComplexTextRun(fontData, characters, stringLocation, stringLength, ltr));
+ }
+
+ unsigned glyphCount() const { return m_glyphCount; }
+ const SimpleFontData* fontData() const { return m_fontData; }
+ const UChar* characters() const { return m_characters; }
+ unsigned stringLocation() const { return m_stringLocation; }
+ size_t stringLength() const { return m_stringLength; }
+ CFIndex indexAt(size_t i) const { return m_indices[i]; }
+ const CGGlyph* glyphs() const { return m_glyphs; }
+ const CGSize* advances() const { return m_advances; }
+
+ private:
+#if USE(CORE_TEXT)
+ ComplexTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength);
+#elif USE(ATSUI)
+ ComplexTextRun(ATSUTextLayout, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride);
+#endif
+ ComplexTextRun(const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr);
+
+#if USE(ATSUI)
+#ifdef BUILDING_ON_TIGER
+ typedef UInt32 URefCon;
+#endif
+ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef, URefCon, void*, ATSULayoutOperationCallbackStatus*);
+#endif
+
+#if USE(CORE_TEXT)
+ RetainPtr<CTRunRef> m_CTRun;
+#endif
+ unsigned m_glyphCount;
+ const SimpleFontData* m_fontData;
+ const UChar* m_characters;
+ unsigned m_stringLocation;
+ size_t m_stringLength;
+#if USE(CORE_TEXT)
+ RetainPtr<CFMutableDataRef> m_indicesData;
+ const CFIndex* m_indices;
+#elif USE(ATSUI)
+ Vector<CFIndex, 64> m_indices;
+#endif
+ Vector<CGGlyph, 64> m_glyphsVector;
+ const CGGlyph* m_glyphs;
+ Vector<CGSize, 64> m_advancesVector;
+ const CGSize* m_advances;
+#if USE(ATSUI)
+ bool m_ltr;
+ bool m_directionalOverride;
+#endif
+ };
+
+ void collectComplexTextRuns();
+ void collectComplexTextRunsForCharacters(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*);
+ void adjustGlyphsAndAdvances();
+
+ const Font& m_font;
+ const TextRun& m_run;
+ bool m_mayUseNaturalWritingDirection;
+
+ Vector<UChar, 256> m_smallCapsBuffer;
+
+ Vector<RefPtr<ComplexTextRun>, 16> m_complexTextRuns;
+ Vector<CGSize, 256> m_adjustedAdvances;
+ Vector<CGGlyph, 256> m_adjustedGlyphs;
+
+ unsigned m_currentCharacter;
+ int m_end;
+
+ CGFloat m_totalWidth;
+
+ float m_runWidthSoFar;
+ unsigned m_numGlyphsSoFar;
+ size_t m_currentRun;
+ unsigned m_glyphInCurrentRun;
+ unsigned m_characterInCurrentGlyph;
+ float m_finalRoundingWidth;
+ float m_padding;
+ float m_padPerSpace;
+
+ HashSet<const SimpleFontData*>* m_fallbackFonts;
+
+ unsigned m_lastRoundingGlyph;
+};
+
+} // namespace WebCore
+
+#endif // ComplexTextController_h
diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
new file mode 100644
index 0000000..78c588f
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006, 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
+ * 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 "ComplexTextController.h"
+
+#if USE(ATSUI)
+
+#include "CharacterNames.h"
+#include "Font.h"
+#include "ShapeArabic.h"
+
+#ifdef __LP64__
+// ATSUTextInserted() is SPI in 64-bit.
+extern "C" {
+OSStatus ATSUTextInserted(ATSUTextLayout iTextLayout, UniCharArrayOffset iInsertionLocation, UniCharCount iInsertionLength);
+}
+#endif
+
+using namespace WTF::Unicode;
+
+namespace WebCore {
+
+OSStatus ComplexTextController::ComplexTextRun::overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef atsuLineRef, URefCon refCon, void*, ATSULayoutOperationCallbackStatus* callbackStatus)
+{
+ ComplexTextRun* complexTextRun = reinterpret_cast<ComplexTextRun*>(refCon);
+ OSStatus status;
+ ItemCount count;
+ ATSLayoutRecord *layoutRecords;
+
+ status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(atsuLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, reinterpret_cast<void**>(&layoutRecords), &count);
+ if (status != noErr) {
+ *callbackStatus = kATSULayoutOperationCallbackStatusContinue;
+ return status;
+ }
+
+ count--;
+ ItemCount j = 0;
+ CFIndex indexOffset = 0;
+
+ if (complexTextRun->m_directionalOverride) {
+ j++;
+ count -= 2;
+ indexOffset = -1;
+ }
+
+ complexTextRun->m_glyphCount = count;
+ complexTextRun->m_glyphsVector.reserveCapacity(count);
+ complexTextRun->m_advancesVector.reserveCapacity(count);
+ complexTextRun->m_indices.reserveCapacity(count);
+
+ bool atBeginning = true;
+ CGFloat lastX = 0;
+
+ for (ItemCount i = 0; i < count; ++i, ++j) {
+ if (layoutRecords[j].glyphID == kATSDeletedGlyphcode) {
+ complexTextRun->m_glyphCount--;
+ continue;
+ }
+ complexTextRun->m_glyphsVector.uncheckedAppend(layoutRecords[j].glyphID);
+ complexTextRun->m_indices.uncheckedAppend(layoutRecords[j].originalOffset / 2 + indexOffset);
+ CGFloat x = FixedToFloat(layoutRecords[j].realPos);
+ if (!atBeginning)
+ complexTextRun->m_advancesVector.uncheckedAppend(CGSizeMake(x - lastX, 0));
+ lastX = x;
+ atBeginning = false;
+ }
+
+ complexTextRun->m_advancesVector.uncheckedAppend(CGSizeMake(FixedToFloat(layoutRecords[j].realPos) - lastX, 0));
+
+ complexTextRun->m_glyphs = complexTextRun->m_glyphsVector.data();
+ complexTextRun->m_advances = complexTextRun->m_advancesVector.data();
+
+ status = ATSUDirectReleaseLayoutDataArrayPtr(atsuLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, reinterpret_cast<void**>(&layoutRecords));
+ *callbackStatus = kATSULayoutOperationCallbackStatusContinue;
+ return noErr;
+}
+
+static inline bool isArabicLamWithAlefLigature(UChar c)
+{
+ return c >= 0xfef5 && c <= 0xfefc;
+}
+
+static void shapeArabic(const UChar* source, UChar* dest, unsigned totalLength)
+{
+ unsigned shapingStart = 0;
+ while (shapingStart < totalLength) {
+ unsigned shapingEnd;
+ // We do not want to pass a Lam with Alef ligature followed by a space to the shaper,
+ // since we want to be able to identify this sequence as the result of shaping a Lam
+ // followed by an Alef and padding with a space.
+ bool foundLigatureSpace = false;
+ for (shapingEnd = shapingStart; !foundLigatureSpace && shapingEnd < totalLength - 1; ++shapingEnd)
+ foundLigatureSpace = isArabicLamWithAlefLigature(source[shapingEnd]) && source[shapingEnd + 1] == ' ';
+ shapingEnd++;
+
+ UErrorCode shapingError = U_ZERO_ERROR;
+ unsigned charsWritten = shapeArabic(source + shapingStart, shapingEnd - shapingStart, dest + shapingStart, shapingEnd - shapingStart, U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR, &shapingError);
+
+ if (U_SUCCESS(shapingError) && charsWritten == shapingEnd - shapingStart) {
+ for (unsigned j = shapingStart; j < shapingEnd - 1; ++j) {
+ if (isArabicLamWithAlefLigature(dest[j]) && dest[j + 1] == ' ')
+ dest[++j] = zeroWidthSpace;
+ }
+ if (foundLigatureSpace) {
+ dest[shapingEnd] = ' ';
+ shapingEnd++;
+ } else if (isArabicLamWithAlefLigature(dest[shapingEnd - 1])) {
+ // u_shapeArabic quirk: if the last two characters in the source string are a Lam and an Alef,
+ // the space is put at the beginning of the string, despite U_SHAPE_LENGTH_FIXED_SPACES_NEAR.
+ ASSERT(dest[shapingStart] == ' ');
+ dest[shapingStart] = zeroWidthSpace;
+ }
+ } else {
+ // Something went wrong. Abandon shaping and just copy the rest of the buffer.
+ LOG_ERROR("u_shapeArabic failed(%d)", shapingError);
+ shapingEnd = totalLength;
+ memcpy(dest + shapingStart, source + shapingStart, (shapingEnd - shapingStart) * sizeof(UChar));
+ }
+ shapingStart = shapingEnd;
+ }
+}
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(ATSUTextLayout atsuTextLayout, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride)
+ : m_fontData(fontData)
+ , m_characters(characters)
+ , m_stringLocation(stringLocation)
+ , m_stringLength(stringLength)
+ , m_ltr(ltr)
+ , m_directionalOverride(directionalOverride)
+{
+ OSStatus status;
+
+ status = ATSUSetTextLayoutRefCon(atsuTextLayout, reinterpret_cast<URefCon>(this));
+
+ ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;
+
+ Boolean rtl = !ltr;
+
+ Vector<UChar, 256> substituteCharacters;
+ bool shouldCheckForMirroring = !ltr && !fontData->m_ATSUMirrors;
+ bool shouldCheckForArabic = !fontData->shapesArabic();
+ bool shouldShapeArabic = false;
+
+ bool mirrored = false;
+ for (size_t i = 0; i < stringLength; ++i) {
+ if (shouldCheckForMirroring) {
+ UChar mirroredChar = u_charMirror(characters[i]);
+ if (mirroredChar != characters[i]) {
+ if (!mirrored) {
+ mirrored = true;
+ substituteCharacters.grow(stringLength);
+ memcpy(substituteCharacters.data(), characters, stringLength * sizeof(UChar));
+ ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
+ }
+ substituteCharacters[i] = mirroredChar;
+ }
+ }
+ if (shouldCheckForArabic && isArabicChar(characters[i])) {
+ shouldCheckForArabic = false;
+ shouldShapeArabic = true;
+ }
+ }
+
+ if (shouldShapeArabic) {
+ Vector<UChar, 256> shapedArabic(stringLength);
+ shapeArabic(substituteCharacters.isEmpty() ? characters : substituteCharacters.data(), shapedArabic.data(), stringLength);
+ substituteCharacters.swap(shapedArabic);
+ ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
+ }
+
+ if (directionalOverride) {
+ UChar override = ltr ? leftToRightOverride : rightToLeftOverride;
+ if (substituteCharacters.isEmpty()) {
+ substituteCharacters.grow(stringLength + 2);
+ substituteCharacters[0] = override;
+ memcpy(substituteCharacters.data() + 1, characters, stringLength * sizeof(UChar));
+ substituteCharacters[stringLength + 1] = popDirectionalFormatting;
+ ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
+ } else {
+ substituteCharacters.prepend(override);
+ substituteCharacters.append(popDirectionalFormatting);
+ }
+ ATSUTextInserted(atsuTextLayout, 0, 2);
+ }
+
+ ATSULayoutOperationOverrideSpecifier overrideSpecifier;
+ overrideSpecifier.operationSelector = kATSULayoutOperationPostLayoutAdjustment;
+ overrideSpecifier.overrideUPP = overrideLayoutOperation;
+
+ ATSUAttributeTag tags[] = { kATSULineLayoutOptionsTag, kATSULineDirectionTag, kATSULayoutOperationOverrideTag };
+ ByteCount sizes[] = { sizeof(ATSLineLayoutOptions), sizeof(Boolean), sizeof(ATSULayoutOperationOverrideSpecifier) };
+ ATSUAttributeValuePtr values[] = { &lineLayoutOptions, &rtl, &overrideSpecifier };
+
+ status = ATSUSetLayoutControls(atsuTextLayout, 3, tags, sizes, values);
+
+ ItemCount boundsCount;
+ status = ATSUGetGlyphBounds(atsuTextLayout, 0, 0, 0, m_stringLength, kATSUseFractionalOrigins, 0, 0, &boundsCount);
+
+ status = ATSUDisposeTextLayout(atsuTextLayout);
+}
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
+ : m_fontData(fontData)
+ , m_characters(characters)
+ , m_stringLocation(stringLocation)
+ , m_stringLength(stringLength)
+{
+ m_indices.reserveCapacity(stringLength);
+ unsigned r = 0;
+ while (r < stringLength) {
+ m_indices.uncheckedAppend(r);
+ if (U_IS_SURROGATE(characters[r])) {
+ ASSERT(r + 1 < stringLength);
+ ASSERT(U_IS_SURROGATE_LEAD(characters[r]));
+ ASSERT(U_IS_TRAIL(characters[r + 1]));
+ r += 2;
+ } else
+ r++;
+ }
+ m_glyphCount = m_indices.size();
+ if (!ltr) {
+ for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
+ std::swap(m_indices[r], m_indices[end]);
+ }
+
+ m_glyphsVector.fill(0, m_glyphCount);
+ m_glyphs = m_glyphsVector.data();
+ m_advancesVector.fill(CGSizeMake(fontData->widthForGlyph(0), 0), m_glyphCount);
+ m_advances = m_advancesVector.data();
+}
+
+static bool fontHasMirroringInfo(ATSUFontID fontID)
+{
+ ByteCount propTableSize;
+ OSStatus status = ATSFontGetTable(fontID, 'prop', 0, 0, 0, &propTableSize);
+ if (status == noErr) // naively assume that if a 'prop' table exists then it contains mirroring info
+ return true;
+ else if (status != kATSInvalidFontTableAccess) // anything other than a missing table is logged as an error
+ LOG_ERROR("ATSFontGetTable failed (%d)", static_cast<int>(status));
+
+ return false;
+}
+
+static void disableLigatures(const SimpleFontData* fontData, TextRenderingMode textMode)
+{
+ // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are
+ // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example.
+ // See bugzilla 5166.
+ if (textMode == OptimizeLegibility || textMode == GeometricPrecision || fontData->platformData().allowsLigatures())
+ return;
+
+ ATSUFontFeatureType featureTypes[] = { kLigaturesType };
+ ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector };
+ OSStatus status = ATSUSetFontFeatures(fontData->m_ATSUStyle, 1, featureTypes, featureSelectors);
+ if (status != noErr)
+ LOG_ERROR("ATSUSetFontFeatures failed (%d) -- ligatures remain enabled", static_cast<int>(status));
+}
+
+static void initializeATSUStyle(const SimpleFontData* fontData, TextRenderingMode textMode)
+{
+ if (fontData->m_ATSUStyleInitialized)
+ return;
+
+ ATSUFontID fontID = fontData->platformData().m_atsuFontID;
+ if (!fontID) {
+ LOG_ERROR("unable to get ATSUFontID for %p", fontData->platformData().font());
+ return;
+ }
+
+ OSStatus status = ATSUCreateStyle(&fontData->m_ATSUStyle);
+ if (status != noErr)
+ LOG_ERROR("ATSUCreateStyle failed (%d)", static_cast<int>(status));
+
+ Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
+ Fract kerningInhibitFactor = FloatToFract(1);
+ static CGAffineTransform verticalFlip = CGAffineTransformMakeScale(1, -1);
+
+ ByteCount styleSizes[4] = { sizeof(fontSize), sizeof(fontID), sizeof(verticalFlip), sizeof(kerningInhibitFactor) };
+ ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
+ ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &verticalFlip, &kerningInhibitFactor };
+
+ bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision;
+ status = ATSUSetAttributes(fontData->m_ATSUStyle, allowKerning ? 3 : 4, styleTags, styleSizes, styleValues);
+ if (status != noErr)
+ LOG_ERROR("ATSUSetAttributes failed (%d)", static_cast<int>(status));
+
+ fontData->m_ATSUMirrors = fontHasMirroringInfo(fontID);
+
+ disableLigatures(fontData, textMode);
+
+ fontData->m_ATSUStyleInitialized = true;
+}
+
+void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
+{
+ if (!fontData) {
+ // Create a run of missing glyphs from the primary font.
+ m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
+ return;
+ }
+
+ if (m_fallbackFonts && fontData != m_font.primaryFont())
+ m_fallbackFonts->add(fontData);
+
+ initializeATSUStyle(fontData, m_font.fontDescription().textRenderingMode());
+
+ OSStatus status;
+ ATSUTextLayout atsuTextLayout;
+ UniCharCount runLength = length;
+
+ status = ATSUCreateTextLayoutWithTextPtr(cp, 0, length, length, 1, &runLength, &fontData->m_ATSUStyle, &atsuTextLayout);
+ if (status != noErr) {
+ LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed with error %d", static_cast<int>(status));
+ return;
+ }
+ m_complexTextRuns.append(ComplexTextRun::create(atsuTextLayout, fontData, cp, stringLocation, length, m_run.ltr(), m_run.directionalOverride()));
+}
+
+} // namespace WebCore
+
+#endif // USE(ATSUI)
diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
new file mode 100644
index 0000000..c9daf84
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ComplexTextController.h"
+
+#if USE(CORE_TEXT)
+
+#include "Font.h"
+
+namespace WebCore {
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
+ : m_CTRun(ctRun)
+ , m_fontData(fontData)
+ , m_characters(characters)
+ , m_stringLocation(stringLocation)
+ , m_stringLength(stringLength)
+{
+ m_glyphCount = CTRunGetGlyphCount(m_CTRun.get());
+ m_indices = CTRunGetStringIndicesPtr(m_CTRun.get());
+ if (!m_indices) {
+ m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
+ CFDataIncreaseLength(m_indicesData.get(), m_glyphCount * sizeof(CFIndex));
+ m_indices = reinterpret_cast<const CFIndex*>(CFDataGetMutableBytePtr(m_indicesData.get()));
+ CTRunGetStringIndices(m_CTRun.get(), CFRangeMake(0, 0), const_cast<CFIndex*>(m_indices));
+ }
+
+ m_glyphs = CTRunGetGlyphsPtr(m_CTRun.get());
+ if (!m_glyphs) {
+ m_glyphsVector.grow(m_glyphCount);
+ CTRunGetGlyphs(m_CTRun.get(), CFRangeMake(0, 0), m_glyphsVector.data());
+ m_glyphs = m_glyphsVector.data();
+ }
+
+ m_advances = CTRunGetAdvancesPtr(m_CTRun.get());
+ if (!m_advances) {
+ m_advancesVector.grow(m_glyphCount);
+ CTRunGetAdvances(m_CTRun.get(), CFRangeMake(0, 0), m_advancesVector.data());
+ m_advances = m_advancesVector.data();
+ }
+
+}
+
+// Missing glyphs run constructor. Core Text will not generate a run of missing glyphs, instead falling back on
+// glyphs from LastResort. We want to use the primary font's missing glyph in order to match the fast text code path.
+ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
+ : m_fontData(fontData)
+ , m_characters(characters)
+ , m_stringLocation(stringLocation)
+ , m_stringLength(stringLength)
+{
+ Vector<CFIndex, 16> indices;
+ unsigned r = 0;
+ while (r < stringLength) {
+ indices.append(r);
+ if (U_IS_SURROGATE(characters[r])) {
+ ASSERT(r + 1 < stringLength);
+ ASSERT(U_IS_SURROGATE_LEAD(characters[r]));
+ ASSERT(U_IS_TRAIL(characters[r + 1]));
+ r += 2;
+ } else
+ r++;
+ }
+ m_glyphCount = indices.size();
+ if (!ltr) {
+ for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
+ std::swap(indices[r], indices[end]);
+ }
+ m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
+ CFDataAppendBytes(m_indicesData.get(), reinterpret_cast<const UInt8*>(indices.data()), m_glyphCount * sizeof(CFIndex));
+ m_indices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_indicesData.get()));
+
+ // Synthesize a run of missing glyphs.
+ m_glyphsVector.fill(0, m_glyphCount);
+ m_glyphs = m_glyphsVector.data();
+ m_advancesVector.fill(CGSizeMake(m_fontData->widthForGlyph(0), 0), m_glyphCount);
+ m_advances = m_advancesVector.data();
+}
+
+void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
+{
+ if (!fontData) {
+ // Create a run of missing glyphs from the primary font.
+ m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
+ return;
+ }
+
+ if (m_fallbackFonts && fontData != m_font.primaryFont())
+ m_fallbackFonts->add(fontData);
+
+ RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
+
+ RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.fontDescription().textRenderingMode())));
+
+ RetainPtr<CTTypesetterRef> typesetter;
+
+ if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) {
+ static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
+ static const void* ltrOptionValues[] = { kCFBooleanFalse };
+ static const void* rtlOptionValues[] = { kCFBooleanTrue };
+ 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()));
+
+ RetainPtr<CTLineRef> line(AdoptCF, CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0)));
+
+ CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
+
+ CFIndex runCount = CFArrayGetCount(runArray);
+
+ for (CFIndex r = 0; r < runCount; r++) {
+ CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
+ ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
+ m_complexTextRuns.append(ComplexTextRun::create(ctRun, fontData, cp, stringLocation, length));
+ }
+}
+
+} // namespace WebCore
+
+#endif // USE(CORE_TEXT)
diff --git a/WebCore/platform/graphics/mac/CoreTextController.h b/WebCore/platform/graphics/mac/CoreTextController.h
deleted file mode 100644
index 4dd6f93..0000000
--- a/WebCore/platform/graphics/mac/CoreTextController.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 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
- * 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 CoreTextController_h
-#define CoreTextController_h
-
-#if USE(CORE_TEXT)
-
-#include "Font.h"
-#include "GlyphBuffer.h"
-#include <wtf/RetainPtr.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class CoreTextController {
-public:
- CoreTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0);
-
- // Advance and emit glyphs up to the specified character.
- void advance(unsigned to, GlyphBuffer* = 0);
-
- // Compute the character offset for a given x coordinate.
- int offsetForPosition(int x, bool includePartialGlyphs);
-
- // Returns the width of everything we've consumed so far.
- float runWidthSoFar() const { return m_runWidthSoFar; }
-
- float totalWidth() const { return m_totalWidth; }
-
- // Extra width to the left of the leftmost glyph.
- float finalRoundingWidth() const { return m_finalRoundingWidth; }
-
-private:
- class CoreTextRun {
- public:
- CoreTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength);
- CoreTextRun(const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr);
-
- CTRunRef ctRun() const { return m_CTRun.get(); }
- unsigned glyphCount() const { return m_glyphCount; }
- const SimpleFontData* fontData() const { return m_fontData; }
- const UChar* characters() const { return m_characters; }
- unsigned stringLocation() const { return m_stringLocation; }
- size_t stringLength() const { return m_stringLength; }
- CFIndex indexAt(size_t i) const { return m_indices[i]; }
-
- private:
- RetainPtr<CTRunRef> m_CTRun;
- unsigned m_glyphCount;
- const SimpleFontData* m_fontData;
- const UChar* m_characters;
- unsigned m_stringLocation;
- size_t m_stringLength;
- const CFIndex* m_indices;
- // Used only if CTRunGet*Ptr fails or if this is a missing glyphs run.
- RetainPtr<CFMutableDataRef> m_indicesData;
- };
-
- void collectCoreTextRuns();
- void collectCoreTextRunsForCharacters(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*);
- void adjustGlyphsAndAdvances();
-
- const Font& m_font;
- const TextRun& m_run;
- bool m_mayUseNaturalWritingDirection;
-
- Vector<UChar, 256> m_smallCapsBuffer;
-
- Vector<CoreTextRun, 16> m_coreTextRuns;
- Vector<CGSize, 256> m_adjustedAdvances;
- Vector<CGGlyph, 256> m_adjustedGlyphs;
-
- unsigned m_currentCharacter;
- int m_end;
-
- CGFloat m_totalWidth;
-
- float m_runWidthSoFar;
- unsigned m_numGlyphsSoFar;
- size_t m_currentRun;
- unsigned m_glyphInCurrentRun;
- float m_finalRoundingWidth;
- float m_padding;
- float m_padPerSpace;
-
- HashSet<const SimpleFontData*>* m_fallbackFonts;
-
- unsigned m_lastRoundingGlyph;
-};
-
-} // namespace WebCore
-#endif // USE(CORE_TEXT)
-#endif // CoreTextController_h
diff --git a/WebCore/platform/graphics/mac/FontMacCoreText.cpp b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
index 9dffc7a..0db2601 100644
--- a/WebCore/platform/graphics/mac/FontMacCoreText.cpp
+++ b/WebCore/platform/graphics/mac/FontComplexTextMac.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
@@ -10,25 +10,22 @@
* 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.
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "Font.h"
-#if USE(CORE_TEXT)
-
-#include "CoreTextController.h"
+#include "ComplexTextController.h"
#include "FontFallbackList.h"
#include "GlyphBuffer.h"
#include "GraphicsContext.h"
@@ -41,7 +38,7 @@ namespace WebCore {
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h,
int from, int to) const
{
- CoreTextController controller(this, run);
+ ComplexTextController controller(this, run);
controller.advance(from);
float beforeWidth = controller.runWidthSoFar();
controller.advance(to);
@@ -63,7 +60,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
GlyphBuffer glyphBuffer;
float startX = point.x();
- CoreTextController controller(this, run);
+ ComplexTextController controller(this, run);
controller.advance(from);
float beforeWidth = controller.runWidthSoFar();
controller.advance(to, &glyphBuffer);
@@ -88,15 +85,14 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
{
- CoreTextController controller(this, run, true, fallbackFonts);
+ ComplexTextController controller(this, run, true, fallbackFonts);
return controller.totalWidth();
}
int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const
{
- CoreTextController controller(this, run);
+ ComplexTextController controller(this, run);
return controller.offsetForPosition(x, includePartialGlyphs);
}
-}
-#endif // USE(CORE_TEXT)
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
index e40bbab..256b5a4 100644
--- a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
@@ -24,6 +24,7 @@
#include <ApplicationServices/ApplicationServices.h>
#include "SharedBuffer.h"
#include "FontPlatformData.h"
+#include "OpenTypeSanitizer.h"
namespace WebCore {
@@ -43,14 +44,24 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
{
ASSERT_ARG(buffer, buffer);
+#if ENABLE(OPENTYPE_SANITIZER)
+ OpenTypeSanitizer sanitizer(buffer);
+ RefPtr<SharedBuffer> transcodeBuffer = sanitizer.sanitize();
+ if (!transcodeBuffer)
+ return 0; // validation failed.
+ buffer = transcodeBuffer.get();
+#endif
+
ATSFontContainerRef containerRef = 0;
ATSFontRef fontRef = 0;
+ RetainPtr<CGFontRef> cgFontRef;
+
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
RetainPtr<CFDataRef> bufferData(AdoptCF, buffer->createCFData());
RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(bufferData.get()));
- CGFontRef cgFontRef = CGFontCreateWithDataProvider(dataProvider.get());
+ cgFontRef.adoptCF(CGFontCreateWithDataProvider(dataProvider.get()));
if (!cgFontRef)
return 0;
#else
@@ -75,13 +86,11 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
return 0;
}
- CGFontRef cgFontRef = CGFontCreateWithPlatformFont(&fontRef);
+ cgFontRef.adoptCF(CGFontCreateWithPlatformFont(&fontRef));
#ifndef BUILDING_ON_TIGER
// Workaround for <rdar://problem/5675504>.
- if (cgFontRef && !CGFontGetNumberOfGlyphs(cgFontRef)) {
- CFRelease(cgFontRef);
+ if (cgFontRef && !CGFontGetNumberOfGlyphs(cgFontRef.get()))
cgFontRef = 0;
- }
#endif
if (!cgFontRef) {
ATSFontDeactivate(containerRef, NULL, kATSOptionFlagsDefault);
@@ -89,7 +98,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
}
#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- return new FontCustomPlatformData(containerRef, fontRef, cgFontRef);
+ return new FontCustomPlatformData(containerRef, fontRef, cgFontRef.releaseRef());
}
}
diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm
index df9494a..bb9561e 100644
--- a/WebCore/platform/graphics/mac/FontMac.mm
+++ b/WebCore/platform/graphics/mac/FontMac.mm
@@ -50,10 +50,33 @@ bool Font::canReturnFallbackFontsForComplexText()
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
CGContextRef cgContext = context->platformContext();
+ bool newShouldUseFontSmoothing = shouldUseSmoothing();
+
+ switch(fontDescription().fontSmoothing()) {
+ case Antialiased: {
+ context->setShouldAntialias(true);
+ newShouldUseFontSmoothing = false;
+ break;
+ }
+ case SubpixelAntialiased: {
+ context->setShouldAntialias(true);
+ newShouldUseFontSmoothing = true;
+ break;
+ }
+ case NoSmoothing: {
+ context->setShouldAntialias(false);
+ newShouldUseFontSmoothing = false;
+ break;
+ }
+ case AutoSmoothing: {
+ // For the AutoSmooth case, don't do anything! Keep the default settings.
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
bool originalShouldUseFontSmoothing = wkCGContextGetShouldSmoothFonts(cgContext);
- bool newShouldUseFontSmoothing = shouldUseSmoothing();
-
if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
CGContextSetShouldSmoothFonts(cgContext, newShouldUseFontSmoothing);
@@ -92,6 +115,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
IntSize shadowSize;
int shadowBlur;
Color shadowColor;
+ ColorSpace fillColorSpace = context->fillColorSpace();
context->getShadow(shadowSize, shadowBlur, shadowColor);
bool hasSimpleShadow = context->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur;
@@ -100,14 +124,14 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
context->clearShadow();
Color fillColor = context->fillColor();
Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- context->setFillColor(shadowFillColor);
+ context->setFillColor(shadowFillColor, fillColorSpace);
CGContextSetTextPosition(cgContext, point.x() + shadowSize.width(), point.y() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
if (font->syntheticBoldOffset()) {
CGContextSetTextPosition(cgContext, point.x() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
- context->setFillColor(fillColor);
+ context->setFillColor(fillColor, fillColorSpace);
}
CGContextSetTextPosition(cgContext, point.x(), point.y());
@@ -118,7 +142,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
}
if (hasSimpleShadow)
- context->setShadow(shadowSize, shadowBlur, shadowColor);
+ context->setShadow(shadowSize, shadowBlur, shadowColor, fillColorSpace);
if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
CGContextSetShouldSmoothFonts(cgContext, originalShouldUseFontSmoothing);
diff --git a/WebCore/platform/graphics/mac/FontMacATSUI.mm b/WebCore/platform/graphics/mac/FontMacATSUI.mm
deleted file mode 100644
index 051abb7..0000000
--- a/WebCore/platform/graphics/mac/FontMacATSUI.mm
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#import "config.h"
-#import "Font.h"
-
-#if USE(ATSUI)
-
-#import "CharacterNames.h"
-#import "GraphicsContext.h"
-#import "Logging.h"
-#import "ShapeArabic.h"
-#import "SimpleFontData.h"
-#import <AppKit/NSGraphicsContext.h>
-#import <wtf/OwnArrayPtr.h>
-
-#define SYNTHETIC_OBLIQUE_ANGLE 14
-
-#ifdef __LP64__
-#define URefCon void*
-#else
-#define URefCon UInt32
-#endif
-
-using namespace std;
-
-namespace WebCore {
-
-struct ATSULayoutParameters : Noncopyable
-{
- ATSULayoutParameters(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0)
- : m_run(run)
- , m_font(0)
- , m_hasSyntheticBold(false)
- , m_syntheticBoldPass(false)
- , m_padPerSpace(0)
- , m_fallbackFonts(fallbackFonts)
- {
- }
-
- ~ATSULayoutParameters()
- {
- ATSUDisposeTextLayout(m_layout);
- }
-
- void initialize(const Font*, const GraphicsContext* = 0);
-
- const TextRun& m_run;
-
- const Font* m_font;
-
- ATSUTextLayout m_layout;
- OwnArrayPtr<const SimpleFontData*> m_fonts;
-
- OwnArrayPtr<UChar> m_charBuffer;
- bool m_hasSyntheticBold;
- bool m_syntheticBoldPass;
- float m_padPerSpace;
- HashSet<const SimpleFontData*>* m_fallbackFonts;
-};
-
-static TextRun copyRunForDirectionalOverrideIfNecessary(const TextRun& run, OwnArrayPtr<UChar>& charactersWithOverride)
-{
- if (!run.directionalOverride())
- return run;
-
- charactersWithOverride.set(new UChar[run.length() + 2]);
- charactersWithOverride[0] = run.rtl() ? rightToLeftOverride : leftToRightOverride;
- memcpy(&charactersWithOverride[1], run.data(0), sizeof(UChar) * run.length());
- charactersWithOverride[run.length() + 1] = popDirectionalFormatting;
-
- TextRun result = run;
- result.setText(charactersWithOverride.get(), run.length() + 2);
- return result;
-}
-
-static bool fontHasMirroringInfo(ATSUFontID fontID)
-{
- ByteCount propTableSize;
- OSStatus status = ATSFontGetTable(fontID, 'prop', 0, 0, 0, &propTableSize);
- if (status == noErr) // naively assume that if a 'prop' table exists then it contains mirroring info
- return true;
- else if (status != kATSInvalidFontTableAccess) // anything other than a missing table is logged as an error
- LOG_ERROR("ATSFontGetTable failed (%d)", status);
-
- return false;
-}
-
-static void disableLigatures(const SimpleFontData* fontData)
-{
- // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are
- // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example.
- // See bugzilla 5166.
- if (fontData->platformData().allowsLigatures())
- return;
-
- ATSUFontFeatureType featureTypes[] = { kLigaturesType };
- ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector };
- OSStatus status = ATSUSetFontFeatures(fontData->m_ATSUStyle, 1, featureTypes, featureSelectors);
- if (status != noErr)
- LOG_ERROR("ATSUSetFontFeatures failed (%d) -- ligatures remain enabled", status);
-}
-
-static void initializeATSUStyle(const SimpleFontData* fontData)
-{
- if (fontData->m_ATSUStyleInitialized)
- return;
-
- ATSUFontID fontID = fontData->platformData().m_atsuFontID;
- if (!fontID) {
- LOG_ERROR("unable to get ATSUFontID for %@", fontData->platformData().font());
- return;
- }
-
- OSStatus status = ATSUCreateStyle(&fontData->m_ATSUStyle);
- if (status != noErr)
- // Who knows how many ATSU functions will crash when passed a NULL style...
- LOG_ERROR("ATSUCreateStyle failed (%d)", status);
-
- CGAffineTransform transform = CGAffineTransformMakeScale(1, -1);
- if (fontData->platformData().m_syntheticOblique)
- transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0));
- Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
- ByteCount styleSizes[4] = { sizeof(Fixed), sizeof(ATSUFontID), sizeof(CGAffineTransform), sizeof(Fract) };
- // Turn off automatic kerning until it is supported in the CG code path (bug 6136)
- Fract kerningInhibitFactor = FloatToFract(1.0);
-
- ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
- ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &transform, &kerningInhibitFactor };
- status = ATSUSetAttributes(fontData->m_ATSUStyle, 4, styleTags, styleSizes, styleValues);
- if (status != noErr)
- LOG_ERROR("ATSUSetAttributes failed (%d)", status);
-
- fontData->m_ATSUMirrors = fontHasMirroringInfo(fontID);
-
- // Turn off ligatures such as 'fi' to match the CG code path's behavior, until bug 6135 is fixed.
- disableLigatures(fontData);
-
- fontData->m_ATSUStyleInitialized = true;
-}
-
-static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef iLineRef, URefCon iRefCon, void*, ATSULayoutOperationCallbackStatus* oCallbackStatus)
-{
- ATSULayoutParameters* params = reinterpret_cast<ATSULayoutParameters*>(iRefCon);
- OSStatus status;
- ItemCount count;
- ATSLayoutRecord *layoutRecords;
-
- if (params->m_run.applyWordRounding()) {
- status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, (void **)&layoutRecords, &count);
- if (status != noErr) {
- *oCallbackStatus = kATSULayoutOperationCallbackStatusContinue;
- return status;
- }
-
- Fixed lastNativePos = 0;
- float lastAdjustedPos = 0;
- const UChar* characters = params->m_charBuffer ? params->m_charBuffer.get() : params->m_run.characters();
- const SimpleFontData** renderers = params->m_fonts.get();
- const SimpleFontData* renderer;
- const SimpleFontData* lastRenderer = 0;
- ByteCount offset = layoutRecords[0].originalOffset;
- UChar nextCh = *(UChar *)(((char *)characters)+offset);
- bool shouldRound = false;
- bool syntheticBoldPass = params->m_syntheticBoldPass;
- Fixed syntheticBoldOffset = 0;
- bool hasExtraSpacing = (params->m_font->letterSpacing() || params->m_font->wordSpacing() || params->m_run.padding()) && !params->m_run.spacingDisabled();
- float padding = params->m_run.padding();
- // In the CoreGraphics code path, the rounding hack is applied in logical order.
- // Here it is applied in visual left-to-right order, which may be better.
- ItemCount lastRoundingChar = 0;
- ItemCount i;
- for (i = 1; i < count; i++) {
- bool isLastChar = i == count - 1;
- renderer = renderers[offset / 2];
- float width;
- if (nextCh == zeroWidthSpace || Font::treatAsZeroWidthSpace(nextCh) && !Font::treatAsSpace(nextCh)) {
- width = 0;
- layoutRecords[i-1].glyphID = renderer->spaceGlyph();
- } else {
- width = FixedToFloat(layoutRecords[i].realPos - lastNativePos);
- if (renderer != lastRenderer && width) {
- lastRenderer = renderer;
- // The CoreGraphics interpretation of NSFontAntialiasedIntegerAdvancementsRenderingMode seems
- // to be "round each glyph's width to the nearest integer". This is not the same as ATSUI
- // does in any of its device-metrics modes.
- shouldRound = renderer->platformData().roundsGlyphAdvances();
- if (syntheticBoldPass)
- syntheticBoldOffset = FloatToFixed(renderer->syntheticBoldOffset());
- if (params->m_fallbackFonts && renderer != params->m_font->primaryFont())
- params->m_fallbackFonts->add(renderer);
- }
- if (shouldRound)
- width = roundf(width);
- width += renderer->syntheticBoldOffset();
- if (renderer->pitch() == FixedPitch ? width == renderer->spaceWidth() : (layoutRecords[i-1].flags & kATSGlyphInfoIsWhiteSpace))
- width = renderer->adjustedSpaceWidth();
- }
- lastNativePos = layoutRecords[i].realPos;
-
- if (hasExtraSpacing) {
- if (width && params->m_font->letterSpacing())
- width +=params->m_font->letterSpacing();
- if (Font::treatAsSpace(nextCh)) {
- if (params->m_run.padding()) {
- if (padding < params->m_padPerSpace) {
- width += padding;
- padding = 0;
- } else {
- width += params->m_padPerSpace;
- padding -= params->m_padPerSpace;
- }
- }
- if (offset != 0 && !Font::treatAsSpace(*((UChar *)(((char *)characters)+offset) - 1)) && params->m_font->wordSpacing())
- width += params->m_font->wordSpacing();
- }
- }
-
- UChar ch = nextCh;
- offset = layoutRecords[i].originalOffset;
- // Use space for nextCh at the end of the loop so that we get inside the rounding hack code.
- // We won't actually round unless the other conditions are satisfied.
- nextCh = isLastChar ? ' ' : *(UChar *)(((char *)characters)+offset);
-
- if (Font::isRoundingHackCharacter(ch))
- width = ceilf(width);
- lastAdjustedPos = lastAdjustedPos + width;
- if (Font::isRoundingHackCharacter(nextCh) && (!isLastChar || params->m_run.applyRunRounding())){
- if (params->m_run.ltr())
- lastAdjustedPos = ceilf(lastAdjustedPos);
- else {
- float roundingWidth = ceilf(lastAdjustedPos) - lastAdjustedPos;
- Fixed rw = FloatToFixed(roundingWidth);
- ItemCount j;
- for (j = lastRoundingChar; j < i; j++)
- layoutRecords[j].realPos += rw;
- lastRoundingChar = i;
- lastAdjustedPos += roundingWidth;
- }
- }
- if (syntheticBoldPass) {
- if (syntheticBoldOffset)
- layoutRecords[i-1].realPos += syntheticBoldOffset;
- else
- layoutRecords[i-1].glyphID = renderer->spaceGlyph();
- }
- layoutRecords[i].realPos = FloatToFixed(lastAdjustedPos);
- }
-
- status = ATSUDirectReleaseLayoutDataArrayPtr(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void **)&layoutRecords);
- }
- *oCallbackStatus = kATSULayoutOperationCallbackStatusHandled;
- return noErr;
-}
-
-static inline bool isArabicLamWithAlefLigature(UChar c)
-{
- return c >= 0xfef5 && c <= 0xfefc;
-}
-
-static void shapeArabic(const UChar* source, UChar* dest, unsigned totalLength, unsigned shapingStart)
-{
- while (shapingStart < totalLength) {
- unsigned shapingEnd;
- // We do not want to pass a Lam with Alef ligature followed by a space to the shaper,
- // since we want to be able to identify this sequence as the result of shaping a Lam
- // followed by an Alef and padding with a space.
- bool foundLigatureSpace = false;
- for (shapingEnd = shapingStart; !foundLigatureSpace && shapingEnd < totalLength - 1; ++shapingEnd)
- foundLigatureSpace = isArabicLamWithAlefLigature(source[shapingEnd]) && source[shapingEnd + 1] == ' ';
- shapingEnd++;
-
- UErrorCode shapingError = U_ZERO_ERROR;
- unsigned charsWritten = shapeArabic(source + shapingStart, shapingEnd - shapingStart, dest + shapingStart, shapingEnd - shapingStart, U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR, &shapingError);
-
- if (U_SUCCESS(shapingError) && charsWritten == shapingEnd - shapingStart) {
- for (unsigned j = shapingStart; j < shapingEnd - 1; ++j) {
- if (isArabicLamWithAlefLigature(dest[j]) && dest[j + 1] == ' ')
- dest[++j] = zeroWidthSpace;
- }
- if (foundLigatureSpace) {
- dest[shapingEnd] = ' ';
- shapingEnd++;
- } else if (isArabicLamWithAlefLigature(dest[shapingEnd - 1])) {
- // u_shapeArabic quirk: if the last two characters in the source string are a Lam and an Alef,
- // the space is put at the beginning of the string, despite U_SHAPE_LENGTH_FIXED_SPACES_NEAR.
- ASSERT(dest[shapingStart] == ' ');
- dest[shapingStart] = zeroWidthSpace;
- }
- } else {
- // Something went wrong. Abandon shaping and just copy the rest of the buffer.
- LOG_ERROR("u_shapeArabic failed(%d)", shapingError);
- shapingEnd = totalLength;
- memcpy(dest + shapingStart, source + shapingStart, (shapingEnd - shapingStart) * sizeof(UChar));
- }
- shapingStart = shapingEnd;
- }
-}
-
-void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* graphicsContext)
-{
- m_font = font;
-
- const SimpleFontData* fontData = font->primaryFont();
- m_fonts.set(new const SimpleFontData*[m_run.length()]);
- if (font->isSmallCaps())
- m_charBuffer.set(new UChar[m_run.length()]);
-
- ATSUTextLayout layout;
- OSStatus status;
- ATSULayoutOperationOverrideSpecifier overrideSpecifier;
-
- initializeATSUStyle(fontData);
-
- // FIXME: This is currently missing the following required features that the CoreGraphics code path has:
- // - \n, \t, and nonbreaking space render as a space.
-
- UniCharCount runLength = m_run.length();
-
- if (m_charBuffer)
- memcpy(m_charBuffer.get(), m_run.characters(), runLength * sizeof(UChar));
-
- status = ATSUCreateTextLayoutWithTextPtr(
- (m_charBuffer ? m_charBuffer.get() : m_run.characters()),
- 0, // offset
- runLength, // length
- runLength, // total length
- 1, // styleRunCount
- &runLength, // length of style run
- &fontData->m_ATSUStyle,
- &layout);
- if (status != noErr)
- LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed(%d)", status);
- m_layout = layout;
- ATSUSetTextLayoutRefCon(m_layout, (URefCon)this);
-
- // FIXME: There are certain times when this method is called, when we don't have access to a GraphicsContext
- // measuring text runs with floatWidthForComplexText is one example.
- // ATSUI requires that we pass a valid CGContextRef to it when specifying kATSUCGContextTag (crashes when passed 0)
- // ATSUI disables sub-pixel rendering if kATSUCGContextTag is not specified! So we're in a bind.
- // Sometimes [[NSGraphicsContext currentContext] graphicsPort] may return the wrong (or no!) context. Nothing we can do about it (yet).
- CGContextRef cgContext = graphicsContext ? graphicsContext->platformContext() : (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-
- ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;
- Boolean rtl = m_run.rtl();
- overrideSpecifier.operationSelector = kATSULayoutOperationPostLayoutAdjustment;
- overrideSpecifier.overrideUPP = overrideLayoutOperation;
- ATSUAttributeTag tags[] = { kATSUCGContextTag, kATSULineLayoutOptionsTag, kATSULineDirectionTag, kATSULayoutOperationOverrideTag };
- ByteCount sizes[] = { sizeof(CGContextRef), sizeof(ATSLineLayoutOptions), sizeof(Boolean), sizeof(ATSULayoutOperationOverrideSpecifier) };
- ATSUAttributeValuePtr values[] = { &cgContext, &lineLayoutOptions, &rtl, &overrideSpecifier };
-
- status = ATSUSetLayoutControls(layout, (m_run.applyWordRounding() ? 4 : 3), tags, sizes, values);
- if (status != noErr)
- LOG_ERROR("ATSUSetLayoutControls failed(%d)", status);
-
- status = ATSUSetTransientFontMatching(layout, YES);
- if (status != noErr)
- LOG_ERROR("ATSUSetTransientFontMatching failed(%d)", status);
-
- m_hasSyntheticBold = false;
- ATSUFontID ATSUSubstituteFont;
- UniCharArrayOffset substituteOffset = 0;
- UniCharCount substituteLength;
- UniCharArrayOffset lastOffset;
- const SimpleFontData* substituteFontData = 0;
-
- while (substituteOffset < runLength) {
- // FIXME: Using ATSUMatchFontsToText() here results in several problems: the CSS font family list is not necessarily followed for the 2nd
- // and onwards unmatched characters; segmented fonts do not work correctly; behavior does not match the simple text and Uniscribe code
- // paths. Change this function to use Font::glyphDataForCharacter() for each character instead.
- lastOffset = substituteOffset;
- status = ATSUMatchFontsToText(layout, substituteOffset, kATSUToTextEnd, &ATSUSubstituteFont, &substituteOffset, &substituteLength);
- if (status == kATSUFontsMatched || status == kATSUFontsNotMatched) {
- const FontData* fallbackFontData = m_font->fontDataForCharacters(m_run.characters() + substituteOffset, substituteLength);
- substituteFontData = fallbackFontData ? fallbackFontData->fontDataForCharacter(m_run[0]) : 0;
- if (substituteFontData) {
- initializeATSUStyle(substituteFontData);
- if (substituteFontData->m_ATSUStyle)
- ATSUSetRunStyle(layout, substituteFontData->m_ATSUStyle, substituteOffset, substituteLength);
- } else
- substituteFontData = fontData;
- } else {
- substituteOffset = runLength;
- substituteLength = 0;
- }
-
- bool shapedArabic = false;
- bool isSmallCap = false;
- UniCharArrayOffset firstSmallCap = 0;
- const SimpleFontData *r = fontData;
- UniCharArrayOffset i;
- for (i = lastOffset; ; i++) {
- if (i == substituteOffset || i == substituteOffset + substituteLength) {
- if (isSmallCap) {
- isSmallCap = false;
- initializeATSUStyle(r->smallCapsFontData(m_font->fontDescription()));
- ATSUSetRunStyle(layout, r->smallCapsFontData(m_font->fontDescription())->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
- }
- if (i == substituteOffset && substituteLength > 0)
- r = substituteFontData;
- else
- break;
- }
- if (!shapedArabic && WTF::Unicode::isArabicChar(m_run[i]) && !r->shapesArabic()) {
- shapedArabic = true;
- if (!m_charBuffer) {
- m_charBuffer.set(new UChar[runLength]);
- memcpy(m_charBuffer.get(), m_run.characters(), i * sizeof(UChar));
- ATSUTextMoved(layout, m_charBuffer.get());
- }
- shapeArabic(m_run.characters(), m_charBuffer.get(), runLength, i);
- }
- if (m_run.rtl() && !r->m_ATSUMirrors) {
- UChar mirroredChar = u_charMirror(m_run[i]);
- if (mirroredChar != m_run[i]) {
- if (!m_charBuffer) {
- m_charBuffer.set(new UChar[runLength]);
- memcpy(m_charBuffer.get(), m_run.characters(), runLength * sizeof(UChar));
- ATSUTextMoved(layout, m_charBuffer.get());
- }
- m_charBuffer[i] = mirroredChar;
- }
- }
- if (m_font->isSmallCaps()) {
- const SimpleFontData* smallCapsData = r->smallCapsFontData(m_font->fontDescription());
- UChar c = m_charBuffer[i];
- UChar newC;
- if (U_GET_GC_MASK(c) & U_GC_M_MASK)
- m_fonts[i] = isSmallCap ? smallCapsData : r;
- else if (!u_isUUppercase(c) && (newC = u_toupper(c)) != c) {
- m_charBuffer[i] = newC;
- if (!isSmallCap) {
- isSmallCap = true;
- firstSmallCap = i;
- }
- m_fonts[i] = smallCapsData;
- } else {
- if (isSmallCap) {
- isSmallCap = false;
- initializeATSUStyle(smallCapsData);
- ATSUSetRunStyle(layout, smallCapsData->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
- }
- m_fonts[i] = r;
- }
- } else
- m_fonts[i] = r;
- if (m_fonts[i]->syntheticBoldOffset())
- m_hasSyntheticBold = true;
- }
- substituteOffset += substituteLength;
- }
- if (m_run.padding()) {
- float numSpaces = 0;
- unsigned k;
- for (k = 0; k < runLength; k++)
- if (Font::treatAsSpace(m_run[k]))
- numSpaces++;
-
- if (numSpaces == 0)
- m_padPerSpace = 0;
- else
- m_padPerSpace = ceilf(m_run.padding() / numSpaces);
- } else
- m_padPerSpace = 0;
-}
-
-FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
-{
- OwnArrayPtr<UChar> charactersWithOverride;
- TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
- if (run.directionalOverride()) {
- from++;
- to++;
- }
-
- ATSULayoutParameters params(adjustedRun);
- params.initialize(this);
-
- ATSTrapezoid firstGlyphBounds;
- ItemCount actualNumBounds;
-
- OSStatus status = ATSUGetGlyphBounds(params.m_layout, 0, 0, from, to - from, kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);
- if (status != noErr || actualNumBounds != 1) {
- static ATSTrapezoid zeroTrapezoid = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
- firstGlyphBounds = zeroTrapezoid;
- }
-
- float beforeWidth = MIN(FixedToFloat(firstGlyphBounds.lowerLeft.x), FixedToFloat(firstGlyphBounds.upperLeft.x));
- float afterWidth = MAX(FixedToFloat(firstGlyphBounds.lowerRight.x), FixedToFloat(firstGlyphBounds.upperRight.x));
-
- FloatRect rect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
-
- return rect;
-}
-
-void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- OSStatus status;
-
- int drawPortionLength = to - from;
- OwnArrayPtr<UChar> charactersWithOverride;
- TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
- if (run.directionalOverride())
- from++;
-
- ATSULayoutParameters params(adjustedRun);
- params.initialize(this, graphicsContext);
-
- // ATSUI can't draw beyond -32768 to +32767 so we translate the CTM and tell ATSUI to draw at (0, 0).
- CGContextRef context = graphicsContext->platformContext();
- CGContextTranslateCTM(context, point.x(), point.y());
-
- IntSize shadowSize;
- int shadowBlur;
- Color shadowColor;
- graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor);
-
- bool hasSimpleShadow = graphicsContext->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur;
- if (hasSimpleShadow) {
- // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
- graphicsContext->clearShadow();
- Color fillColor = graphicsContext->fillColor();
- Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- graphicsContext->setFillColor(shadowFillColor);
- CGContextTranslateCTM(context, shadowSize.width(), shadowSize.height());
- status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
- if (status == noErr && params.m_hasSyntheticBold) {
- // Force relayout for the bold pass
- ATSUClearLayoutCache(params.m_layout, 0);
- params.m_syntheticBoldPass = true;
- status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
- // Force relayout for the next pass
- ATSUClearLayoutCache(params.m_layout, 0);
- params.m_syntheticBoldPass = false;
- }
- CGContextTranslateCTM(context, -shadowSize.width(), -shadowSize.height());
- graphicsContext->setFillColor(fillColor);
- }
-
- status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
- if (status == noErr && params.m_hasSyntheticBold) {
- // Force relayout for the bold pass
- ATSUClearLayoutCache(params.m_layout, 0);
- params.m_syntheticBoldPass = true;
- status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
- }
- CGContextTranslateCTM(context, -point.x(), -point.y());
-
- if (status != noErr)
- // Nothing to do but report the error (dev build only).
- LOG_ERROR("ATSUDrawText() failed(%d)", status);
-
- if (hasSimpleShadow)
- graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor);
-}
-
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
-{
- if (run.length() == 0)
- return 0;
-
- ATSULayoutParameters params(run, fallbackFonts);
- params.initialize(this);
-
- OSStatus status;
-
- ATSTrapezoid firstGlyphBounds;
- ItemCount actualNumBounds;
- status = ATSUGetGlyphBounds(params.m_layout, 0, 0, 0, run.length(), kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);
- if (status != noErr)
- LOG_ERROR("ATSUGetGlyphBounds() failed(%d)", status);
- if (actualNumBounds != 1)
- LOG_ERROR("unexpected result from ATSUGetGlyphBounds(): actualNumBounds(%d) != 1", actualNumBounds);
-
- return MAX(FixedToFloat(firstGlyphBounds.upperRight.x), FixedToFloat(firstGlyphBounds.lowerRight.x)) -
- MIN(FixedToFloat(firstGlyphBounds.upperLeft.x), FixedToFloat(firstGlyphBounds.lowerLeft.x));
-}
-
-int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool /*includePartialGlyphs*/) const
-{
- OwnArrayPtr<UChar> charactersWithOverride;
- TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
-
- ATSULayoutParameters params(adjustedRun);
- params.initialize(this);
-
- UniCharArrayOffset primaryOffset = 0;
-
- // FIXME: No idea how to avoid including partial glyphs.
- // Not even sure if that's the behavior this yields now.
- Boolean isLeading;
- UniCharArrayOffset secondaryOffset = 0;
- OSStatus status = ATSUPositionToOffset(params.m_layout, FloatToFixed(x), FloatToFixed(-1), &primaryOffset, &isLeading, &secondaryOffset);
- unsigned offset;
- if (status == noErr) {
- offset = (unsigned)primaryOffset;
- if (run.directionalOverride() && offset > 0)
- offset--;
- } else
- // Failed to find offset! Return 0 offset.
- offset = 0;
-
- return offset;
-}
-
-}
-#endif // USE(ATSUI)
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
new file mode 100644
index 0000000..41f63a9
--- /dev/null
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
@@ -0,0 +1,1365 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "GraphicsContext3D.h"
+
+#include "CachedImage.h"
+#include "WebGLActiveInfo.h"
+#include "WebGLArray.h"
+#include "WebGLBuffer.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLFloatArray.h"
+#include "WebGLIntArray.h"
+#include "CanvasObject.h"
+#include "WebGLProgram.h"
+#include "WebGLRenderbuffer.h"
+#include "WebGLShader.h"
+#include "WebGLTexture.h"
+#include "WebGLUnsignedByteArray.h"
+#include "CString.h"
+#include "HTMLCanvasElement.h"
+#include "HTMLImageElement.h"
+#include "ImageBuffer.h"
+#include "NotImplemented.h"
+#include "WebKitCSSMatrix.h"
+
+#include <CoreGraphics/CGBitmapContext.h>
+#include <OpenGL/CGLRenderers.h>
+
+namespace WebCore {
+
+static void setPixelFormat(Vector<CGLPixelFormatAttribute>& attribs, int colorBits, int depthBits, bool accelerated, bool supersample, bool closest)
+{
+ attribs.clear();
+
+ attribs.append(kCGLPFAColorSize);
+ attribs.append(static_cast<CGLPixelFormatAttribute>(colorBits));
+ attribs.append(kCGLPFADepthSize);
+ attribs.append(static_cast<CGLPixelFormatAttribute>(depthBits));
+
+ if (accelerated)
+ attribs.append(kCGLPFAAccelerated);
+ else {
+ attribs.append(kCGLPFARendererID);
+ attribs.append(static_cast<CGLPixelFormatAttribute>(kCGLRendererGenericFloatID));
+ }
+
+ if (supersample)
+ attribs.append(kCGLPFASupersample);
+
+ if (closest)
+ attribs.append(kCGLPFAClosestPolicy);
+
+ attribs.append(static_cast<CGLPixelFormatAttribute>(0));
+}
+
+PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create()
+{
+ OwnPtr<GraphicsContext3D> context(new GraphicsContext3D());
+ return context->m_contextObj ? context.release() : 0;
+}
+
+GraphicsContext3D::GraphicsContext3D()
+ : m_contextObj(0)
+ , m_texture(0)
+ , m_fbo(0)
+ , m_depthBuffer(0)
+{
+ Vector<CGLPixelFormatAttribute> attribs;
+ CGLPixelFormatObj pixelFormatObj = 0;
+ GLint numPixelFormats = 0;
+
+ // We will try:
+ //
+ // 1) 32 bit RGBA/32 bit depth/accelerated/supersampled
+ // 2) 32 bit RGBA/32 bit depth/accelerated
+ // 3) 32 bit RGBA/16 bit depth/accelerated
+ // 4) closest to 32 bit RGBA/16 bit depth/software renderer
+ //
+ // If none of that works, we simply fail and set m_contextObj to 0.
+
+ setPixelFormat(attribs, 32, 32, true, true, false);
+ CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats);
+ if (numPixelFormats == 0) {
+ setPixelFormat(attribs, 32, 32, true, false, false);
+ CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats);
+
+ if (numPixelFormats == 0) {
+ setPixelFormat(attribs, 32, 16, true, false, false);
+ CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats);
+
+ if (numPixelFormats == 0) {
+ setPixelFormat(attribs, 32, 16, false, false, true);
+ CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats);
+
+ if (numPixelFormats == 0) {
+ // Could not find an acceptable renderer - fail
+ return;
+ }
+ }
+ }
+ }
+
+ CGLError err = CGLCreateContext(pixelFormatObj, 0, &m_contextObj);
+ CGLDestroyPixelFormat(pixelFormatObj);
+
+ if (err != kCGLNoError || !m_contextObj) {
+ // Could not create the context - fail
+ m_contextObj = 0;
+ return;
+ }
+
+ // Set the current context to the one given to us.
+ CGLSetCurrentContext(m_contextObj);
+
+ // create a texture to render into
+ ::glGenTextures(1, &m_texture);
+ ::glBindTexture(GL_TEXTURE_2D, m_texture);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+
+ // create an FBO
+ ::glGenFramebuffersEXT(1, &m_fbo);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+
+ ::glGenRenderbuffersEXT(1, &m_depthBuffer);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
+ ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 1, 1);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+
+ ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0);
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
+
+ ::glClearColor(0, 0, 0, 0);
+}
+
+GraphicsContext3D::~GraphicsContext3D()
+{
+ if (m_contextObj) {
+ CGLSetCurrentContext(m_contextObj);
+ ::glDeleteRenderbuffersEXT(1, & m_depthBuffer);
+ ::glDeleteTextures(1, &m_texture);
+ ::glDeleteFramebuffersEXT(1, &m_fbo);
+ CGLSetCurrentContext(0);
+ CGLDestroyContext(m_contextObj);
+ }
+}
+
+void GraphicsContext3D::makeContextCurrent()
+{
+ CGLSetCurrentContext(m_contextObj);
+}
+
+void GraphicsContext3D::beginPaint(WebGLRenderingContext* context)
+{
+ UNUSED_PARAM(context);
+}
+
+void GraphicsContext3D::endPaint()
+{
+}
+
+void GraphicsContext3D::reshape(int width, int height)
+{
+ if (width == m_currentWidth && height == m_currentHeight || !m_contextObj)
+ return;
+
+ m_currentWidth = width;
+ m_currentHeight = height;
+
+ CGLSetCurrentContext(m_contextObj);
+
+ ::glBindTexture(GL_TEXTURE_2D, m_texture);
+ ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
+ ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+
+ ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0);
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
+ GLenum status = ::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ // FIXME: cleanup
+ notImplemented();
+ }
+
+ ::glViewport(0, 0, m_currentWidth, m_currentHeight);
+ ::glClear(GL_COLOR_BUFFER_BIT);
+ ::glFlush();
+}
+
+static inline void ensureContext(CGLContextObj context)
+{
+ if (!context)
+ return;
+
+ CGLContextObj currentContext = CGLGetCurrentContext();
+ if (currentContext != context)
+ CGLSetCurrentContext(context);
+}
+
+void GraphicsContext3D::activeTexture(unsigned long texture)
+{
+ ensureContext(m_contextObj);
+ ::glActiveTexture(texture);
+}
+
+void GraphicsContext3D::attachShader(WebGLProgram* program, WebGLShader* shader)
+{
+ ASSERT(program);
+ ASSERT(shader);
+ ensureContext(m_contextObj);
+ ::glAttachShader((GLuint) program->object(), (GLuint) shader->object());
+}
+
+void GraphicsContext3D::bindAttribLocation(WebGLProgram* program, unsigned long index, const String& name)
+{
+ ASSERT(program);
+ ensureContext(m_contextObj);
+ ::glBindAttribLocation((GLuint) program->object(), index, name.utf8().data());
+}
+
+void GraphicsContext3D::bindBuffer(unsigned long target, WebGLBuffer* buffer)
+{
+ ensureContext(m_contextObj);
+ ::glBindBuffer(target, buffer ? (GLuint) buffer->object() : 0);
+}
+
+
+void GraphicsContext3D::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer)
+{
+ ensureContext(m_contextObj);
+ ::glBindFramebufferEXT(target, buffer ? (GLuint) buffer->object() : m_fbo);
+}
+
+void GraphicsContext3D::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderbuffer)
+{
+ ensureContext(m_contextObj);
+ ::glBindRenderbufferEXT(target, renderbuffer ? (GLuint) renderbuffer->object() : 0);
+}
+
+
+void GraphicsContext3D::bindTexture(unsigned long target, WebGLTexture* texture)
+{
+ ensureContext(m_contextObj);
+ ::glBindTexture(target, texture ? (GLuint) texture->object() : 0);
+}
+
+void GraphicsContext3D::blendColor(double red, double green, double blue, double alpha)
+{
+ ensureContext(m_contextObj);
+ ::glBlendColor(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha));
+}
+
+void GraphicsContext3D::blendEquation( unsigned long mode )
+{
+ ensureContext(m_contextObj);
+ ::glBlendEquation(mode);
+}
+
+void GraphicsContext3D::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha)
+{
+ ensureContext(m_contextObj);
+ ::glBlendEquationSeparate(modeRGB, modeAlpha);
+}
+
+
+void GraphicsContext3D::blendFunc(unsigned long sfactor, unsigned long dfactor)
+{
+ ensureContext(m_contextObj);
+ ::glBlendFunc(sfactor, dfactor);
+}
+
+void GraphicsContext3D::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha)
+{
+ ensureContext(m_contextObj);
+ ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage)
+{
+ ensureContext(m_contextObj);
+ ::glBufferData(target, size, 0, usage);
+}
+void GraphicsContext3D::bufferData(unsigned long target, WebGLArray* array, unsigned long usage)
+{
+ if (!array || !array->length())
+ return;
+
+ ensureContext(m_contextObj);
+ ::glBufferData(target, array->byteLength(), array->baseAddress(), usage);
+}
+
+void GraphicsContext3D::bufferSubData(unsigned long target, long offset, WebGLArray* array)
+{
+ if (!array || !array->length())
+ return;
+
+ ensureContext(m_contextObj);
+ ::glBufferSubData(target, offset, array->byteLength(), array->baseAddress());
+}
+
+unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target)
+{
+ ensureContext(m_contextObj);
+ return ::glCheckFramebufferStatusEXT(target);
+}
+
+void GraphicsContext3D::clearColor(double r, double g, double b, double a)
+{
+ ensureContext(m_contextObj);
+ ::glClearColor(static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a));
+}
+
+void GraphicsContext3D::clear(unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glClear(mask);
+}
+
+void GraphicsContext3D::clearDepth(double depth)
+{
+ ensureContext(m_contextObj);
+ ::glClearDepth(depth);
+}
+
+void GraphicsContext3D::clearStencil(long s)
+{
+ ensureContext(m_contextObj);
+ ::glClearStencil(s);
+}
+
+void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha)
+{
+ ensureContext(m_contextObj);
+ ::glColorMask(red, green, blue, alpha);
+}
+
+void GraphicsContext3D::compileShader(WebGLShader* shader)
+{
+ ASSERT(shader);
+ ensureContext(m_contextObj);
+ ::glCompileShader((GLuint) shader->object());
+}
+
+void GraphicsContext3D::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border)
+{
+ ensureContext(m_contextObj);
+ ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+}
+
+void GraphicsContext3D::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+}
+
+void GraphicsContext3D::cullFace(unsigned long mode)
+{
+ ensureContext(m_contextObj);
+ ::glCullFace(mode);
+}
+
+void GraphicsContext3D::depthFunc(unsigned long func)
+{
+ ensureContext(m_contextObj);
+ ::glDepthFunc(func);
+}
+
+void GraphicsContext3D::depthMask(bool flag)
+{
+ ensureContext(m_contextObj);
+ ::glDepthMask(flag);
+}
+
+void GraphicsContext3D::depthRange(double zNear, double zFar)
+{
+ ensureContext(m_contextObj);
+ ::glDepthRange(zNear, zFar);
+}
+
+void GraphicsContext3D::detachShader(WebGLProgram* program, WebGLShader* shader)
+{
+ ASSERT(program);
+ ASSERT(shader);
+ ensureContext(m_contextObj);
+ ::glDetachShader((GLuint) program->object(), (GLuint) shader->object());
+}
+
+void GraphicsContext3D::disable(unsigned long cap)
+{
+ ensureContext(m_contextObj);
+ ::glDisable(cap);
+}
+
+void GraphicsContext3D::disableVertexAttribArray(unsigned long index)
+{
+ ensureContext(m_contextObj);
+ ::glDisableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count)
+{
+ ensureContext(m_contextObj);
+ ::glDrawArrays(mode, first, count);
+}
+
+void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset)
+{
+ ensureContext(m_contextObj);
+ ::glDrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::enable(unsigned long cap)
+{
+ ensureContext(m_contextObj);
+ ::glEnable(cap);
+}
+
+void GraphicsContext3D::enableVertexAttribArray(unsigned long index)
+{
+ ensureContext(m_contextObj);
+ ::glEnableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::finish()
+{
+ ensureContext(m_contextObj);
+ ::glFinish();
+}
+
+void GraphicsContext3D::flush()
+{
+ ensureContext(m_contextObj);
+ ::glFlush();
+}
+
+void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer* buffer)
+{
+ ensureContext(m_contextObj);
+ ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer ? (GLuint) buffer->object() : 0);
+}
+
+void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture* texture, long level)
+{
+ ensureContext(m_contextObj);
+ ::glFramebufferTexture2DEXT(target, attachment, textarget, texture ? (GLuint) texture->object() : 0, level);
+}
+
+void GraphicsContext3D::frontFace(unsigned long mode)
+{
+ ensureContext(m_contextObj);
+ ::glFrontFace(mode);
+}
+
+void GraphicsContext3D::generateMipmap(unsigned long target)
+{
+ ensureContext(m_contextObj);
+ ::glGenerateMipmapEXT(target);
+}
+
+bool GraphicsContext3D::getActiveAttrib(WebGLProgram* program, unsigned long index, ActiveInfo& info)
+{
+ if (!program->object()) {
+ synthesizeGLError(INVALID_VALUE);
+ return false;
+ }
+ ensureContext(m_contextObj);
+ GLint maxAttributeSize = 0;
+ ::glGetProgramiv(static_cast<GLuint>(program->object()), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize);
+ GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination
+ GLsizei nameLength = 0;
+ GLint size = 0;
+ GLenum type = 0;
+ ::glGetActiveAttrib(static_cast<GLuint>(program->object()), index, maxAttributeSize, &nameLength, &size, &type, name);
+ if (!nameLength)
+ return false;
+ info.name = String(name, nameLength);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+bool GraphicsContext3D::getActiveUniform(WebGLProgram* program, unsigned long index, ActiveInfo& info)
+{
+ if (!program->object()) {
+ synthesizeGLError(INVALID_VALUE);
+ return false;
+ }
+ ensureContext(m_contextObj);
+ GLint maxUniformSize = 0;
+ ::glGetProgramiv(static_cast<GLuint>(program->object()), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize);
+ GLchar name[maxUniformSize]; // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination
+ GLsizei nameLength = 0;
+ GLint size = 0;
+ GLenum type = 0;
+ ::glGetActiveUniform(static_cast<GLuint>(program->object()), index, maxUniformSize, &nameLength, &size, &type, name);
+ if (!nameLength)
+ return false;
+ info.name = String(name, nameLength);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+int GraphicsContext3D::getAttribLocation(WebGLProgram* program, const String& name)
+{
+ if (!program)
+ return -1;
+
+ ensureContext(m_contextObj);
+ return ::glGetAttribLocation((GLuint) program->object(), name.utf8().data());
+}
+
+unsigned long GraphicsContext3D::getError()
+{
+ if (m_syntheticErrors.size() > 0) {
+ ListHashSet<unsigned long>::iterator iter = m_syntheticErrors.begin();
+ unsigned long err = *iter;
+ m_syntheticErrors.remove(iter);
+ return err;
+ }
+
+ ensureContext(m_contextObj);
+ return ::glGetError();
+}
+
+String GraphicsContext3D::getString(unsigned long name)
+{
+ ensureContext(m_contextObj);
+ return String((const char*) ::glGetString(name));
+}
+
+void GraphicsContext3D::hint(unsigned long target, unsigned long mode)
+{
+ ensureContext(m_contextObj);
+ ::glHint(target, mode);
+}
+
+bool GraphicsContext3D::isBuffer(WebGLBuffer* buffer)
+{
+ if (!buffer)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsBuffer((GLuint) buffer->object());
+}
+
+bool GraphicsContext3D::isEnabled(unsigned long cap)
+{
+ ensureContext(m_contextObj);
+ return ::glIsEnabled(cap);
+}
+
+bool GraphicsContext3D::isFramebuffer(WebGLFramebuffer* framebuffer)
+{
+ if (!framebuffer)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsFramebufferEXT((GLuint) framebuffer->object());
+}
+
+bool GraphicsContext3D::isProgram(WebGLProgram* program)
+{
+ if (!program)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsProgram((GLuint) program->object());
+}
+
+bool GraphicsContext3D::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
+{
+ if (!renderbuffer)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsRenderbufferEXT((GLuint) renderbuffer->object());
+}
+
+bool GraphicsContext3D::isShader(WebGLShader* shader)
+{
+ if (!shader)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsShader((GLuint) shader->object());
+}
+
+bool GraphicsContext3D::isTexture(WebGLTexture* texture)
+{
+ if (!texture)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsTexture((GLuint) texture->object());
+}
+
+void GraphicsContext3D::lineWidth(double width)
+{
+ ensureContext(m_contextObj);
+ ::glLineWidth(static_cast<float>(width));
+}
+
+void GraphicsContext3D::linkProgram(WebGLProgram* program)
+{
+ ASSERT(program);
+ ensureContext(m_contextObj);
+ ::glLinkProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::pixelStorei(unsigned long pname, long param)
+{
+ ensureContext(m_contextObj);
+ ::glPixelStorei(pname, param);
+}
+
+void GraphicsContext3D::polygonOffset(double factor, double units)
+{
+ ensureContext(m_contextObj);
+ ::glPolygonOffset(static_cast<float>(factor), static_cast<float>(units));
+}
+
+PassRefPtr<WebGLArray> GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type)
+{
+ ensureContext(m_contextObj);
+
+ // FIXME: For now we only accept GL_UNSIGNED_BYTE/GL_RGBA. In reality OpenGL ES 2.0 accepts that pair and one other
+ // as specified by GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE. But for now we will
+ // not accept those.
+ // FIXME: Also, we should throw when an unacceptable value is passed
+ if (type != GL_UNSIGNED_BYTE || format != GL_RGBA)
+ return 0;
+
+ RefPtr<WebGLUnsignedByteArray> array = WebGLUnsignedByteArray::create(width * height * 4);
+ ::glReadPixels(x, y, width, height, format, type, (GLvoid*) array->data());
+ return array;
+}
+
+void GraphicsContext3D::releaseShaderCompiler()
+{
+ // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants
+ ensureContext(m_contextObj);
+ //::glReleaseShaderCompiler();
+}
+
+void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::glRenderbufferStorageEXT(target, internalformat, width, height);
+}
+
+void GraphicsContext3D::sampleCoverage(double value, bool invert)
+{
+ ensureContext(m_contextObj);
+ ::glSampleCoverage(static_cast<float>(value), invert);
+}
+
+void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::glScissor(x, y, width, height);
+}
+
+void GraphicsContext3D::shaderSource(WebGLShader* shader, const String& string)
+{
+ ASSERT(shader);
+
+ ensureContext(m_contextObj);
+ const CString& cs = string.utf8();
+ const char* s = cs.data();
+
+ int length = string.length();
+ ::glShaderSource((GLuint) shader->object(), 1, &s, &length);
+}
+
+void GraphicsContext3D::stencilFunc(unsigned long func, long ref, unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilFunc(func, ref, mask);
+}
+
+void GraphicsContext3D::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilFuncSeparate(face, func, ref, mask);
+}
+
+void GraphicsContext3D::stencilMask(unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilMask(mask);
+}
+
+void GraphicsContext3D::stencilMaskSeparate(unsigned long face, unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilMaskSeparate(face, mask);
+}
+
+void GraphicsContext3D::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass)
+{
+ ensureContext(m_contextObj);
+ ::glStencilOp(fail, zfail, zpass);
+}
+
+void GraphicsContext3D::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass)
+{
+ ensureContext(m_contextObj);
+ ::glStencilOpSeparate(face, fail, zfail, zpass);
+}
+
+void GraphicsContext3D::texParameterf(unsigned target, unsigned pname, float value)
+{
+ ensureContext(m_contextObj);
+ ::glTexParameterf(target, pname, static_cast<float>(value));
+}
+
+void GraphicsContext3D::texParameteri(unsigned target, unsigned pname, int value)
+{
+ ensureContext(m_contextObj);
+ ::glTexParameteri(target, pname, static_cast<float>(value));
+}
+
+void GraphicsContext3D::uniform1f(long location, float v0)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1f(location, v0);
+}
+
+void GraphicsContext3D::uniform1fv(long location, float* array, int size)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2f(long location, float v0, float v1)
+{
+ ensureContext(m_contextObj);
+ ::glUniform2f(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2fv(long location, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 2
+ ensureContext(m_contextObj);
+ ::glUniform2fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3f(long location, float v0, float v1, float v2)
+{
+ ensureContext(m_contextObj);
+ ::glUniform3f(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3fv(long location, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 3
+ ensureContext(m_contextObj);
+ ::glUniform3fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4f(long location, float v0, float v1, float v2, float v3)
+{
+ ensureContext(m_contextObj);
+ ::glUniform4f(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4fv(long location, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 4
+ ensureContext(m_contextObj);
+ ::glUniform4fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform1i(long location, int v0)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1i(location, v0);
+}
+
+void GraphicsContext3D::uniform1iv(long location, int* array, int size)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2i(long location, int v0, int v1)
+{
+ ensureContext(m_contextObj);
+ ::glUniform2i(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2iv(long location, int* array, int size)
+{
+ // FIXME: length needs to be a multiple of 2
+ ensureContext(m_contextObj);
+ ::glUniform2iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3i(long location, int v0, int v1, int v2)
+{
+ ensureContext(m_contextObj);
+ ::glUniform3i(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3iv(long location, int* array, int size)
+{
+ // FIXME: length needs to be a multiple of 3
+ ensureContext(m_contextObj);
+ ::glUniform3iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4i(long location, int v0, int v1, int v2, int v3)
+{
+ ensureContext(m_contextObj);
+ ::glUniform4i(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4iv(long location, int* array, int size)
+{
+ // FIXME: length needs to be a multiple of 4
+ ensureContext(m_contextObj);
+ ::glUniform4iv(location, size, array);
+}
+
+void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 4
+ ensureContext(m_contextObj);
+ ::glUniformMatrix2fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 9
+ ensureContext(m_contextObj);
+ ::glUniformMatrix3fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 16
+ ensureContext(m_contextObj);
+ ::glUniformMatrix4fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::useProgram(WebGLProgram* program)
+{
+ ASSERT(program);
+
+ ensureContext(m_contextObj);
+ ::glUseProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::validateProgram(WebGLProgram* program)
+{
+ ASSERT(program);
+
+ ensureContext(m_contextObj);
+ ::glValidateProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::vertexAttrib1f(unsigned long indx, float v0)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib1f(indx, v0);
+}
+
+void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib1fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib2f(unsigned long indx, float v0, float v1)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib2f(indx, v0, v1);
+}
+
+void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib2fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib3f(indx, v0, v1, v2);
+}
+
+void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib3fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib4f(indx, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib4fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, unsigned long stride, unsigned long offset)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttribPointer(indx, size, type, normalized, stride, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height));
+}
+
+void GraphicsContext3D::getBooleanv(unsigned long pname, unsigned char* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetBooleanv(pname, value);
+}
+
+void GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long pname, int* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetBufferParameteriv(target, pname, value);
+}
+
+void GraphicsContext3D::getFloatv(unsigned long pname, float* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetFloatv(pname, value);
+}
+
+void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname, int* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
+}
+
+void GraphicsContext3D::getIntegerv(unsigned long pname, int* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetIntegerv(pname, value);
+}
+
+void GraphicsContext3D::getProgramiv(WebGLProgram* program, unsigned long pname, int* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetProgramiv((GLuint) program->object(), pname, value);
+}
+
+String GraphicsContext3D::getProgramInfoLog(WebGLProgram* program)
+{
+ ASSERT(program);
+
+ ensureContext(m_contextObj);
+ GLint length;
+ ::glGetProgramiv((GLuint) program->object(), GL_INFO_LOG_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) fastMalloc(length);
+ if (!info)
+ return "";
+
+ ::glGetProgramInfoLog((GLuint) program->object(), length, &size, info);
+ String s(info);
+ fastFree(info);
+ return s;
+}
+
+void GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigned long pname, int* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetRenderbufferParameterivEXT(target, pname, value);
+}
+
+void GraphicsContext3D::getShaderiv(WebGLShader* shader, unsigned long pname, int* value)
+{
+ ASSERT(shader);
+
+ ensureContext(m_contextObj);
+ ::glGetShaderiv((GLuint) shader->object(), pname, value);
+}
+
+String GraphicsContext3D::getShaderInfoLog(WebGLShader* shader)
+{
+ ASSERT(shader);
+
+ ensureContext(m_contextObj);
+ GLint length;
+ ::glGetShaderiv((GLuint) shader->object(), GL_INFO_LOG_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) fastMalloc(length);
+ if (!info)
+ return "";
+
+ ::glGetShaderInfoLog((GLuint) shader->object(), length, &size, info);
+ String s(info);
+ fastFree(info);
+ return s;
+}
+
+String GraphicsContext3D::getShaderSource(WebGLShader* shader)
+{
+ ASSERT(shader);
+
+ ensureContext(m_contextObj);
+ GLint length;
+ ::glGetShaderiv((GLuint) shader->object(), GL_SHADER_SOURCE_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) fastMalloc(length);
+ if (!info)
+ return "";
+
+ ::glGetShaderSource((GLuint) shader->object(), length, &size, info);
+ String s(info);
+ fastFree(info);
+ return s;
+}
+
+
+void GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long pname, float* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetTexParameterfv(target, pname, value);
+}
+
+void GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pname, int* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetTexParameteriv(target, pname, value);
+}
+
+void GraphicsContext3D::getUniformfv(WebGLProgram* program, long location, float* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetUniformfv((GLuint) program->object(), location, value);
+}
+
+void GraphicsContext3D::getUniformiv(WebGLProgram* program, long location, int* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetUniformiv((GLuint) program->object(), location, value);
+}
+
+long GraphicsContext3D::getUniformLocation(WebGLProgram* program, const String& name)
+{
+ ASSERT(program);
+
+ ensureContext(m_contextObj);
+ return ::glGetUniformLocation((GLuint) program->object(), name.utf8().data());
+}
+
+void GraphicsContext3D::getVertexAttribfv(unsigned long index, unsigned long pname, float* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetVertexAttribfv(index, pname, value);
+}
+
+void GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long pname, int* value)
+{
+ ensureContext(m_contextObj);
+ ::glGetVertexAttribiv(index, pname, value);
+}
+
+long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+
+ void* pointer;
+ ::glGetVertexAttribPointerv(index, pname, &pointer);
+ return reinterpret_cast<long>(pointer);
+}
+
+// Assumes the texture you want to go into is bound
+static void imageToTexture(Image* image, unsigned target, unsigned level)
+{
+ if (!image)
+ return;
+
+ CGImageRef textureImage = image->getCGImageRef();
+ if (!textureImage)
+ return;
+
+ size_t textureWidth = CGImageGetWidth(textureImage);
+ size_t textureHeight = CGImageGetHeight(textureImage);
+
+ GLubyte* textureData = (GLubyte*) fastMalloc(textureWidth * textureHeight * 4);
+ if (!textureData)
+ return;
+
+ CGContextRef textureContext = CGBitmapContextCreate(textureData, textureWidth, textureHeight, 8, textureWidth * 4,
+ CGImageGetColorSpace(textureImage), kCGImageAlphaPremultipliedLast);
+ CGContextSetBlendMode(textureContext, kCGBlendModeCopy);
+ CGContextDrawImage(textureContext, CGRectMake(0, 0, (CGFloat)textureWidth, (CGFloat)textureHeight), textureImage);
+ CGContextRelease(textureContext);
+
+ ::glTexImage2D(target, level, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
+ fastFree(textureData);
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, WebGLArray* pixels)
+{
+ // FIXME: Need to do bounds checking on the buffer here.
+ ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels->baseAddress());
+ return 0;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, ImageData* pixels)
+{
+ // FIXME: need to implement this form
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(internalformat);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(border);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(pixels);
+ return -1;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+ ASSERT(image);
+
+ ensureContext(m_contextObj);
+ imageToTexture(image, target, level);
+ return 0;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: need to implement this form
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(video);
+
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, WebGLArray* pixels)
+{
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(pixels);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, ImageData* pixels)
+{
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(pixels);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, Image* image, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(image);
+
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(video);
+
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+ return -1;
+}
+
+unsigned GraphicsContext3D::createBuffer()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenBuffers(1, &o);
+ return o;
+}
+
+unsigned GraphicsContext3D::createFramebuffer()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenFramebuffersEXT(1, &o);
+ return o;
+}
+
+unsigned GraphicsContext3D::createProgram()
+{
+ ensureContext(m_contextObj);
+ return glCreateProgram();
+}
+
+unsigned GraphicsContext3D::createRenderbuffer()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenRenderbuffersEXT(1, &o);
+ return o;
+}
+
+unsigned GraphicsContext3D::createShader(unsigned long type)
+{
+ ensureContext(m_contextObj);
+ return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
+}
+
+unsigned GraphicsContext3D::createTexture()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenTextures(1, &o);
+ return o;
+}
+
+void GraphicsContext3D::deleteBuffer(unsigned buffer)
+{
+ ensureContext(m_contextObj);
+ glDeleteBuffers(1, &buffer);
+}
+
+void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer)
+{
+ ensureContext(m_contextObj);
+ glDeleteFramebuffersEXT(1, &framebuffer);
+}
+
+void GraphicsContext3D::deleteProgram(unsigned program)
+{
+ ensureContext(m_contextObj);
+ glDeleteProgram(program);
+}
+
+void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer)
+{
+ ensureContext(m_contextObj);
+ glDeleteRenderbuffersEXT(1, &renderbuffer);
+}
+
+void GraphicsContext3D::deleteShader(unsigned shader)
+{
+ ensureContext(m_contextObj);
+ glDeleteShader(shader);
+}
+
+void GraphicsContext3D::deleteTexture(unsigned texture)
+{
+ ensureContext(m_contextObj);
+ glDeleteTextures(1, &texture);
+}
+
+int GraphicsContext3D::sizeInBytes(int type)
+{
+ switch (type) {
+ case GL_BYTE:
+ return sizeof(GLbyte);
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ case GL_SHORT:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GL_INT:
+ return sizeof(GLint);
+ case GL_UNSIGNED_INT:
+ return sizeof(GLuint);
+ case GL_FLOAT:
+ return sizeof(GLfloat);
+ default:
+ return 0;
+ }
+}
+
+void GraphicsContext3D::synthesizeGLError(unsigned long error)
+{
+ m_syntheticErrors.add(error);
+}
+
+}
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index 2404319..6c9b872 100644
--- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -50,27 +50,26 @@ void GraphicsContext::drawFocusRing(const Color& color)
int radius = (focusRingWidth() - 1) / 2;
int offset = radius + focusRingOffset();
- CGColorRef colorRef = color.isValid() ? createCGColor(color) : 0;
+ RetainPtr<CGColorRef> colorRef;
+ if (color.isValid())
+ colorRef.adoptCF(createCGColor(color));
- CGMutablePathRef focusRingPath = CGPathCreateMutable();
+ RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable());
const Vector<IntRect>& rects = focusRingRects();
unsigned rectCount = rects.size();
for (unsigned i = 0; i < rectCount; i++)
- CGPathAddRect(focusRingPath, 0, CGRectInset(rects[i], -offset, -offset));
+ CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rects[i], -offset, -offset));
CGContextRef context = platformContext();
#ifdef BUILDING_ON_TIGER
CGContextBeginTransparencyLayer(context, NULL);
#endif
CGContextBeginPath(context);
- CGContextAddPath(context, focusRingPath);
- wkDrawFocusRing(context, colorRef, radius);
+ CGContextAddPath(context, focusRingPath.get());
+ wkDrawFocusRing(context, colorRef.get(), radius);
#ifdef BUILDING_ON_TIGER
CGContextEndTransparencyLayer(context);
#endif
- CGColorRelease(colorRef);
-
- CGPathRelease(focusRingPath);
}
#ifdef BUILDING_ON_TIGER // Post-Tiger's setCompositeOperation() is defined in GraphicsContextCG.cpp.
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
index ebdc6ac..8024091 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
@@ -54,6 +54,7 @@ public:
// for hosting this GraphicsLayer in a native layer hierarchy
virtual NativeLayer nativeLayer() const;
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
virtual void addChild(GraphicsLayer*);
virtual void addChildAtIndex(GraphicsLayer*, int index);
virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
@@ -62,6 +63,8 @@ public:
virtual void removeFromParent();
+ virtual void setMaskLayer(GraphicsLayer*);
+
virtual void setPosition(const FloatPoint&);
virtual void setAnchorPoint(const FloatPoint3D&);
virtual void setSize(const FloatSize&);
@@ -86,6 +89,10 @@ public:
virtual void setNeedsDisplay();
virtual void setNeedsDisplayInRect(const FloatRect&);
+#if ENABLE(3D_CANVAS)
+ virtual void setGraphicsContext3DNeedsDisplay();
+#endif
+
virtual void setContentsRect(const IntRect&);
virtual void suspendAnimations(double time);
@@ -98,13 +105,14 @@ public:
virtual void setContentsToImage(Image*);
virtual void setContentsToVideo(PlatformLayer*);
+#if ENABLE(3D_CANVAS)
+ virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*);
+#endif
virtual PlatformLayer* platformLayer() const;
-#ifndef NDEBUG
virtual void setDebugBackgroundColor(const Color&);
virtual void setDebugBorder(const Color&, float borderWidth);
-#endif
virtual void setGeometryOrientation(CompositingCoordinatesOrientation);
@@ -170,8 +178,12 @@ private:
void updateContentsImage();
void updateContentsVideo();
+#if ENABLE(3D_CANVAS)
+ void updateContentsGraphicsContext3D();
+#endif
void updateContentsRect();
void updateGeometryOrientation();
+ void updateMaskLayer();
void updateLayerAnimations();
@@ -199,8 +211,12 @@ private:
DirtyRectsChanged = 1 << 16,
ContentsImageChanged = 1 << 17,
ContentsVideoChanged = 1 << 18,
- ContentsRectChanged = 1 << 19,
- GeometryOrientationChanged = 1 << 20
+#if ENABLE(3D_CANVAS)
+ ContentsGraphicsContext3DChanged = 1 << 19,
+#endif
+ ContentsRectChanged = 1 << 20,
+ GeometryOrientationChanged = 1 << 21,
+ MaskLayerChanged = 1 << 22
};
typedef unsigned LayerChangeFlags;
void noteLayerPropertyChanged(LayerChangeFlags flags);
@@ -215,6 +231,9 @@ private:
NoContentsLayer = 0,
ContentsLayerForImage,
ContentsLayerForVideo
+#if ENABLE(3D_CANVAS)
+ ,ContentsLayerForGraphicsLayer3D
+#endif
};
ContentsLayerPurpose m_contentsLayerPurpose;
@@ -260,6 +279,11 @@ private:
Vector<FloatRect> m_dirtyRects;
LayerChangeFlags m_uncommittedChanges;
+
+#if ENABLE(3D_CANVAS)
+ PlatformGraphicsContext3D m_platformGraphicsContext3D;
+ Platform3DObject m_platformTexture;
+#endif
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index e5b9035..dea6bfc 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -31,6 +31,9 @@
#import "Animation.h"
#import "BlockExceptions.h"
+#if ENABLE(3D_CANVAS)
+#import "Canvas3DLayer.h"
+#endif
#import "CString.h"
#import "FloatConversion.h"
#import "FloatRect.h"
@@ -44,6 +47,7 @@
#import "WebLayer.h"
#import "WebTiledLayer.h"
#import <limits.h>
+#import <objc/objc-auto.h>
#import <wtf/CurrentTime.h>
#import <wtf/UnusedParam.h>
#import <wtf/RetainPtr.h>
@@ -145,11 +149,11 @@ static NSValue* getTransformFunctionValue(const TransformOperation* transformOp,
case TransformOperation::ROTATE_Y:
return [NSNumber numberWithDouble:transformOp ? deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle()) : 0];
case TransformOperation::SCALE_X:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 0];
+ return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1];
case TransformOperation::SCALE_Y:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 0];
+ return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1];
case TransformOperation::SCALE_Z:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 0];
+ return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1];
case TransformOperation::TRANSLATE_X:
return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0];
case TransformOperation::TRANSLATE_Y:
@@ -157,13 +161,23 @@ static NSValue* getTransformFunctionValue(const TransformOperation* transformOp,
case TransformOperation::TRANSLATE_Z:
return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0];
case TransformOperation::SCALE:
+ case TransformOperation::SCALE_3D:
+ return [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1],
+ nil];
case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_3D:
+ return [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->y(size) : 0],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0],
+ nil];
case TransformOperation::SKEW_X:
case TransformOperation::SKEW_Y:
case TransformOperation::SKEW:
case TransformOperation::MATRIX:
- case TransformOperation::SCALE_3D:
- case TransformOperation::TRANSLATE_3D:
case TransformOperation::ROTATE_3D:
case TransformOperation::MATRIX_3D:
case TransformOperation::PERSPECTIVE:
@@ -204,6 +218,12 @@ static NSString* getValueFunctionNameForTransformOperation(TransformOperation::O
return @"translateY"; // kCAValueFunctionTranslateY;
case TransformOperation::TRANSLATE_Z:
return @"translateZ"; // kCAValueFunctionTranslateZ;
+ case TransformOperation::SCALE:
+ case TransformOperation::SCALE_3D:
+ return @"scale"; // kCAValueFunctionScale;
+ case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_3D:
+ return @"translate"; // kCAValueFunctionTranslate;
default:
return nil;
}
@@ -255,7 +275,6 @@ static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction& tim
return 0;
}
-#ifndef NDEBUG
static void setLayerBorderColor(PlatformLayer* layer, const Color& color)
{
CGColorRef borderColor = createCGColor(color);
@@ -267,7 +286,6 @@ static void clearBorderColor(PlatformLayer* layer)
{
[layer setBorderColor:nil];
}
-#endif
static void setLayerBackgroundColor(PlatformLayer* layer, const Color& color)
{
@@ -281,6 +299,18 @@ static void clearLayerBackgroundColor(PlatformLayer* layer)
[layer setBackgroundColor:0];
}
+static void safeSetSublayers(CALayer* layer, NSArray* sublayers)
+{
+ // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
+ if (objc_collectingEnabled() && ![sublayers count]) {
+ while ([[layer sublayers] count])
+ [[[layer sublayers] objectAtIndex:0] removeFromSuperlayer];
+ return;
+ }
+
+ [layer setSublayers:sublayers];
+}
+
static bool caValueFunctionSupported()
{
static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
@@ -298,20 +328,6 @@ GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoord
return CompositingCoordinatesBottomUp;
}
-#ifndef NDEBUG
-bool GraphicsLayer::showDebugBorders()
-{
- static bool showDebugBorders = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebCoreLayerBorders"];
- return showDebugBorders;
-}
-
-bool GraphicsLayer::showRepaintCounter()
-{
- static bool showRepaintCounter = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebCoreLayerRepaintCounter"];
- return showRepaintCounter;
-}
-#endif
-
static NSDictionary* nullActionsDictionary()
{
NSNull* nullValue = [NSNull null];
@@ -331,16 +347,20 @@ static NSDictionary* nullActionsDictionary()
return actions;
}
-GraphicsLayer* GraphicsLayer::createGraphicsLayer(GraphicsLayerClient* client)
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
{
return new GraphicsLayerCA(client);
}
GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
-: GraphicsLayer(client)
-, m_contentsLayerPurpose(NoContentsLayer)
-, m_contentsLayerHasBackgroundColor(false)
-, m_uncommittedChanges(NoChange)
+ : GraphicsLayer(client)
+ , m_contentsLayerPurpose(NoContentsLayer)
+ , m_contentsLayerHasBackgroundColor(false)
+ , m_uncommittedChanges(NoChange)
+#if ENABLE(3D_CANVAS)
+ , m_platformGraphicsContext3D(NullPlatformGraphicsContext3D)
+ , m_platformTexture(NullPlatform3DObject)
+#endif
{
BEGIN_BLOCK_OBJC_EXCEPTIONS
m_layer.adoptNS([[WebLayer alloc] init]);
@@ -350,9 +370,7 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
setContentsOrientation(defaultContentsOrientation());
#endif
-#ifndef NDEBUG
updateDebugIndicators();
-#endif
m_animationDelegate.adoptNS([[WebAnimationDelegate alloc] init]);
[m_animationDelegate.get() setLayer:this];
@@ -392,6 +410,15 @@ NativeLayer GraphicsLayerCA::nativeLayer() const
return m_layer.get();
}
+bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool childrenChanged = GraphicsLayer::setChildren(children);
+ if (childrenChanged)
+ noteLayerPropertyChanged(ChildrenChanged);
+
+ return childrenChanged;
+}
+
void GraphicsLayerCA::addChild(GraphicsLayer* childLayer)
{
GraphicsLayer::addChild(childLayer);
@@ -432,6 +459,15 @@ void GraphicsLayerCA::removeFromParent()
GraphicsLayer::removeFromParent();
}
+void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer)
+{
+ if (layer == m_maskLayer)
+ return;
+
+ GraphicsLayer::setMaskLayer(layer);
+ noteLayerPropertyChanged(MaskLayerChanged);
+}
+
void GraphicsLayerCA::setPosition(const FloatPoint& point)
{
if (point == m_position)
@@ -672,10 +708,10 @@ void GraphicsLayerCA::setContentsToImage(Image* image)
CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
- if (CFEqual(colorSpace, deviceRGB)) {
- // CoreGraphics renders images tagged with DeviceRGB using GenericRGB. When we hand such
+ if (colorSpace && CFEqual(colorSpace, deviceRGB)) {
+ // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such
// images to CA we need to tag them similarly so CA rendering matches CG rendering.
- static CGColorSpaceRef genericRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB));
}
m_contentsLayerPurpose = ContentsLayerForImage;
@@ -733,6 +769,9 @@ void GraphicsLayerCA::recursiveCommitChanges()
{
commitLayerChanges();
+ if (m_maskLayer)
+ static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChanges();
+
const Vector<GraphicsLayer*>& childLayers = children();
size_t numChildren = childLayers.size();
for (size_t i = 0; i < numChildren; ++i) {
@@ -763,7 +802,12 @@ void GraphicsLayerCA::commitLayerChanges()
if (m_uncommittedChanges & ContentsVideoChanged) // Needs to happen before ChildrenChanged
updateContentsVideo();
-
+
+#if ENABLE(3D_CANVAS)
+ if (m_uncommittedChanges & ContentsGraphicsContext3DChanged) // Needs to happen before ChildrenChanged
+ updateContentsGraphicsContext3D();
+#endif
+
if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video
updateLayerBackgroundColor();
@@ -812,6 +856,9 @@ void GraphicsLayerCA::commitLayerChanges()
if (m_uncommittedChanges & GeometryOrientationChanged)
updateGeometryOrientation();
+ if (m_uncommittedChanges & MaskLayerChanged)
+ updateMaskLayer();
+
m_uncommittedChanges = NoChange;
END_BLOCK_OBJC_EXCEPTIONS
}
@@ -821,10 +868,12 @@ void GraphicsLayerCA::updateSublayerList()
NSMutableArray* newSublayers = nil;
if (m_transformLayer) {
- // FIXME: add the primary layer in the correct order with negative z-order children.
+ // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
newSublayers = [[NSMutableArray alloc] initWithObjects:m_layer.get(), nil];
} else if (m_contentsLayer) {
// FIXME: add the contents layer in the correct order with negative z-order children.
+ // This does not cause visible rendering issues because currently contents layers are only used
+ // for replaced elements that don't have children.
newSublayers = [[NSMutableArray alloc] initWithObjects:m_contentsLayer.get(), nil];
}
@@ -843,17 +892,16 @@ void GraphicsLayerCA::updateSublayerList()
[newSublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
if (m_transformLayer) {
- [m_transformLayer.get() setSublayers:newSublayers];
+ safeSetSublayers(m_transformLayer.get(), newSublayers);
if (m_contentsLayer) {
// If we have a transform layer, then the contents layer is parented in the
// primary layer (which is itself a child of the transform layer).
- [m_layer.get() setSublayers:nil];
+ safeSetSublayers(m_layer.get(), nil);
[m_layer.get() addSublayer:m_contentsLayer.get()];
}
- } else {
- [m_layer.get() setSublayers:newSublayers];
- }
+ } else
+ safeSetSublayers(m_layer.get(), newSublayers);
[newSublayers release];
}
@@ -919,9 +967,7 @@ void GraphicsLayerCA::updateChildrenTransform()
void GraphicsLayerCA::updateMasksToBounds()
{
[m_layer.get() setMasksToBounds:m_masksToBounds];
-#ifndef NDEBUG
updateDebugIndicators();
-#endif
}
void GraphicsLayerCA::updateContentsOpaque()
@@ -1006,9 +1052,7 @@ void GraphicsLayerCA::updateLayerDrawsContent()
else
[m_layer.get() setContents:nil];
-#ifndef NDEBUG
updateDebugIndicators();
-#endif
}
void GraphicsLayerCA::updateLayerBackgroundColor()
@@ -1061,6 +1105,18 @@ void GraphicsLayerCA::updateContentsVideo()
}
}
+#if ENABLE(3D_CANVAS)
+void GraphicsLayerCA::updateContentsGraphicsContext3D()
+{
+ // Canvas3D layer was set as m_contentsLayer, and will get parented in updateSublayerList().
+ if (m_contentsLayer) {
+ setupContentsLayer(m_contentsLayer.get());
+ [m_contentsLayer.get() setNeedsDisplay];
+ updateContentsRect();
+ }
+}
+#endif
+
void GraphicsLayerCA::updateContentsRect()
{
if (!m_contentsLayer)
@@ -1094,6 +1150,12 @@ void GraphicsLayerCA::updateGeometryOrientation()
#endif
}
+void GraphicsLayerCA::updateMaskLayer()
+{
+ CALayer* maskCALayer = m_maskLayer ? m_maskLayer->platformLayer() : 0;
+ [m_layer.get() setMask:maskCALayer];
+}
+
void GraphicsLayerCA::updateLayerAnimations()
{
if (m_transitionPropertiesToRemove.size()) {
@@ -1182,6 +1244,21 @@ void GraphicsLayerCA::setAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedP
[layer addAnimation:caAnim forKey:animationName];
}
+// Workaround for <rdar://problem/7311367>
+static void bug7311367Workaround(CALayer* transformLayer, const TransformationMatrix& transform)
+{
+ if (!transformLayer)
+ return;
+
+ CATransform3D caTransform;
+ copyTransform(caTransform, transform);
+ caTransform.m41 += 1;
+ [transformLayer setTransform:caTransform];
+
+ caTransform.m41 -= 1;
+ [transformLayer setTransform:caTransform];
+}
+
bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, int index)
{
PlatformLayer* layer = animatedLayer(property);
@@ -1192,10 +1269,11 @@ bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, int
return false;
[layer removeAnimationForKey:animationName];
+
+ bug7311367Workaround(m_transformLayer.get(), m_transform);
return true;
}
-
static void copyAnimationProperties(CAPropertyAnimation* from, CAPropertyAnimation* to)
{
[to setBeginTime:[from beginTime]];
@@ -1247,6 +1325,40 @@ void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, int ind
[layer addAnimation:pausedAnim forKey:animationName]; // This will replace the running animation.
}
+#if ENABLE(3D_CANVAS)
+void GraphicsLayerCA::setContentsToGraphicsContext3D(const GraphicsContext3D* graphicsContext3D)
+{
+ PlatformGraphicsContext3D context = graphicsContext3D->platformGraphicsContext3D();
+ Platform3DObject texture = graphicsContext3D->platformTexture();
+
+ if (context == m_platformGraphicsContext3D && texture == m_platformTexture)
+ return;
+
+ m_platformGraphicsContext3D = context;
+ m_platformTexture = texture;
+
+ noteLayerPropertyChanged(ChildrenChanged);
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+
+ if (m_platformGraphicsContext3D != NullPlatformGraphicsContext3D && m_platformTexture != NullPlatform3DObject) {
+ // create the inner 3d layer
+ m_contentsLayer.adoptNS([[Canvas3DLayer alloc] initWithContext:static_cast<CGLContextObj>(m_platformGraphicsContext3D) texture:static_cast<GLuint>(m_platformTexture)]);
+#ifndef NDEBUG
+ [m_contentsLayer.get() setName:@"3D Layer"];
+#endif
+ } else {
+ // remove the inner layer
+ m_contentsLayer = 0;
+ }
+
+ END_BLOCK_OBJC_EXCEPTIONS
+
+ noteLayerPropertyChanged(ContentsGraphicsContext3DChanged);
+ m_contentsLayerPurpose = m_contentsLayer ? ContentsLayerForGraphicsLayer3D : NoContentsLayer;
+}
+#endif
+
void GraphicsLayerCA::repaintLayerDirtyRects()
{
if (!m_dirtyRects.size())
@@ -1582,7 +1694,6 @@ PlatformLayer* GraphicsLayerCA::platformLayer() const
return primaryLayer();
}
-#ifndef NDEBUG
void GraphicsLayerCA::setDebugBackgroundColor(const Color& color)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS
@@ -1609,7 +1720,6 @@ void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth)
END_BLOCK_OBJC_EXCEPTIONS
}
-#endif // NDEBUG
bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const
{
@@ -1656,7 +1766,7 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer)
}
[m_layer.get() setLayerOwner:this];
- [m_layer.get() setSublayers:[oldLayer.get() sublayers]];
+ safeSetSublayers(m_layer.get(), [oldLayer.get() sublayers]);
[[oldLayer.get() superlayer] replaceSublayer:oldLayer.get() with:m_layer.get()];
@@ -1687,9 +1797,7 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer)
// need to tell new layer to draw itself
setNeedsDisplay();
-#ifndef NDEBUG
updateDebugIndicators();
-#endif
}
GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const
@@ -1733,12 +1841,10 @@ void GraphicsLayerCA::setupContentsLayer(CALayer* contentsLayer)
} else
[contentsLayer setAnchorPoint:CGPointZero];
-#ifndef NDEBUG
if (showDebugBorders()) {
setLayerBorderColor(contentsLayer, Color(0, 0, 128, 180));
[contentsLayer setBorderWidth:1.0f];
}
-#endif
}
void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity)
@@ -1765,6 +1871,14 @@ void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags)
m_uncommittedChanges |= flags;
}
+#if ENABLE(3D_CANVAS)
+void GraphicsLayerCA::setGraphicsContext3DNeedsDisplay()
+{
+ if (m_contentsLayerPurpose == ContentsLayerForGraphicsLayer3D)
+ [m_contentsLayer.get() setNeedsDisplay];
+}
+#endif
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/mac/IconMac.mm b/WebCore/platform/graphics/mac/IconMac.mm
index 63abe59..aee7234 100644
--- a/WebCore/platform/graphics/mac/IconMac.mm
+++ b/WebCore/platform/graphics/mac/IconMac.mm
@@ -39,27 +39,32 @@ Icon::~Icon()
{
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
- // Don't pass relative filenames -- we don't want a result that depends on the current directory.
- // Need 0U here to disambiguate String::operator[] from operator(NSString*, int)[]
- if (filename.isEmpty() || filename[0U] != '/')
+ if (filenames.isEmpty())
return 0;
- NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile:filename];
- if (!image)
- return 0;
+ bool useIconFromFirstFile;
+#ifdef BUILDING_ON_TIGER
+ // FIXME: find a better image for multiple files to use on Tiger.
+ useIconFromFirstFile = true;
+#else
+ useIconFromFirstFile = filenames.size() == 1;
+#endif
+ if (useIconFromFirstFile) {
+ // Don't pass relative filenames -- we don't want a result that depends on the current directory.
+ // Need 0U here to disambiguate String::operator[] from operator(NSString*, int)[]
+ if (filenames[0].isEmpty() || filenames[0][0U] != '/')
+ return 0;
- return adoptRef(new Icon(image));
-}
+ NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile:filenames[0]];
+ if (!image)
+ return 0;
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
-{
- if (filenames.isEmpty())
- return 0;
+ return adoptRef(new Icon(image));
+ }
#ifdef BUILDING_ON_TIGER
- // FIXME: find a better image to use on Tiger.
- return createIconForFile(filenames[0]);
+ return 0;
#else
NSImage* image = [NSImage imageNamed:NSImageNameMultipleDocuments];
if (!image)
diff --git a/WebCore/platform/graphics/mac/ImageMac.mm b/WebCore/platform/graphics/mac/ImageMac.mm
index a0d257b..672c3c8 100644
--- a/WebCore/platform/graphics/mac/ImageMac.mm
+++ b/WebCore/platform/graphics/mac/ImageMac.mm
@@ -94,16 +94,15 @@ CFDataRef BitmapImage::getTIFFRepresentation()
RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(0, 0));
// FIXME: Use type kCGImageTypeIdentifierTIFF constant once is becomes available in the API
- CGImageDestinationRef destination = CGImageDestinationCreateWithData(data.get(), CFSTR("public.tiff"), numValidFrames, 0);
-
+ RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), CFSTR("public.tiff"), numValidFrames, 0));
+
if (!destination)
return 0;
for (unsigned i = 0; i < numValidFrames; ++i)
- CGImageDestinationAddImage(destination, images[i], 0);
+ CGImageDestinationAddImage(destination.get(), images[i], 0);
- CGImageDestinationFinalize(destination);
- CFRelease(destination);
+ CGImageDestinationFinalize(destination.get());
m_tiffRep = data;
return m_tiffRep.get();
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 54eea00..7aaf95d 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -77,8 +77,12 @@ private:
static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
static bool isAvailable();
+ PlatformMedia platformMedia() const;
+
IntSize naturalSize() const;
bool hasVideo() const;
+ bool hasAudio() const;
+ bool supportsFullscreen() const;
void load(const String& url);
void cancelLoad();
@@ -97,6 +101,9 @@ private:
void setVolume(float);
void setPreservesPitch(bool);
+ bool hasClosedCaptions() const;
+ void setClosedCaptionsVisible(bool);
+
void setEndTime(float time);
int dataRate() const;
@@ -104,7 +111,7 @@ private:
MediaPlayer::NetworkState networkState() const { return m_networkState; }
MediaPlayer::ReadyState readyState() const { return m_readyState; }
- float maxTimeBuffered() const;
+ PassRefPtr<TimeRanges> buffered() const;
float maxTimeSeekable() const;
unsigned bytesLoaded() const;
bool totalBytesKnown() const;
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index c1d7fcb..dfb5958 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -39,6 +39,7 @@
#import "KURL.h"
#import "MIMETypeRegistry.h"
#import "SoftLinking.h"
+#import "TimeRanges.h"
#import "WebCoreSystemInterface.h"
#import <QTKit/QTKit.h>
#import <objc/objc-runtime.h>
@@ -84,6 +85,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieAskUnresolvedDataRefsAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieHasAudioAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieIsActiveAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateDidChangeNotification, NSString *)
@@ -119,6 +121,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *)
#define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute()
#define QTMovieDidEndNotification getQTMovieDidEndNotification()
#define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute()
+#define QTMovieHasAudioAttribute getQTMovieHasAudioAttribute()
#define QTMovieIsActiveAttribute getQTMovieIsActiveAttribute()
#define QTMovieLoadStateAttribute getQTMovieLoadStateAttribute()
#define QTMovieLoadStateDidChangeNotification getQTMovieLoadStateDidChangeNotification()
@@ -230,7 +233,7 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
void MediaPlayerPrivate::createQTMovie(const String& url)
{
- NSURL *cocoaURL = KURL(url);
+ NSURL *cocoaURL = KURL(ParsedURLString, url);
NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
cocoaURL, QTMovieURLAttribute,
[NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute,
@@ -562,6 +565,12 @@ void MediaPlayerPrivate::load(const String& url)
[m_objcObserver.get() setDelayCallbacks:NO];
}
+PlatformMedia MediaPlayerPrivate::platformMedia() const
+{
+ PlatformMedia plaftformMedia = { m_qtMovie.get() };
+ return plaftformMedia;
+}
+
void MediaPlayerPrivate::play()
{
if (!metaDataAvailable())
@@ -719,18 +728,54 @@ bool MediaPlayerPrivate::hasVideo() const
return [[m_qtMovie.get() attributeForKey:QTMovieHasVideoAttribute] boolValue];
}
+bool MediaPlayerPrivate::hasAudio() const
+{
+ if (!m_qtMovie)
+ return false;
+ return [[m_qtMovie.get() attributeForKey:QTMovieHasAudioAttribute] boolValue];
+}
+
+bool MediaPlayerPrivate::supportsFullscreen() const
+{
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ return true;
+#else
+ // See <rdar://problem/7389945>
+ return false;
+#endif
+}
+
void MediaPlayerPrivate::setVolume(float volume)
{
+ if (m_qtMovie)
+ [m_qtMovie.get() setVolume:volume];
+}
+
+bool MediaPlayerPrivate::hasClosedCaptions() const
+{
if (!metaDataAvailable())
- return;
- [m_qtMovie.get() setVolume:volume];
+ return false;
+ return wkQTMovieHasClosedCaptions(m_qtMovie.get());
+}
+
+void MediaPlayerPrivate::setClosedCaptionsVisible(bool closedCaptionsVisible)
+{
+ if (metaDataAvailable()) {
+ wkQTMovieSetShowClosedCaptions(m_qtMovie.get(), closedCaptionsVisible);
+
+#if USE(ACCELERATED_COMPOSITING) && (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
+ if (closedCaptionsVisible && m_qtVideoLayer) {
+ // Captions will be rendered upsided down unless we flag the movie as flipped (again). See <rdar://7408440>.
+ [m_qtVideoLayer.get() setGeometryFlipped:YES];
+ }
+#endif
+ }
}
void MediaPlayerPrivate::setRate(float rate)
{
- if (!metaDataAvailable())
- return;
- [m_qtMovie.get() setRate:rate];
+ if (m_qtMovie)
+ [m_qtMovie.get() setRate:rate];
}
void MediaPlayerPrivate::setPreservesPitch(bool preservesPitch)
@@ -758,10 +803,13 @@ int MediaPlayerPrivate::dataRate() const
return wkQTMovieDataRate(m_qtMovie.get());
}
-
-float MediaPlayerPrivate::maxTimeBuffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
- return maxTimeLoaded();
+ RefPtr<TimeRanges> timeRanges = TimeRanges::create();
+ float loaded = maxTimeLoaded();
+ if (loaded > 0)
+ timeRanges->add(0, loaded);
+ return timeRanges.release();
}
float MediaPlayerPrivate::maxTimeSeekable() const
@@ -1136,10 +1184,10 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
TextRun textRun(text.characters(), text.length());
const Color color(255, 0, 0);
context->scale(FloatSize(1.0f, -1.0f));
- context->setStrokeColor(color);
+ context->setStrokeColor(color, styleToUse->colorSpace());
context->setStrokeStyle(SolidStroke);
context->setStrokeThickness(1.0f);
- context->setFillColor(color);
+ context->setFillColor(color, styleToUse->colorSpace());
context->drawText(styleToUse->font(), textRun, IntPoint(2, -3));
}
}
diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index cdde7cf..97a7251 100644
--- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -50,6 +50,8 @@
- (BOOL)_isFakeFixedPitch;
@end
+using namespace std;
+
namespace WebCore {
const float smallCapsFontSizeMultiplier = 0.7f;
@@ -269,7 +271,7 @@ void SimpleFontData::platformInit()
// and web pages that foolishly use this metric for width will be laid out
// poorly if we return an accurate height. Classic case is Times 13 point,
// which has an "x" that is 7x6 pixels.
- m_xHeight = MAX(NSMaxX(xBox), NSMaxY(xBox));
+ m_xHeight = max(NSMaxX(xBox), NSMaxY(xBox));
} else
m_xHeight = [m_platformData.font() xHeight];
}
@@ -443,13 +445,13 @@ CTFontRef SimpleFontData::getCTFont() const
return m_CTFont.get();
}
-CFDictionaryRef SimpleFontData::getCFStringAttributes() const
+CFDictionaryRef SimpleFontData::getCFStringAttributes(TextRenderingMode textMode) const
{
if (m_CFStringAttributes)
return m_CFStringAttributes.get();
- static const float kerningAdjustmentValue = 0;
- static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue);
+ bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision;
+ bool allowLigatures = platformData().allowsLigatures() || allowKerning;
static const int ligaturesNotAllowedValue = 0;
static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue);
@@ -457,10 +459,23 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes() const
static const int ligaturesAllowedValue = 1;
static CFNumberRef ligaturesAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesAllowedValue);
- static const void* attributeKeys[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName };
- const void* attributeValues[] = { getCTFont(), kerningAdjustment, platformData().allowsLigatures() ? ligaturesAllowed : ligaturesNotAllowed };
-
- m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, attributeKeys, attributeValues, sizeof(attributeKeys) / sizeof(*attributeKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ if (!allowKerning) {
+ static const float kerningAdjustmentValue = 0;
+ static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue);
+ static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName };
+ const void* valuesWithKerningDisabled[] = { getCTFont(), kerningAdjustment, allowLigatures
+ ? ligaturesAllowed : ligaturesNotAllowed };
+ m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, keysWithKerningDisabled, valuesWithKerningDisabled,
+ sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled),
+ &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ } else {
+ // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning.
+ static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName };
+ const void* valuesWithKerningEnabled[] = { getCTFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed };
+ m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, keysWithKerningEnabled, valuesWithKerningEnabled,
+ sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled),
+ &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ }
return m_CFStringAttributes.get();
}
diff --git a/WebCore/platform/graphics/mac/WebLayer.mm b/WebCore/platform/graphics/mac/WebLayer.mm
index 2647466..56b28e6 100644
--- a/WebCore/platform/graphics/mac/WebLayer.mm
+++ b/WebCore/platform/graphics/mac/WebLayer.mm
@@ -80,7 +80,6 @@ using namespace WebCore;
}
#endif
-#ifndef NDEBUG
if (layerContents->showRepaintCounter()) {
bool isTiledLayer = [layer isKindOfClass:[CATiledLayer class]];
@@ -107,7 +106,6 @@ using namespace WebCore;
CGContextRestoreGState(context);
}
-#endif
CGContextRestoreGState(context);
}
diff --git a/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp
new file mode 100644
index 0000000..b4cdb09
--- /dev/null
+++ b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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"
+#if ENABLE(OPENTYPE_SANITIZER)
+#include "OpenTypeSanitizer.h"
+
+#include "SharedBuffer.h"
+#include "opentype-sanitiser.h"
+#include "ots-memory-stream.h"
+#include <wtf/OwnArrayPtr.h>
+
+namespace WebCore {
+
+PassRefPtr<SharedBuffer> OpenTypeSanitizer::sanitize()
+{
+ if (!m_buffer)
+ return 0;
+
+ // This is the largest web font size which we'll try to transcode.
+ static const size_t maxWebFontSize = 30 * 1024 * 1024; // 30 MB
+ if (m_buffer->size() > maxWebFontSize)
+ return 0;
+
+ // A transcoded font is usually smaller than an original font.
+ // However, it can be slightly bigger than the original one due to
+ // name table replacement and/or padding for glyf table.
+ static const size_t padLen = 20 * 1024; // 20 kB
+
+ OwnArrayPtr<unsigned char> transcodeRawBuffer(new unsigned char[m_buffer->size() + padLen]);
+ ots::MemoryStream output(transcodeRawBuffer.get(), m_buffer->size() + padLen);
+ if (!ots::Process(&output, reinterpret_cast<const uint8_t*>(m_buffer->data()), m_buffer->size()))
+ return 0;
+
+ const size_t transcodeLen = output.Tell();
+ return SharedBuffer::create(transcodeRawBuffer.get(), transcodeLen);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(OPENTYPE_SANITIZER)
diff --git a/WebCore/platform/graphics/opentype/OpenTypeSanitizer.h b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.h
new file mode 100644
index 0000000..3f93448
--- /dev/null
+++ b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OpenTypeSanitizer_h
+#define OpenTypeSanitizer_h
+
+#if ENABLE(OPENTYPE_SANITIZER)
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class SharedBuffer;
+
+class OpenTypeSanitizer {
+public:
+ explicit OpenTypeSanitizer(SharedBuffer* buffer)
+ : m_buffer(buffer)
+ {
+ }
+
+ PassRefPtr<SharedBuffer> sanitize();
+
+private:
+ SharedBuffer* const m_buffer;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(OPENTYPE_SANITIZER)
+#endif // OpenTypeSanitizer_h
diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
index 895887f..3a60160 100644
--- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
+++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -339,7 +340,10 @@ bool getEOTHeader(SharedBuffer* fontData, EOTHeader& eotHeader, size_t& overlayD
return true;
}
-HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
+// code shared by renameFont and renameAndActivateFont
+// adds fontName to the font table in fontData, and writes the new font table to rewrittenFontTable
+// returns the size of the name table (which is used by renameAndActivateFont), or 0 on early abort
+static size_t renameFontInternal(SharedBuffer* fontData, const String& fontName, Vector<char> &rewrittenFontData)
{
size_t originalDataSize = fontData->size();
const sfntHeader* sfnt = reinterpret_cast<const sfntHeader*>(fontData->data());
@@ -357,7 +361,7 @@ HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
// Rounded up to a multiple of 4 to simplify the checksum calculation.
size_t nameTableSize = ((offsetof(nameTable, nameRecords) + nameRecordCount * sizeof(nameRecord) + fontName.length() * sizeof(UChar)) & ~3) + 4;
- Vector<char> rewrittenFontData(fontData->size() + nameTableSize);
+ rewrittenFontData.resize(fontData->size() + nameTableSize);
char* data = rewrittenFontData.data();
memcpy(data, fontData->data(), originalDataSize);
@@ -394,15 +398,50 @@ HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
for (unsigned i = 0; i * sizeof(BigEndianULong) < nameTableSize; ++i)
rewrittenSfnt->tables[t].checkSum = rewrittenSfnt->tables[t].checkSum + reinterpret_cast<BigEndianULong*>(name)[i];
+ return nameTableSize;
+}
+
+#if PLATFORM(WINCE)
+// AddFontMemResourceEx does not exist on WinCE, so we must handle the font data manually
+// This function just renames the font and overwrites the old font data with the new
+bool renameFont(SharedBuffer* fontData, const String& fontName)
+{
+ // abort if the data is too small to be a font header with a "tables" entry
+ if (fontData->size() < offsetof(sfntHeader, tables))
+ return false;
+
+ // abort if the data is too small to hold all the tables specified in the header
+ const sfntHeader* header = reinterpret_cast<const sfntHeader*>(fontData->data());
+ if (fontData->size() < offsetof(sfntHeader, tables) + header->numTables * sizeof(TableDirectoryEntry))
+ return false;
+
+ Vector<char> rewrittenFontData;
+ if (!renameFontInternal(fontData, fontName, rewrittenFontData))
+ return false;
+
+ fontData->clear();
+ fontData->append(rewrittenFontData.data(), rewrittenFontData.size());
+ return true;
+}
+#else
+// Rename the font and install the new font data into the system
+HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
+{
+ Vector<char> rewrittenFontData;
+ size_t nameTableSize = renameFontInternal(fontData, fontName, rewrittenFontData);
+ if (!nameTableSize)
+ return 0;
+
DWORD numFonts = 0;
- HANDLE fontHandle = AddFontMemResourceEx(data, originalDataSize + nameTableSize, 0, &numFonts);
+ HANDLE fontHandle = AddFontMemResourceEx(rewrittenFontData.data(), fontData->size() + nameTableSize, 0, &numFonts);
- if (fontHandle && numFonts != 1) {
+ if (fontHandle && numFonts < 1) {
RemoveFontMemResourceEx(fontHandle);
return 0;
}
return fontHandle;
}
+#endif
}
diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.h b/WebCore/platform/graphics/opentype/OpenTypeUtilities.h
index 13dad6f..4c75314 100644
--- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.h
+++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,6 +36,10 @@ struct BigEndianUShort;
struct EOTPrefix;
class SharedBuffer;
+#if PLATFORM(WINCE)
+typedef unsigned __int8 UInt8;
+#endif
+
struct EOTHeader {
EOTHeader();
diff --git a/WebCore/platform/graphics/qt/ColorQt.cpp b/WebCore/platform/graphics/qt/ColorQt.cpp
index 5d16740..151766a 100644
--- a/WebCore/platform/graphics/qt/ColorQt.cpp
+++ b/WebCore/platform/graphics/qt/ColorQt.cpp
@@ -40,7 +40,10 @@ Color::Color(const QColor& c)
Color::operator QColor() const
{
- return QColor(red(), green(), blue(), alpha());
+ if (m_valid)
+ return QColor(red(), green(), blue(), alpha());
+ else
+ return QColor();
}
}
diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp
index 5d29389..82fb709 100644
--- a/WebCore/platform/graphics/qt/FontCacheQt.cpp
+++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp
@@ -34,260 +34,39 @@
#include <wtf/ListHashSet.h>
#include <wtf/StdLibExtras.h>
+#include <QFont>
+
using namespace WTF;
namespace WebCore {
-FontCache* fontCache()
-{
- DEFINE_STATIC_LOCAL(FontCache, globalFontCache, ());
- return &globalFontCache;
-}
-
-FontCache::FontCache()
+void FontCache::platformInit()
{
}
-void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
-{
-}
-
-// This type must be consistent with FontPlatformData's ctor - the one which
-// gets FontDescription as it's parameter.
-class FontPlatformDataCacheKey {
-public:
- FontPlatformDataCacheKey(const FontDescription& description)
- : m_familyName()
- , m_bold(false)
- , m_size(description.computedPixelSize())
- , m_italic(description.italic())
- , m_smallCaps(description.smallCaps())
- , m_hash(0)
- {
- // FIXME: Map all FontWeight values to QFont weights in FontPlatformData's ctor and follow it here
- if (FontPlatformData::toQFontWeight(description.weight()) > QFont::Normal)
- m_bold = true;
-
- const FontFamily* family = &description.family();
- while (family) {
- m_familyName.append(family->family());
- family = family->next();
- if (family)
- m_familyName.append(',');
- }
-
- computeHash();
- }
-
- FontPlatformDataCacheKey(const FontPlatformData& fontData)
- : m_familyName(static_cast<String>(fontData.family()))
- , m_size(fontData.pixelSize())
- , m_bold(fontData.bold())
- , m_italic(fontData.italic())
- , m_smallCaps(fontData.smallCaps())
- , m_hash(0)
- {
- computeHash();
- }
-
- FontPlatformDataCacheKey(HashTableDeletedValueType) : m_size(hashTableDeletedSize()) { }
- bool isHashTableDeletedValue() const { return m_size == hashTableDeletedSize(); }
-
- enum HashTableEmptyValueType { HashTableEmptyValue };
-
- FontPlatformDataCacheKey(HashTableEmptyValueType)
- : m_familyName()
- , m_size(0)
- , m_bold(false)
- , m_italic(false)
- , m_smallCaps(false)
- , m_hash(0)
- {
- }
-
- bool operator==(const FontPlatformDataCacheKey& other) const
- {
- if (m_hash != other.m_hash)
- return false;
-
- return equalIgnoringCase(m_familyName, other.m_familyName) && m_size == other.m_size &&
- m_bold == other.m_bold && m_italic == other.m_italic && m_smallCaps == other.m_smallCaps;
- }
-
- unsigned hash() const
- {
- return m_hash;
- }
-
- void computeHash()
- {
- unsigned hashCodes[] = {
- CaseFoldingHash::hash(m_familyName),
- m_size | static_cast<unsigned>(m_bold << sizeof(unsigned) * 8 - 1)
- | static_cast<unsigned>(m_italic) << sizeof(unsigned) *8 - 2
- | static_cast<unsigned>(m_smallCaps) << sizeof(unsigned) * 8 - 3
- };
- m_hash = StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
- }
-
-private:
- String m_familyName;
- int m_size;
- bool m_bold;
- bool m_italic;
- bool m_smallCaps;
- unsigned m_hash;
-
- static unsigned hashTableDeletedSize() { return 0xFFFFFFFFU; }
-};
-
-struct FontPlatformDataCacheKeyHash {
- static unsigned hash(const FontPlatformDataCacheKey& key)
- {
- return key.hash();
- }
-
- static bool equal(const FontPlatformDataCacheKey& a, const FontPlatformDataCacheKey& b)
- {
- return a == b;
- }
-
- static const bool safeToCompareToEmptyOrDeleted = true;
-};
-
-struct FontPlatformDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformDataCacheKey> {
- static const bool needsDestruction = true;
- static const FontPlatformDataCacheKey& emptyValue()
- {
- DEFINE_STATIC_LOCAL(FontPlatformDataCacheKey, key, (FontPlatformDataCacheKey::HashTableEmptyValue));
- return key;
- }
- static void constructDeletedValue(FontPlatformDataCacheKey& slot)
- {
- new (&slot) FontPlatformDataCacheKey(HashTableDeletedValue);
- }
- static bool isDeletedValue(const FontPlatformDataCacheKey& value)
- {
- return value.isHashTableDeletedValue();
- }
-};
-
-typedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontPlatformDataCache;
-
-// using Q_GLOBAL_STATIC leads to crash. TODO investigate the way to fix this.
-static FontPlatformDataCache* gFontPlatformDataCache = 0;
-
-FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& description, const AtomicString& family, bool checkingAlternateName)
-{
- if (!gFontPlatformDataCache)
- gFontPlatformDataCache = new FontPlatformDataCache;
-
- FontPlatformDataCacheKey key(description);
- FontPlatformData* platformData = gFontPlatformDataCache->get(key);
- if (!platformData) {
- platformData = new FontPlatformData(description);
- gFontPlatformDataCache->add(key, platformData);
- }
- return platformData;
-}
-
-typedef HashMap<FontPlatformDataCacheKey, std::pair<SimpleFontData*, unsigned>, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontDataCache;
-
-static FontDataCache* gFontDataCache = 0;
-
-static const int cMaxInactiveFontData = 40;
-static const int cTargetInactiveFontData = 32;
-
-static ListHashSet<const SimpleFontData*>* gInactiveFontDataSet = 0;
-
-SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* fontPlatformData)
-{
- if (!gFontDataCache) {
- gFontDataCache = new FontDataCache;
- gInactiveFontDataSet = new ListHashSet<const SimpleFontData*>;
- }
-
- FontPlatformDataCacheKey key(*fontPlatformData);
- FontDataCache::iterator it = gFontDataCache->find(key);
- if (it == gFontDataCache->end()) {
- SimpleFontData* fontData = new SimpleFontData(*fontPlatformData);
- gFontDataCache->add(key, std::pair<SimpleFontData*, unsigned>(fontData, 1));
- return fontData;
- }
- if (!it->second.second++) {
- ASSERT(gInactiveFontDataSet->contains(it->second.first));
- gInactiveFontDataSet->remove(it->second.first);
- }
- return it->second.first;
-}
-
-FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription&)
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font&, const UChar*, int)
{
return 0;
}
-void FontCache::releaseFontData(const WebCore::SimpleFontData* fontData)
-{
- ASSERT(gFontDataCache);
- ASSERT(!fontData->isCustomFont());
-
- FontPlatformDataCacheKey key(fontData->platformData());
- FontDataCache::iterator it = gFontDataCache->find(key);
- ASSERT(it != gFontDataCache->end());
- if (!--it->second.second) {
- gInactiveFontDataSet->add(it->second.first);
- if (gInactiveFontDataSet->size() > cMaxInactiveFontData)
- purgeInactiveFontData(gInactiveFontDataSet->size() - cTargetInactiveFontData);
- }
-}
-
-void FontCache::purgeInactiveFontData(int count)
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
{
- static bool isPurging; // Guard against reentry when e.g. a deleted FontData releases its small caps FontData.
- if (isPurging)
- return;
-
- isPurging = true;
-
- ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontDataSet->begin();
- ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontDataSet->end();
- for (int i = 0; i < count && it != end; ++i, ++it) {
- FontPlatformDataCacheKey key = (*it)->platformData();
- pair<SimpleFontData*, unsigned> fontDataPair = gFontDataCache->take(key);
- ASSERT(fontDataPair.first != 0);
- ASSERT(!fontDataPair.second);
- delete fontDataPair.first;
-
- FontPlatformData* platformData = gFontPlatformDataCache->take(key);
- if (platformData)
- delete platformData;
- }
-
- if (it == end) {
- // Removed everything
- gInactiveFontDataSet->clear();
- } else {
- for (int i = 0; i < count; ++i)
- gInactiveFontDataSet->remove(gInactiveFontDataSet->begin());
- }
-
- isPurging = false;
+ return 0;
}
-void FontCache::addClient(FontSelector*)
+FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
{
+ const AtomicString fallbackFamily = QFont(fontDescription.family().family()).lastResortFont();
+ return new FontPlatformData(fontDescription, fallbackFamily);
}
-void FontCache::removeClient(FontSelector*)
+void FontCache::getTraitsInFamily(const AtomicString&, Vector<unsigned>&)
{
}
-void FontCache::invalidate()
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
{
- if (!gFontPlatformDataCache || !gFontDataCache)
- return;
-
- purgeInactiveFontData();
+ return new FontPlatformData(fontDescription, familyName);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp b/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
index a19464e..6e9d053 100644
--- a/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
@@ -43,7 +43,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
font.setWeight(QFont::Bold);
font.setItalic(italic);
- return FontPlatformData(font, bold);
+ return FontPlatformData(font);
}
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
diff --git a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
deleted file mode 100644
index c29fd56..0000000
--- a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- 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 "FontCache.h"
-#include "SegmentedFontData.h"
-
-#include <QDebug>
-
-namespace WebCore {
-
-FontFallbackList::FontFallbackList()
- : m_pageZero(0)
- , m_cachedPrimarySimpleFontData(0)
- , m_fontSelector(0)
- , m_familyIndex(0)
- , m_pitch(UnknownPitch)
- , m_loadingCustomFonts(false)
- , m_generation(0)
-{
-}
-
-void FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector> fontSelector)
-{
- releaseFontData();
- m_fontList.clear();
- m_pageZero = 0;
- m_pages.clear();
- m_cachedPrimarySimpleFontData = 0;
- m_familyIndex = 0;
- m_pitch = UnknownPitch;
- m_loadingCustomFonts = false;
- m_fontSelector = fontSelector;
- m_generation = 0;
-}
-
-void FontFallbackList::releaseFontData()
-{
- unsigned numFonts = m_fontList.size();
- for (unsigned i = 0; i < numFonts; ++i) {
- if (m_fontList[i].second)
- delete m_fontList[i].first;
- else {
- ASSERT(!m_fontList[i].first->isSegmented());
- fontCache()->releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].first));
- }
- }
-}
-
-void FontFallbackList::determinePitch(const WebCore::Font* font) const
-{
- const FontData* fontData = primaryFontData(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;
-
- // Search for the WebCore font that is already in the list
- for (int i = m_fontList.size() - 1; i >= 0; --i) {
- pair<const FontData*, bool> item = m_fontList[i];
- // item.second means that the item was created locally or not
- if (!item.second)
- return item.first;
- }
-
- // 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;
- if (!data->isCustomFont()) {
- // Custom fonts can be freed anytime so we must not hold them
- m_fontList.append(pair<const FontData*, bool>(data, false));
- }
- return data;
- }
- }
- family = family->next();
- }
-
- if (m_fontList.size())
- return m_fontList[0].first;
-
- const FontData* result = new SimpleFontData(FontPlatformData(description, _font->wordSpacing(), _font->letterSpacing()), true);
- m_fontList.append(pair<const FontData*, bool>(result, true));
- return result;
-}
-
-const FontData* FontFallbackList::fontDataForCharacters(const WebCore::Font* font, const UChar*, int) const
-{
- return primaryFontData(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 92219fd..4a3f8bc 100644
--- a/WebCore/platform/graphics/qt/FontPlatformData.h
+++ b/WebCore/platform/graphics/qt/FontPlatformData.h
@@ -26,20 +26,62 @@
#include "FontDescription.h"
#include <QFont>
+#include <QHash>
namespace WebCore {
class String;
+class FontPlatformDataPrivate {
+public:
+ FontPlatformDataPrivate()
+ : refCount(1)
+ , size(font.pointSizeF())
+ , bold(font.bold())
+ , oblique(false)
+ {}
+ FontPlatformDataPrivate(const float size, const bool bold, const bool oblique)
+ : refCount(1)
+ , size(size)
+ , bold(bold)
+ , oblique(oblique)
+ {}
+ FontPlatformDataPrivate(const QFont& font)
+ : refCount(1)
+ , font(font)
+ , size(font.pointSizeF())
+ , bold(font.bold())
+ , oblique(false)
+ {}
+ unsigned refCount;
+ QFont font;
+ float size;
+ bool bold : 1;
+ bool oblique : 1;
+};
+
+
-class FontPlatformData
-{
+class FontPlatformData : public FastAllocBase {
public:
-#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);
+ FontPlatformData(const FontPlatformData &);
+ FontPlatformData(const FontDescription&, const AtomicString& familyName, int wordSpacing = 0, int letterSpacing = 0);
+ FontPlatformData(const QFont& font)
+ : m_data(new FontPlatformDataPrivate(font))
+ {}
+ FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_data(reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ {}
+
+ ~FontPlatformData();
+
+ FontPlatformData& operator=(const FontPlatformData&);
+ bool operator==(const FontPlatformData&) const;
+
+ bool isHashTableDeletedValue() const
+ {
+ return m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1);
+ }
static inline QFont::Weight toQFontWeight(FontWeight fontWeight)
{
@@ -62,22 +104,62 @@ public:
}
}
- QFont font() const { return m_font; }
- float size() const { return m_size; }
- QString family() const { return m_font.family(); }
- bool bold() const { return m_bold; }
- bool italic() const { return m_font.italic(); }
- bool smallCaps() const { return m_font.capitalization() == QFont::SmallCaps; }
- int pixelSize() const { return m_font.pixelSize(); }
+ QFont font() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font;
+ return QFont();
+ }
+ float size() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->size;
+ return 0.0f;
+ }
+ QString family() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font.family();
+ return QString();
+ }
+ bool bold() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->bold;
+ return false;
+ }
+ bool italic() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font.italic();
+ return false;
+ }
+ bool smallCaps() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font.capitalization() == QFont::SmallCaps;
+ return false;
+ }
+ int pixelSize() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font.pixelSize();
+ return 0;
+ }
+ unsigned hash() const;
#ifndef NDEBUG
String description() const;
#endif
-
- float m_size;
- bool m_bold;
- bool m_oblique;
- QFont m_font;
+private:
+ FontPlatformDataPrivate* m_data;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
index 7709be6..2cc2fc6 100644
--- a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
+++ b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
@@ -26,56 +26,104 @@
namespace WebCore {
-FontPlatformData::FontPlatformData(const FontDescription& description, int wordSpacing, int letterSpacing)
- : m_size(0.0f)
- , m_bold(false)
- , m_oblique(false)
+static inline bool isEmtpyValue(const float size, const bool bold, const bool oblique)
{
- QString familyName;
+ // this is the empty value by definition of the trait FontDataCacheKeyTraits
+ return !bold && !oblique && size == 0.f;
+}
+
+FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
+{
+ if (isEmtpyValue(size, bold, oblique))
+ m_data = 0;
+ else
+ m_data = new FontPlatformDataPrivate(size, bold, oblique);
+}
+
+FontPlatformData::FontPlatformData(const FontPlatformData &other) : m_data(other.m_data)
+{
+ if (m_data && m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ ++m_data->refCount;
+}
+
+FontPlatformData::FontPlatformData(const FontDescription& description, const AtomicString& familyName, int wordSpacing, int letterSpacing)
+ : m_data(new FontPlatformDataPrivate())
+{
+ QString familyNames(familyName);
+ if (!familyName.isEmpty())
+ familyNames += QLatin1Char(',');
+
const FontFamily* family = &description.family();
while (family) {
- familyName += family->family();
+ familyNames += family->family();
family = family->next();
if (family)
- familyName += QLatin1Char(',');
+ familyNames += QLatin1Char(',');
}
+ QFont& font = m_data->font;
+ font.setFamily(familyName);
+ font.setPixelSize(qRound(description.computedSize()));
+ font.setItalic(description.italic());
+ font.setWeight(toQFontWeight(description.weight()));
+ font.setWordSpacing(wordSpacing);
+ font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
+ const bool smallCaps = description.smallCaps();
+ font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
+
+ m_data->bold = font.bold();
+ m_data->size = font.pointSizeF();
+}
- m_font.setFamily(familyName);
- m_font.setPixelSize(qRound(description.computedSize()));
- m_font.setItalic(description.italic());
-
- m_font.setWeight(toQFontWeight(description.weight()));
- m_bold = m_font.bold();
-
- 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()
+{
+ if (!m_data || m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ return;
+ --m_data->refCount;
+ if (!m_data->refCount)
+ delete m_data;
}
-FontPlatformData::FontPlatformData(const QFont& font, bool bold)
- : m_size(font.pointSize())
- , m_bold(bold)
- , m_oblique(false)
- , m_font(font)
+FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
{
+ if (m_data == other.m_data)
+ return *this;
+ if (m_data && m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1)) {
+ --m_data->refCount;
+ if (!m_data->refCount)
+ delete m_data;
+ }
+ m_data = other.m_data;
+ if (m_data && m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ ++m_data->refCount;
+ return *this;
}
-#if ENABLE(SVG_FONTS)
-FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
- : m_size(size)
- , m_bold(bold)
- , m_oblique(oblique)
+bool FontPlatformData::operator==(const FontPlatformData& other) const
{
+ if (m_data == other.m_data)
+ return true;
+
+ if (!m_data || !other.m_data
+ || m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1) || other.m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ return false;
+
+ const bool equals = (m_data->size == other.m_data->size
+ && m_data->bold == other.m_data->bold
+ && m_data->oblique == other.m_data->oblique
+ && m_data->font == other.m_data->font);
+ return equals;
}
-#endif
-FontPlatformData::FontPlatformData()
- : m_size(0.0f)
- , m_bold(false)
- , m_oblique(false)
+unsigned FontPlatformData::hash() const
{
+ if (!m_data)
+ return 0;
+ if (m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ return 1;
+ return qHash(m_data->font.toString())
+ ^ qHash(*reinterpret_cast<quint32*>(&m_data->size))
+ ^ qHash(m_data->bold)
+ ^ qHash(m_data->oblique);
}
#ifndef NDEBUG
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index e8eb923..1e44626 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -42,7 +42,6 @@
#include <limits.h>
-#if QT_VERSION >= 0x040400
namespace WebCore {
static const QString qstring(const TextRun& run)
@@ -197,7 +196,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
return w + run.padding();
}
-int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const
+int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool) const
{
const QString string = fixSpacing(qstring(run));
QTextLayout layout(string, font());
@@ -229,5 +228,3 @@ QFont Font::font() const
}
-#endif
-
diff --git a/WebCore/platform/graphics/qt/FontQt43.cpp b/WebCore/platform/graphics/qt/FontQt43.cpp
deleted file mode 100644
index 45bf05d..0000000
--- a/WebCore/platform/graphics/qt/FontQt43.cpp
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- 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/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index e259a4e..a095476 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -34,29 +34,29 @@
*/
#include "config.h"
+#include "GraphicsContext.h"
#ifdef Q_WS_WIN
#include <windows.h>
#endif
-#include "TransformationMatrix.h"
#include "Color.h"
#include "FloatConversion.h"
#include "Font.h"
-#include "GraphicsContext.h"
#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
+#include "NotImplemented.h"
#include "Path.h"
#include "Pattern.h"
#include "Pen.h"
-#include "NotImplemented.h"
+#include "TransformationMatrix.h"
#include <QBrush>
#include <QDebug>
#include <QGradient>
-#include <QPainter>
#include <QPaintDevice>
#include <QPaintEngine>
+#include <QPainter>
#include <QPainterPath>
#include <QPixmap>
#include <QPolygonF>
@@ -72,35 +72,35 @@ namespace WebCore {
static inline QPainter::CompositionMode toQtCompositionMode(CompositeOperator op)
{
switch (op) {
- case CompositeClear:
- return QPainter::CompositionMode_Clear;
- case CompositeCopy:
- return QPainter::CompositionMode_Source;
- case CompositeSourceOver:
- return QPainter::CompositionMode_SourceOver;
- case CompositeSourceIn:
- return QPainter::CompositionMode_SourceIn;
- case CompositeSourceOut:
- return QPainter::CompositionMode_SourceOut;
- case CompositeSourceAtop:
- return QPainter::CompositionMode_SourceAtop;
- case CompositeDestinationOver:
- return QPainter::CompositionMode_DestinationOver;
- case CompositeDestinationIn:
- return QPainter::CompositionMode_DestinationIn;
- case CompositeDestinationOut:
- return QPainter::CompositionMode_DestinationOut;
- case CompositeDestinationAtop:
- return QPainter::CompositionMode_DestinationAtop;
- case CompositeXOR:
- return QPainter::CompositionMode_Xor;
- case CompositePlusDarker:
- // there is no exact match, but this is the closest
- return QPainter::CompositionMode_Darken;
- case CompositeHighlight:
- return QPainter::CompositionMode_SourceOver;
- case CompositePlusLighter:
- return QPainter::CompositionMode_Plus;
+ case CompositeClear:
+ return QPainter::CompositionMode_Clear;
+ case CompositeCopy:
+ return QPainter::CompositionMode_Source;
+ case CompositeSourceOver:
+ return QPainter::CompositionMode_SourceOver;
+ case CompositeSourceIn:
+ return QPainter::CompositionMode_SourceIn;
+ case CompositeSourceOut:
+ return QPainter::CompositionMode_SourceOut;
+ case CompositeSourceAtop:
+ return QPainter::CompositionMode_SourceAtop;
+ case CompositeDestinationOver:
+ return QPainter::CompositionMode_DestinationOver;
+ case CompositeDestinationIn:
+ return QPainter::CompositionMode_DestinationIn;
+ case CompositeDestinationOut:
+ return QPainter::CompositionMode_DestinationOut;
+ case CompositeDestinationAtop:
+ return QPainter::CompositionMode_DestinationAtop;
+ case CompositeXOR:
+ return QPainter::CompositionMode_Xor;
+ case CompositePlusDarker:
+ // there is no exact match, but this is the closest
+ return QPainter::CompositionMode_Darken;
+ case CompositeHighlight:
+ return QPainter::CompositionMode_SourceOver;
+ case CompositePlusLighter:
+ return QPainter::CompositionMode_Plus;
}
return QPainter::CompositionMode_SourceOver;
@@ -109,12 +109,12 @@ static inline QPainter::CompositionMode toQtCompositionMode(CompositeOperator op
static inline Qt::PenCapStyle toQtLineCap(LineCap lc)
{
switch (lc) {
- case ButtCap:
- return Qt::FlatCap;
- case RoundCap:
- return Qt::RoundCap;
- case SquareCap:
- return Qt::SquareCap;
+ case ButtCap:
+ return Qt::FlatCap;
+ case RoundCap:
+ return Qt::RoundCap;
+ case SquareCap:
+ return Qt::SquareCap;
}
return Qt::FlatCap;
@@ -123,12 +123,12 @@ static inline Qt::PenCapStyle toQtLineCap(LineCap lc)
static inline Qt::PenJoinStyle toQtLineJoin(LineJoin lj)
{
switch (lj) {
- case MiterJoin:
- return Qt::SvgMiterJoin;
- case RoundJoin:
- return Qt::RoundJoin;
- case BevelJoin:
- return Qt::BevelJoin;
+ case MiterJoin:
+ return Qt::SvgMiterJoin;
+ case RoundJoin:
+ return Qt::RoundJoin;
+ case BevelJoin:
+ return Qt::BevelJoin;
}
return Qt::MiterJoin;
@@ -210,8 +210,8 @@ public:
return redirect;
return painter;
- } else
- return &layers.top()->painter;
+ }
+ return &layers.top()->painter;
}
bool antiAliasingForRectsAndLines;
@@ -256,8 +256,8 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
setPaintingDisabled(!context);
if (context) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), DeviceColorSpace);
+ setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
}
}
@@ -411,46 +411,25 @@ void GraphicsContext::drawRect(const IntRect& rect)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+ IntRect shadowRect = rect;
+ shadowRect.move(shadowSize.width(), shadowSize.height());
+ shadowRect.inflate(static_cast<int>(p->pen().widthF()));
+ p->fillRect(shadowRect, QColor(shadowColor));
+ }
+
p->drawRect(rect);
p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
-// FIXME: Now that this is refactored, it should be shared by all contexts.
-static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth,
- const StrokeStyle& penStyle)
-{
- // 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.
- if (penStyle == DottedStroke || penStyle == DashedStroke) {
- if (p1.x() == p2.x()) {
- p1.setY(p1.y() + strokeWidth);
- p2.setY(p2.y() - strokeWidth);
- } else {
- p1.setX(p1.x() + strokeWidth);
- p2.setX(p2.x() - strokeWidth);
- }
- }
-
- if (((int) strokeWidth) % 2) {
- if (p1.x() == p2.x()) {
- // We're a vertical line. Adjust our x.
- p1.setX(p1.x() + 0.5);
- p2.setX(p2.x() + 0.5);
- } else {
- // We're a horizontal line. Adjust our y.
- p1.setY(p1.y() + 0.5);
- p2.setY(p2.y() + 0.5);
- }
- }
-}
-
// This is only used to draw borders.
void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
{
@@ -468,7 +447,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
FloatPoint p2 = point2;
bool isVerticalLine = (p1.x() == p2.x());
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
adjustLineToPixelBoundaries(p1, p2, width, style);
@@ -479,22 +458,22 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (textDrawingMode() == cTextFill && getShadow(shadowSize, shadowBlur, shadowColor)) {
p->save();
p->translate(shadowSize.width(), shadowSize.height());
- p->setPen(QColor(shadowColor));
+ p->setPen(shadowColor);
p->drawLine(p1, p2);
p->restore();
}
int patWidth = 0;
switch (style) {
- case NoStroke:
- case SolidStroke:
- break;
- case DottedStroke:
- patWidth = (int)width;
- break;
- case DashedStroke:
- patWidth = 3 * (int)width;
- break;
+ case NoStroke:
+ case SolidStroke:
+ break;
+ case DottedStroke:
+ patWidth = static_cast<int>(width);
+ break;
+ case DashedStroke:
+ patWidth = 3 * static_cast<int>(width);
+ break;
}
if (patWidth) {
@@ -523,7 +502,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth == 1)
patternOffset = 1.0f;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -571,11 +550,25 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f || !strokeColor().alpha())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, true);
- p->drawArc(rect, startAngle * 16, angleSpan * 16);
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ startAngle *= 16;
+ angleSpan *= 16;
+ if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+ p->save();
+ p->translate(shadowSize.width(), shadowSize.height());
+ QPen pen(p->pen());
+ pen.setColor(shadowColor);
+ p->setPen(pen);
+ p->drawArc(rect, startAngle, angleSpan);
+ p->restore();
+ }
+ p->drawArc(rect, startAngle, angleSpan);
p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
@@ -593,9 +586,25 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
for (size_t i = 0; i < npoints; i++)
polygon[i] = points[i];
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
p->save();
p->setRenderHint(QPainter::Antialiasing, shouldAntialias);
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+ p->save();
+ p->translate(shadowSize.width(), shadowSize.height());
+ if (p->brush().style() != Qt::NoBrush)
+ p->setBrush(QBrush(shadowColor));
+ QPen pen(p->pen());
+ if (pen.style() != Qt::NoPen) {
+ pen.setColor(shadowColor);
+ p->setPen(pen);
+ }
+ p->drawConvexPolygon(polygon);
+ p->restore();
+ }
p->drawConvexPolygon(polygon);
p->restore();
}
@@ -605,34 +614,44 @@ QPen GraphicsContext::pen()
if (paintingDisabled())
return QPen();
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
return p->pen();
}
+static void inline drawFilledShadowPath(GraphicsContext* context, QPainter* p, const QPainterPath *path)
+{
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (context->getShadow(shadowSize, shadowBlur, shadowColor)) {
+ p->translate(shadowSize.width(), shadowSize.height());
+ p->fillPath(*path, QBrush(shadowColor));
+ p->translate(-shadowSize.width(), -shadowSize.height());
+ }
+}
+
void GraphicsContext::fillPath()
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPainterPath path = m_data->currentPath;
path.setFillRule(toQtFillRule(fillRule()));
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- if (fillColor().alpha())
- p->fillPath(path, p->brush());
- break;
- case PatternColorSpace: {
- TransformationMatrix affine;
- p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
- break;
- }
- case GradientColorSpace:
- QBrush brush(*m_common->state.fillGradient->platformGradient());
- brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
- p->fillPath(path, brush);
- break;
+ if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) {
+ drawFilledShadowPath(this, p, &path);
+ if (m_common->state.fillPattern) {
+ TransformationMatrix affine;
+ p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
+ } else if (m_common->state.fillGradient) {
+ QBrush brush(*m_common->state.fillGradient->platformGradient());
+ brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
+ p->fillPath(path, brush);
+ } else {
+ if (fillColor().alpha())
+ p->fillPath(path, p->brush());
+ }
}
m_data->currentPath = QPainterPath();
}
@@ -642,77 +661,97 @@ void GraphicsContext::strokePath()
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
- QPen pen = p->pen();
+ QPainter* p = m_data->p();
+ QPen pen(p->pen());
QPainterPath path = m_data->currentPath;
path.setFillRule(toQtFillRule(fillRule()));
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- if (strokeColor().alpha())
+ if (m_common->state.strokePattern || m_common->state.strokeGradient || strokeColor().alpha()) {
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+ QTransform t(p->worldTransform());
+ p->translate(shadowSize.width(), shadowSize.height());
+ QPen shadowPen(pen);
+ shadowPen.setColor(shadowColor);
+ p->strokePath(path, shadowPen);
+ p->setWorldTransform(t);
+ }
+ if (m_common->state.strokePattern) {
+ TransformationMatrix affine;
+ pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine)));
+ p->setPen(pen);
p->strokePath(path, pen);
- break;
- case PatternColorSpace: {
- TransformationMatrix affine;
- pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine)));
- p->setPen(pen);
- p->strokePath(path, pen);
- break;
- }
- case GradientColorSpace: {
- QBrush brush(*m_common->state.strokeGradient->platformGradient());
- brush.setTransform(m_common->state.strokeGradient->gradientSpaceTransform());
- pen.setBrush(brush);
- p->setPen(pen);
- p->strokePath(path, pen);
- break;
- }
+ } else if (m_common->state.strokeGradient) {
+ QBrush brush(*m_common->state.strokeGradient->platformGradient());
+ brush.setTransform(m_common->state.strokeGradient->gradientSpaceTransform());
+ pen.setBrush(brush);
+ p->setPen(pen);
+ p->strokePath(path, pen);
+ } else {
+ if (strokeColor().alpha())
+ p->strokePath(path, pen);
+ }
}
m_data->currentPath = QPainterPath();
}
+static inline void drawBorderlessRectShadow(GraphicsContext* context, QPainter* p, const FloatRect& rect)
+{
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (context->getShadow(shadowSize, shadowBlur, shadowColor)) {
+ FloatRect shadowRect(rect);
+ shadowRect.move(shadowSize.width(), shadowSize.height());
+ p->fillRect(shadowRect, QColor(shadowColor));
+ }
+}
+
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- if (fillColor().alpha())
- p->fillRect(rect, p->brush());
- break;
- case PatternColorSpace: {
- TransformationMatrix affine;
- p->fillRect(rect, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
- break;
- }
- case GradientColorSpace:
- QBrush brush(*m_common->state.fillGradient->platformGradient());
- brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
- p->fillRect(rect, brush);
- break;
+ if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) {
+ drawBorderlessRectShadow(this, p, rect);
+ if (m_common->state.fillPattern) {
+ TransformationMatrix affine;
+ p->fillRect(rect, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
+ } else if (m_common->state.fillGradient) {
+ QBrush brush(*m_common->state.fillGradient->platformGradient());
+ brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
+ p->fillRect(rect, brush);
+ } else {
+ if (fillColor().alpha())
+ p->fillRect(rect, p->brush());
+ }
}
- m_data->currentPath = QPainterPath();
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& c, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
- m_data->solidColor.setColor(QColor(c));
- m_data->p()->fillRect(rect, m_data->solidColor);
+ m_data->solidColor.setColor(c);
+ QPainter* p = m_data->p();
+ drawBorderlessRectShadow(this, p, rect);
+ p->fillRect(rect, m_data->solidColor);
}
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled() || !color.alpha())
return;
Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight);
- m_data->p()->fillPath(*path.platformPath(), QColor(color));
+ QPainter* p = m_data->p();
+ drawFilledShadowPath(this, p, path.platformPath());
+ p->fillPath(*path.platformPath(), QColor(color));
}
void GraphicsContext::beginPath()
@@ -750,7 +789,7 @@ void GraphicsContext::clipPath(WindRule clipRule)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPainterPath newPath = m_data->currentPath;
newPath.setFillRule(clipRule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
p->setClipPath(newPath);
@@ -769,10 +808,10 @@ void GraphicsContext::drawFocusRing(const Color& color)
const Vector<IntRect>& rects = focusRingRects();
unsigned rectCount = rects.size();
- if (rects.size() == 0)
+ if (!rects.size())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
@@ -793,7 +832,7 @@ void GraphicsContext::drawFocusRing(const Color& color)
QPainterPath newPath = stroker.createStroke(path);
p->strokePath(newPath, nPen);
#else
- for (int i = 0; i < rectCount; ++i)
+ for (unsigned i = 0; i < rectCount; ++i)
p->drawRect(QRectF(rects[i]));
#endif
p->setPen(oldPen);
@@ -802,7 +841,7 @@ void GraphicsContext::drawFocusRing(const Color& color)
p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
-void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
+void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool)
{
if (paintingDisabled())
return;
@@ -811,8 +850,7 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr
drawLine(origin, endPoint);
}
-void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&,
- int width, bool grammar)
+void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int, bool)
{
if (paintingDisabled())
return;
@@ -829,10 +867,16 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
return FloatRect(QRectF(result));
}
-void GraphicsContext::setPlatformShadow(const IntSize& pos, int blur, const Color &color)
+void GraphicsContext::setPlatformShadow(const IntSize& size, int, const Color&, ColorSpace)
{
// Qt doesn't support shadows natively, they are drawn manually in the draw*
// functions
+
+ if (m_common->state.shadowsIgnoreTransforms) {
+ // Meaning that this graphics context is associated with a CanvasRenderingContext
+ // We flip the height since CG and HTML5 Canvas have opposite Y axis
+ m_common->state.shadowSize = IntSize(size.width(), -size.height());
+ }
}
void GraphicsContext::clearPlatformShadow()
@@ -848,8 +892,8 @@ void GraphicsContext::beginTransparencyLayer(float opacity)
int x, y, w, h;
x = y = 0;
- QPainter *p = m_data->p();
- const QPaintDevice *device = p->device();
+ QPainter* p = m_data->p();
+ const QPaintDevice* device = p->device();
w = device->width();
h = device->height();
@@ -871,10 +915,10 @@ void GraphicsContext::endTransparencyLayer()
if (paintingDisabled())
return;
- TransparencyLayer *layer = m_data->layers.pop();
+ TransparencyLayer* layer = m_data->layers.pop();
layer->painter.end();
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
p->save();
p->resetTransform();
p->setOpacity(layer->opacity);
@@ -889,7 +933,7 @@ void GraphicsContext::clearRect(const FloatRect& rect)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPainter::CompositionMode currentCompositionMode = p->compositionMode();
if (p->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
p->setCompositionMode(QPainter::CompositionMode_Source);
@@ -916,7 +960,7 @@ void GraphicsContext::setLineCap(LineCap lc)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen nPen = p->pen();
nPen.setCapStyle(toQtLineCap(lc));
p->setPen(nPen);
@@ -948,7 +992,7 @@ void GraphicsContext::setLineJoin(LineJoin lj)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen nPen = p->pen();
nPen.setJoinStyle(toQtLineJoin(lj));
p->setPen(nPen);
@@ -959,7 +1003,7 @@ void GraphicsContext::setMiterLimit(float limit)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen nPen = p->pen();
nPen.setMiterLimit(limit);
p->setPen(nPen);
@@ -969,7 +1013,7 @@ void GraphicsContext::setAlpha(float opacity)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
p->setOpacity(opacity);
}
@@ -990,20 +1034,29 @@ void GraphicsContext::clip(const Path& path)
m_data->p()->setClipPath(*path.platformPath(), Qt::IntersectClip);
}
+void GraphicsContext::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
- QRectF clipBounds = p->clipPath().boundingRect();
+ QPainter* p = m_data->p();
QPainterPath clippedOut = *path.platformPath();
QPainterPath newClip;
newClip.setFillRule(Qt::OddEvenFill);
- newClip.addRect(clipBounds);
- newClip.addPath(clippedOut);
-
- p->setClipPath(newClip, Qt::IntersectClip);
+ if (p->hasClipping()) {
+ newClip.addRect(p->clipPath().boundingRect());
+ newClip.addPath(clippedOut);
+ p->setClipPath(newClip, Qt::IntersectClip);
+ } else {
+ newClip.addRect(p->window());
+ newClip.addPath(clippedOut & newClip);
+ p->setClipPath(newClip);
+ }
}
void GraphicsContext::translate(float x, float y)
@@ -1061,14 +1114,21 @@ void GraphicsContext::clipOut(const IntRect& rect)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
- QRectF clipBounds = p->clipPath().boundingRect();
+ QPainter* p = m_data->p();
QPainterPath newClip;
newClip.setFillRule(Qt::OddEvenFill);
- newClip.addRect(clipBounds);
- newClip.addRect(QRect(rect));
-
- p->setClipPath(newClip, Qt::IntersectClip);
+ if (p->hasClipping()) {
+ newClip.addRect(p->clipPath().boundingRect());
+ newClip.addRect(QRect(rect));
+ p->setClipPath(newClip, Qt::IntersectClip);
+ } else {
+ QRect clipOutRect(rect);
+ QRect window(p->window());
+ clipOutRect &= window;
+ newClip.addRect(window);
+ newClip.addRect(clipOutRect);
+ p->setClipPath(newClip);
+ }
}
void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
@@ -1076,14 +1136,21 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
- QRectF clipBounds = p->clipPath().boundingRect();
+ QPainter* p = m_data->p();
QPainterPath newClip;
newClip.setFillRule(Qt::OddEvenFill);
- newClip.addRect(clipBounds);
- newClip.addEllipse(QRect(rect));
-
- p->setClipPath(newClip, Qt::IntersectClip);
+ if (p->hasClipping()) {
+ newClip.addRect(p->clipPath().boundingRect());
+ newClip.addEllipse(QRect(rect));
+ p->setClipPath(newClip, Qt::IntersectClip);
+ } else {
+ QRect clipOutRect(rect);
+ QRect window(p->window());
+ clipOutRect &= window;
+ newClip.addRect(window);
+ newClip.addEllipse(clipOutRect);
+ p->setClipPath(newClip);
+ }
}
void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
@@ -1109,7 +1176,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
path.setFillRule(Qt::OddEvenFill);
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, true);
@@ -1134,16 +1201,16 @@ void GraphicsContext::concatCTM(const TransformationMatrix& transform)
}
}
-void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
+void GraphicsContext::setURLForRect(const KURL&, const IntRect&)
{
notImplemented();
}
-void GraphicsContext::setPlatformStrokeColor(const Color& color)
+void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen newPen(p->pen());
newPen.setColor(color);
p->setPen(newPen);
@@ -1153,7 +1220,7 @@ void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen newPen(p->pen());
newPen.setStyle(toQPenStyle(strokeStyle));
p->setPen(newPen);
@@ -1163,13 +1230,13 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen newPen(p->pen());
newPen.setWidthF(thickness);
p->setPen(newPen);
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -1184,7 +1251,6 @@ void GraphicsContext::setPlatformShouldAntialias(bool enable)
}
#ifdef Q_WS_WIN
-#include <windows.h>
HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
diff --git a/WebCore/platform/graphics/qt/IconQt.cpp b/WebCore/platform/graphics/qt/IconQt.cpp
index 34c3c47..a9870fc 100644
--- a/WebCore/platform/graphics/qt/IconQt.cpp
+++ b/WebCore/platform/graphics/qt/IconQt.cpp
@@ -40,15 +40,17 @@ Icon::~Icon()
{
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
-{
- RefPtr<Icon> i = adoptRef(new Icon);
- i->m_icon = QIcon(filename);
- return i.release();
-}
-
PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
+ if (filenames.isEmpty())
+ return 0;
+
+ if (filenames.size() == 1) {
+ RefPtr<Icon> i = adoptRef(new Icon);
+ i->m_icon = QIcon(filenames[0]);
+ return i.release();
+ }
+
//FIXME: Implement this
return 0;
}
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index 22a5a43..5255428 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -68,7 +68,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
}
-ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace, bool& success)
: m_data(size)
, m_size(size)
{
@@ -125,12 +125,13 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
m_data.m_painter->begin(&m_data.m_pixmap);
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+template <Multiply multiplied>
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size)
{
PassRefPtr<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())
+ if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
memset(data, 0, result->data()->length());
int originx = rect.x();
@@ -140,8 +141,8 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originx = 0;
}
int endx = rect.x() + rect.width();
- if (endx > m_size.width())
- endx = m_size.width();
+ if (endx > size.width())
+ endx = size.width();
int numColumns = endx - originx;
int originy = rect.y();
@@ -151,11 +152,16 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originy = 0;
}
int endy = rect.y() + rect.height();
- if (endy > m_size.height())
- endy = m_size.height();
+ if (endy > size.height())
+ endy = size.height();
int numRows = endy - originy;
- QImage image = m_data.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+ QImage image = imageData.m_pixmap.toImage();
+ if (multiplied == Unmultiplied)
+ image = image.convertToFormat(QImage::Format_ARGB32);
+ else
+ image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
ASSERT(!image.isNull());
unsigned destBytesPerRow = 4 * rect.width();
@@ -176,7 +182,18 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Unmultiplied>(rect, m_data, m_size);
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Premultiplied>(rect, m_data, m_size);
+}
+
+template <Multiply multiplied>
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -184,49 +201,65 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
int originx = sourceRect.x();
int destx = destPoint.x() + sourceRect.x();
ASSERT(destx >= 0);
- ASSERT(destx < m_size.width());
+ ASSERT(destx < size.width());
ASSERT(originx >= 0);
ASSERT(originx <= sourceRect.right());
int endx = destPoint.x() + sourceRect.right();
- ASSERT(endx <= m_size.width());
+ ASSERT(endx <= 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(desty < size.height());
ASSERT(originy >= 0);
ASSERT(originy <= sourceRect.bottom());
int endy = destPoint.y() + sourceRect.bottom();
- ASSERT(endy <= m_size.height());
+ ASSERT(endy <= size.height());
int numRows = endy - desty;
unsigned srcBytesPerRow = 4 * source->width();
- bool isPainting = m_data.m_painter->isActive();
+ bool isPainting = data.m_painter->isActive();
if (isPainting)
- m_data.m_painter->end();
+ data.m_painter->end();
- QImage image = m_data.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+ QImage image = data.m_pixmap.toImage();
+ if (multiplied == Unmultiplied)
+ image = image.convertToFormat(QImage::Format_ARGB32);
+ else
+ image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
for (int y = 0; y < numRows; ++y) {
quint32* scanLine = reinterpret_cast<quint32*>(image.scanLine(y + desty));
for (int x = 0; x < numColumns; x++) {
- int basex = x * 4;
- scanLine[x + destx] = reinterpret_cast<quint32*>(srcRows + basex)[0];
+ // ImageData stores the pixels in RGBA while QImage is ARGB
+ quint32 pixel = reinterpret_cast<quint32*>(srcRows + 4 * x)[0];
+ pixel = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
+ scanLine[x + destx] = pixel;
}
srcRows += srcBytesPerRow;
}
- m_data.m_pixmap = QPixmap::fromImage(image);
+ data.m_pixmap = QPixmap::fromImage(image);
if (isPainting)
- m_data.m_painter->begin(&m_data.m_pixmap);
+ data.m_painter->begin(&data.m_pixmap);
+}
+
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size);
}
// We get a mimeType here but QImageWriter does not support mimetypes but
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 7bbdcc0..b6823dd 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -35,303 +35,205 @@
#include <QtGui/QImageReader>
#include <qdebug.h>
-namespace {
- const QImage::Format DesiredFormat = QImage::Format_ARGB32;
- const bool debugImageDecoderQt = false;
-}
-
namespace WebCore {
-ImageDecoderQt::ImageData::ImageData(const QImage& image, ImageState imageState, int duration) :
- m_image(image), m_imageState(imageState), m_duration(duration)
-{
-}
-
-// Context, maintains IODevice on a data buffer.
-class ImageDecoderQt::ReadContext {
-public:
- enum LoadMode {
- // Load images incrementally. This is still experimental and
- // will cause the image plugins to report errors.
- // Also note that as of Qt 4.2.2, the JPEG loader does not return error codes
- // on "preliminary end of data".
- LoadIncrementally,
- // Load images only if all data have been received
- LoadComplete };
-
- ReadContext(const IncomingData & data, LoadMode loadMode, ImageList &target);
-
- enum ReadResult { ReadEOF, ReadFailed, ReadPartial, ReadComplete };
+ImageDecoder* ImageDecoder::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;
- // Append data and read out all images. Returns the result
- // of the last read operation, so, even if ReadPartial is returned,
- // a few images might have been read.
- ReadResult read(bool allDataReceived);
+ return new ImageDecoderQt;
+}
- QImageReader *reader() { return &m_reader; }
+ImageDecoderQt::ImageDecoderQt()
+ : m_buffer(0)
+ , m_reader(0)
+ , m_repetitionCount(cAnimationNone)
+{
+}
-private:
- enum IncrementalReadResult { IncrementalReadFailed, IncrementalReadPartial, IncrementalReadComplete };
- // Incrementally read an image
- IncrementalReadResult readImageLines(ImageData &);
+ImageDecoderQt::~ImageDecoderQt()
+{
+ delete m_reader;
+ delete m_buffer;
+}
- const LoadMode m_loadMode;
+void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived)
+{
+ if (m_failed)
+ return;
- QByteArray m_data;
- QBuffer m_buffer;
- QImageReader m_reader;
+ // No progressive loading possible
+ if (!allDataReceived)
+ return;
- ImageList &m_target;
+ // Cache our own new data.
+ ImageDecoder::setData(data, allDataReceived);
- // Detected data format of the stream
- enum QImage::Format m_dataFormat;
- QSize m_size;
+ // We expect to be only called once with allDataReceived
+ ASSERT(!m_buffer);
+ ASSERT(!m_reader);
-};
+ // Attempt to load the data
+ QByteArray imageData = QByteArray::fromRawData(m_data->data(), m_data->size());
+ m_buffer = new QBuffer;
+ m_buffer->setData(imageData);
+ m_buffer->open(QBuffer::ReadOnly);
+ m_reader = new QImageReader(m_buffer, m_format);
+}
-ImageDecoderQt::ReadContext::ReadContext(const IncomingData & data, LoadMode loadMode, ImageList &target)
- : m_loadMode(loadMode)
- , m_data(data.data(), data.size())
- , m_buffer(&m_data)
- , m_reader(&m_buffer)
- , m_target(target)
- , m_dataFormat(QImage::Format_Invalid)
+bool ImageDecoderQt::isSizeAvailable()
{
- m_buffer.open(QIODevice::ReadOnly);
-}
+ if (!ImageDecoder::isSizeAvailable() && m_reader)
+ internalDecodeSize();
+ return ImageDecoder::isSizeAvailable();
+}
-ImageDecoderQt::ReadContext::ReadResult
- ImageDecoderQt::ReadContext::read(bool allDataReceived)
+size_t ImageDecoderQt::frameCount()
{
- // Complete mode: Read only all all data received
- if (m_loadMode == LoadComplete && !allDataReceived)
- return ReadPartial;
-
- // Attempt to read out all images
- while (true) {
- if (m_target.empty() || m_target.back().m_imageState == ImageComplete) {
- // Start a new image.
- if (!m_reader.canRead())
- return ReadEOF;
-
- // Attempt to construct an empty image of the matching size and format
- // for efficient reading
- QImage newImage = m_dataFormat != QImage::Format_Invalid ?
- QImage(m_size, m_dataFormat) : QImage();
- m_target.push_back(ImageData(newImage));
- }
+ if (m_frameBufferCache.isEmpty() && m_reader) {
+ if (m_reader->supportsAnimation()) {
+ int imageCount = m_reader->imageCount();
- // read chunks
- switch (readImageLines(m_target.back())) {
- case IncrementalReadFailed:
- m_target.pop_back();
- return ReadFailed;
- case IncrementalReadPartial:
- return ReadPartial;
- case IncrementalReadComplete:
- m_target.back().m_imageState = ImageComplete;
- //store for next
- m_dataFormat = m_target.back().m_image.format();
- m_size = m_target.back().m_image.size();
- const bool supportsAnimation = m_reader.supportsAnimation();
-
- if (debugImageDecoderQt)
- qDebug() << "readImage(): #" << m_target.size() << " complete, " << m_size
- << " format " << m_dataFormat << " supportsAnimation=" << supportsAnimation;
- // No point in readinfg further
- if (!supportsAnimation)
- return ReadComplete;
-
- break;
+ // Fixup for Qt decoders... imageCount() is wrong
+ // and jumpToNextImage does not work either... so
+ // we will have to parse everything...
+ if (imageCount == 0)
+ forceLoadEverything();
+ else
+ m_frameBufferCache.resize(imageCount);
+ } else {
+ m_frameBufferCache.resize(1);
}
}
- return ReadComplete;
+
+ return m_frameBufferCache.size();
}
+int ImageDecoderQt::repetitionCount() const
+{
+ if (m_reader && m_reader->supportsAnimation())
+ m_repetitionCount = qMax(0, m_reader->loopCount());
+ return m_repetitionCount;
+}
-ImageDecoderQt::ReadContext::IncrementalReadResult
- ImageDecoderQt::ReadContext::readImageLines(ImageData &imageData)
+String ImageDecoderQt::filenameExtension() const
{
- // TODO: Implement incremental reading here,
- // set state to reflect complete header, etc.
- // For now, we read the whole image.
-
- const qint64 startPos = m_buffer.pos();
- // Oops, failed. Rewind.
- if (!m_reader.read(&imageData.m_image)) {
- m_buffer.seek(startPos);
- const bool gotHeader = imageData.m_image.size().width();
-
- if (debugImageDecoderQt)
- qDebug() << "readImageLines(): read() failed: " << m_reader.errorString()
- << " got header=" << gotHeader;
- // [Experimental] Did we manage to read the header?
- if (gotHeader) {
- imageData.m_imageState = ImageHeaderValid;
- return IncrementalReadPartial;
- }
- return IncrementalReadFailed;
- }
- imageData.m_duration = m_reader.nextImageDelay();
- return IncrementalReadComplete;
-}
+ return String(m_format.constData(), m_format.length());
+};
-ImageDecoderQt* ImageDecoderQt::create(const SharedBuffer& data)
+RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
{
- // We need at least 4 bytes to figure out what kind of image we're dealing with.
- if (data.size() < 4)
- return 0;
+ // In case the ImageDecoderQt got recreated we don't know
+ // yet how many images we are going to have and need to
+ // find that out now.
+ int count = m_frameBufferCache.size();
+ if (!m_failed && count == 0) {
+ internalDecodeSize();
+ count = frameCount();
+ }
- QByteArray bytes = QByteArray::fromRawData(data.data(), data.size());
- QBuffer buffer(&bytes);
- if (!buffer.open(QBuffer::ReadOnly))
+ if (index >= static_cast<size_t>(count))
return 0;
- QString imageFormat = QString::fromLatin1(QImageReader::imageFormat(&buffer).toLower());
- if (imageFormat.isEmpty())
- return 0; // Image format not supported
-
- return new ImageDecoderQt(imageFormat);
+ RGBA32Buffer& frame = m_frameBufferCache[index];
+ if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
+ internalReadImage(index);
+ return &frame;
}
-ImageDecoderQt::ImageDecoderQt(const QString &imageFormat)
- : m_hasAlphaChannel(false)
- , m_imageFormat(imageFormat)
+void ImageDecoderQt::clearFrameBufferCache(size_t /*index*/)
{
}
-ImageDecoderQt::~ImageDecoderQt()
+void ImageDecoderQt::internalDecodeSize()
{
-}
+ ASSERT(m_reader);
-bool ImageDecoderQt::hasFirstImageHeader() const
-{
- return !m_imageList.empty() && m_imageList[0].m_imageState >= ImageHeaderValid;
-}
+ // If we have a QSize() something failed
+ QSize size = m_reader->size();
+ if (size.isEmpty())
+ return failRead();
-void ImageDecoderQt::reset()
-{
- m_hasAlphaChannel = false;
- m_failed = false;
- m_imageList.clear();
- m_pixmapCache.clear();
- m_loopCount = cAnimationNone;
+ m_format = m_reader->format();
+ setSize(size.width(), size.height());
}
-void ImageDecoderQt::setData(const IncomingData &data, bool allDataReceived)
+void ImageDecoderQt::internalReadImage(size_t frameIndex)
{
- reset();
- ReadContext readContext(data, ReadContext::LoadComplete, m_imageList);
-
- if (debugImageDecoderQt)
- qDebug() << " setData " << data.size() << " image bytes, complete=" << allDataReceived;
-
- const ReadContext::ReadResult readResult = readContext.read(allDataReceived);
-
- if (hasFirstImageHeader())
- m_hasAlphaChannel = m_imageList[0].m_image.hasAlphaChannel();
-
- if (debugImageDecoderQt)
- qDebug() << " read returns " << readResult;
-
- switch (readResult) {
- case ReadContext::ReadFailed:
- m_failed = true;
- break;
- case ReadContext::ReadEOF:
- case ReadContext::ReadPartial:
- case ReadContext::ReadComplete:
- // Did we read anything - try to set the size.
- if (hasFirstImageHeader()) {
- QSize imgSize = m_imageList[0].m_image.size();
- setSize(imgSize.width(), imgSize.height());
-
- if (readContext.reader()->supportsAnimation()) {
- if (readContext.reader()->loopCount() != -1)
- m_loopCount = readContext.reader()->loopCount();
- else
- m_loopCount = 0; //loop forever
- }
- }
- break;
- }
-}
+ ASSERT(m_reader);
+ if (m_reader->supportsAnimation())
+ m_reader->jumpToImage(frameIndex);
+ else if (frameIndex != 0)
+ return failRead();
-bool ImageDecoderQt::isSizeAvailable()
-{
- if (debugImageDecoderQt)
- qDebug() << " ImageDecoderQt::isSizeAvailable() returns" << ImageDecoder::isSizeAvailable();
- return ImageDecoder::isSizeAvailable();
-}
+ internalHandleCurrentImage(frameIndex);
-size_t ImageDecoderQt::frameCount() const
-{
- if (debugImageDecoderQt)
- qDebug() << " ImageDecoderQt::frameCount() returns" << m_imageList.size();
- return m_imageList.size();
-}
+ // Attempt to return some memory
+ for (int i = 0; i < m_frameBufferCache.size(); ++i)
+ if (m_frameBufferCache[i].status() != RGBA32Buffer::FrameComplete)
+ return;
-int ImageDecoderQt::repetitionCount() const
-{
- if (debugImageDecoderQt)
- qDebug() << " ImageDecoderQt::repetitionCount() returns" << m_loopCount;
- return m_loopCount;
+ delete m_reader;
+ delete m_buffer;
+ m_buffer = 0;
+ m_reader = 0;
}
-bool ImageDecoderQt::supportsAlpha() const
+void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
{
- return m_hasAlphaChannel;
-}
+ // Now get the QImage from Qt and place it in the RGBA32Buffer
+ QImage img;
+ if (!m_reader->read(&img))
+ return failRead();
-int ImageDecoderQt::duration(size_t index) const
-{
- if (index >= m_imageList.size())
- return 0;
- return m_imageList[index].m_duration;
+ // now into the RGBA32Buffer - even if the image is not
+ QSize imageSize = img.size();
+ RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex];
+ buffer->setRect(m_reader->currentImageRect());
+ buffer->setStatus(RGBA32Buffer::FrameComplete);
+ buffer->setDuration(m_reader->nextImageDelay());
+ buffer->setDecodedImage(img);
}
-String ImageDecoderQt::filenameExtension() const
-{
- if (debugImageDecoderQt)
- qDebug() << " ImageDecoderQt::filenameExtension() returns" << m_imageFormat;
- return m_imageFormat;
-};
+// The QImageIOHandler is not able to tell us how many frames
+// we have and we need to parse every image. We do this by
+// increasing the m_frameBufferCache by one and try to parse
+// the image. We stop when QImage::read fails and then need
+// to resize the m_frameBufferCache to the final size and update
+// the m_failed. In case we failed to decode the first image
+// we want to keep m_failed set to true.
-RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
-{
- Q_ASSERT("use imageAtIndex instead");
- return 0;
-}
-
-QPixmap* ImageDecoderQt::imageAtIndex(size_t index) const
+// TODO: Do not increment the m_frameBufferCache.size() by one but more than one
+void ImageDecoderQt::forceLoadEverything()
{
- if (debugImageDecoderQt)
- qDebug() << "ImageDecoderQt::imageAtIndex(" << index << ')';
+ int imageCount = 0;
- if (index >= m_imageList.size())
- return 0;
-
- if (!m_pixmapCache.contains(index)) {
- m_pixmapCache.insert(index,
- QPixmap::fromImage(m_imageList[index].m_image));
+ do {
+ m_frameBufferCache.resize(++imageCount);
+ internalHandleCurrentImage(imageCount - 1);
+ } while(!m_failed);
- // store null image since the converted pixmap is already in pixmap cache
- Q_ASSERT(m_imageList[index].m_imageState == ImageComplete);
- m_imageList[index].m_image = QImage();
- }
- return &m_pixmapCache[index];
+ // If we failed decoding the first image we actually
+ // have no images and need to keep m_failed set to
+ // true otherwise we want to reset it and forget about
+ // the last attempt to decode a image.
+ m_frameBufferCache.resize(imageCount - 1);
+ m_failed = imageCount == 1;
}
-void ImageDecoderQt::clearFrame(size_t index)
+void ImageDecoderQt::failRead()
{
- if (m_imageList.size() < (int)index)
- m_imageList[index].m_image = QImage();
- m_pixmapCache.take(index);
+ setFailed();
+ delete m_reader;
+ delete m_buffer;
+ m_reader = 0;
+ m_buffer = 0;
}
-
}
// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
index fc52479..d11b938 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.h
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -28,10 +28,11 @@
#define ImageDecoderQt_h
#include "ImageDecoder.h"
-#include <QtGui/QImage>
+#include <QtGui/QImageReader>
#include <QtGui/QPixmap>
#include <QtCore/QList>
#include <QtCore/QHash>
+#include <QtCore/QBuffer>
namespace WebCore {
@@ -39,54 +40,35 @@ namespace WebCore {
class ImageDecoderQt : public ImageDecoder
{
public:
- static ImageDecoderQt* create(const SharedBuffer& data);
+ ImageDecoderQt();
~ImageDecoderQt();
- typedef Vector<char> IncomingData;
-
- virtual void setData(const IncomingData& data, bool allDataReceived);
+ virtual void setData(SharedBuffer* data, bool allDataReceived);
virtual bool isSizeAvailable();
- virtual size_t frameCount() const;
+ virtual size_t frameCount();
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);
+ virtual void clearFrameBufferCache(size_t clearBeforeFrame);
private:
- ImageDecoderQt(const QString &imageFormat);
ImageDecoderQt(const ImageDecoderQt&);
ImageDecoderQt &operator=(const ImageDecoderQt&);
- class ReadContext;
- void reset();
- bool hasFirstImageHeader() const;
-
- enum ImageState {
- // Started image reading
- ImagePartial,
- // Header (size / alpha) are known
- ImageHeaderValid,
- // Image is complete
- ImageComplete };
-
- struct ImageData {
- ImageData(const QImage& image, ImageState imageState = ImagePartial, int duration=0);
- QImage m_image;
- ImageState m_imageState;
- int m_duration;
- };
-
- bool m_hasAlphaChannel;
- typedef QList<ImageData> ImageList;
- mutable ImageList m_imageList;
- mutable QHash<int, QPixmap> m_pixmapCache;
- int m_loopCount;
- QString m_imageFormat;
+private:
+ void internalDecodeSize();
+ void internalReadImage(size_t);
+ void internalHandleCurrentImage(size_t);
+ void forceLoadEverything();
+ void failRead();
+
+private:
+ QByteArray m_format;
+ QBuffer* m_buffer;
+ QImageReader* m_reader;
+ mutable int m_repetitionCount;
};
diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp
index 5d40e26..9a82911 100644
--- a/WebCore/platform/graphics/qt/ImageQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageQt.cpp
@@ -44,9 +44,7 @@
#include <QPainter>
#include <QImage>
#include <QImageReader>
-#if QT_VERSION >= 0x040300
#include <QTransform>
-#endif
#include <QDebug>
@@ -64,6 +62,8 @@ static QPixmap loadResourcePixmap(const char *name)
pixmap = QWebSettings::webGraphic(QWebSettings::DefaultFrameIconGraphic);
else if (qstrcmp(name, "textAreaResizeCorner") == 0)
pixmap = QWebSettings::webGraphic(QWebSettings::TextAreaSizeGripCornerGraphic);
+ else if (qstrcmp(name, "deleteButton") == 0)
+ pixmap = QWebSettings::webGraphic(QWebSettings::DeleteButtonGraphic);
return pixmap;
}
@@ -76,6 +76,7 @@ bool FrameData::clear(bool clearMetadata)
m_haveMetadata = false;
if (m_frame) {
+ delete m_frame;
m_frame = 0;
return true;
}
@@ -93,7 +94,7 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name)
}
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect)
{
QPixmap* framePixmap = nativeImageForCurrentFrame();
if (!framePixmap) // If it's too early we won't have an image yet.
@@ -119,6 +120,38 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
imageObserver()->didDraw(this);
}
+BitmapImage::BitmapImage(QPixmap* pixmap, ImageObserver* observer)
+ : Image(observer)
+ , m_currentFrame(0)
+ , m_frames(0)
+ , m_frameTimer(0)
+ , m_repetitionCount(cAnimationNone)
+ , m_repetitionCountStatus(Unknown)
+ , m_repetitionsComplete(0)
+ , m_isSolidColor(false)
+ , m_checkedForSolidColor(false)
+ , m_animationFinished(true)
+ , m_allDataReceived(true)
+ , m_haveSize(true)
+ , m_sizeAvailable(true)
+ , m_decodedSize(0)
+ , m_haveFrameCount(true)
+ , m_frameCount(1)
+{
+ initPlatformData();
+
+ int width = pixmap->width();
+ int height = pixmap->height();
+ m_decodedSize = width * height * 4;
+ m_size = IntSize(width, height);
+
+ m_frames.grow(1);
+ m_frames[0].m_frame = pixmap;
+ m_frames[0].m_hasAlpha = pixmap->hasAlpha();
+ m_frames[0].m_haveMetadata = true;
+ checkForSolidColor();
+}
+
void BitmapImage::initPlatformData()
{
}
@@ -129,7 +162,7 @@ void BitmapImage::invalidatePlatformData()
// Drawing Routines
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
- const FloatRect& src, CompositeOperator op)
+ const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
startAnimation();
@@ -138,7 +171,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, dst, solidColor(), op);
+ fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
return;
}
@@ -180,6 +213,13 @@ void BitmapImage::checkForSolidColor()
m_solidColor = QColor::fromRgba(framePixmap->toImage().pixel(0, 0));
}
+#if PLATFORM(WIN_OS)
+PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap)
+{
+ return BitmapImage::create(new QPixmap(QPixmap::fromWinHBITMAP(hBitmap)));
+}
+#endif
+
}
diff --git a/WebCore/platform/graphics/qt/ImageSourceQt.cpp b/WebCore/platform/graphics/qt/ImageSourceQt.cpp
deleted file mode 100644
index 8ae449c..0000000
--- a/WebCore/platform/graphics/qt/ImageSourceQt.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- *
- * 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 "ImageSource.h"
-#include "ImageDecoderQt.h"
-#include "SharedBuffer.h"
-
-#include <QBuffer>
-#include <QImage>
-#include <QImageReader>
-
-namespace WebCore {
-
-ImageSource::ImageSource()
- : m_decoder(0)
-{
-}
-
-ImageSource::~ImageSource()
-{
- clear(true);
-}
-
-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 = ImageDecoderQt::create(*data);
-
- if (!m_decoder)
- return;
-
- 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)
- return false;
-
- return m_decoder->isSizeAvailable();
-}
-
-IntSize ImageSource::size() const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->size();
-}
-
-IntSize ImageSource::frameSizeAtIndex(size_t index) const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->frameSizeAtIndex(index);
-}
-
-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->frameCount();
-}
-
-NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
-{
- if (!m_decoder)
- return 0;
-
- return m_decoder->imageAtIndex(index);
-}
-
-float ImageSource::frameDurationAtIndex(size_t index)
-{
- if (!m_decoder)
- 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 = m_decoder->duration(index) / 1000.0f;
- return (duration < 0.051f) ? 0.100f : duration;
-}
-
-bool ImageSource::frameHasAlphaAtIndex(size_t index)
-{
- if (!m_decoder || !m_decoder->supportsAlpha())
- return false;
-
- const QPixmap* source = m_decoder->imageAtIndex(index);
- if (!source)
- return false;
-
- return source->hasAlphaChannel();
-}
-
-bool ImageSource::frameIsCompleteAtIndex(size_t index)
-{
- return (m_decoder && m_decoder->imageAtIndex(index));
-}
-
-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);
-}
-
-}
-
-// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
index 76b1494..f446755 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
@@ -27,6 +27,7 @@
#include "FrameView.h"
#include "GraphicsContext.h"
#include "NotImplemented.h"
+#include "TimeRanges.h"
#include "Widget.h"
#include <wtf/HashSet.h>
@@ -37,9 +38,9 @@
#include <QUrl>
#include <QEvent>
-#include <Phonon/AudioOutput>
-#include <Phonon/MediaObject>
-#include <Phonon/VideoWidget>
+#include <audiooutput.h>
+#include <mediaobject.h>
+#include <videowidget.h>
using namespace Phonon;
@@ -100,15 +101,15 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
foreach (QWidget* widget, qFindChildren<QWidget*>(m_videoWidget))
widget->installEventFilter(this);
- connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
- this, SLOT(stateChanged(Phonon::State, Phonon::State)));
+ connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
+ this, SLOT(stateChanged(Phonon::State,Phonon::State)));
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)));
connect(m_mediaObject, SIGNAL(bufferStatus(int)), this, SLOT(bufferStatus(int)));
connect(m_mediaObject, SIGNAL(finished()), this, SLOT(finished()));
- connect(m_mediaObject, SIGNAL(currentSourceChanged(const Phonon::MediaSource&)),
- this, SLOT(currentSourceChanged(const Phonon::MediaSource&)));
+ connect(m_mediaObject, SIGNAL(currentSourceChanged(Phonon::MediaSource)),
+ this, SLOT(currentSourceChanged(Phonon::MediaSource)));
connect(m_mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
connect(m_mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64)));
}
@@ -146,7 +147,7 @@ void MediaPlayerPrivate::getSupportedTypes(HashSet<String>&)
notImplemented();
}
-MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
+MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String&, const String&)
{
// FIXME: do the real thing
notImplemented();
@@ -160,6 +161,14 @@ bool MediaPlayerPrivate::hasVideo() const
return hasVideo;
}
+bool MediaPlayerPrivate::hasAudio() const
+{
+ // FIXME: Phonon::MediaObject does not have such a hasAudio() function
+ bool hasAudio = true;
+ LOG(Media, "MediaPlayerPrivatePhonon::hasAudio() -> %s", hasAudio ? "true" : "false");
+ return hasAudio;
+}
+
void MediaPlayerPrivate::load(const String& url)
{
LOG(Media, "MediaPlayerPrivatePhonon::load(\"%s\")", url.utf8().data());
@@ -247,15 +256,15 @@ float MediaPlayerPrivate::currentTime() const
return currentTime;
}
-void MediaPlayerPrivate::setEndTime(float endTime)
+void MediaPlayerPrivate::setEndTime(float)
{
notImplemented();
}
-float MediaPlayerPrivate::maxTimeBuffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
notImplemented();
- return 0.0f;
+ return TimeRanges::create();
}
float MediaPlayerPrivate::maxTimeSeekable() const
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
index 9572d61..e1193b6 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
@@ -80,6 +80,7 @@ namespace WebCore {
IntSize naturalSize() const;
bool hasVideo() const;
+ bool hasAudio() const;
void load(const String &url);
void cancelLoad();
@@ -104,7 +105,7 @@ namespace WebCore {
MediaPlayer::NetworkState networkState() const;
MediaPlayer::ReadyState readyState() const;
- float maxTimeBuffered() const;
+ PassRefPtr<TimeRanges> buffered() const;
float maxTimeSeekable() const;
unsigned bytesLoaded() const;
bool totalBytesKnown() const;
diff --git a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
index f823f84..f093d7d 100644
--- a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
+++ b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
@@ -33,7 +33,7 @@ void SimpleFontData::determinePitch()
m_treatAsFixedPitch = m_platformData.font().fixedPitch();
}
-bool SimpleFontData::containsCharacters(const UChar*, int length) const
+bool SimpleFontData::containsCharacters(const UChar*, int) const
{
return true;
}
diff --git a/WebCore/platform/graphics/qt/StillImageQt.cpp b/WebCore/platform/graphics/qt/StillImageQt.cpp
index 95b3bc8..1db04a7 100644
--- a/WebCore/platform/graphics/qt/StillImageQt.cpp
+++ b/WebCore/platform/graphics/qt/StillImageQt.cpp
@@ -50,7 +50,7 @@ NativeImagePtr StillImage::nativeImageForCurrentFrame()
}
void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
- const FloatRect& src, CompositeOperator op)
+ const FloatRect& src, ColorSpace, CompositeOperator op)
{
if (m_pixmap.isNull())
return;
diff --git a/WebCore/platform/graphics/qt/StillImageQt.h b/WebCore/platform/graphics/qt/StillImageQt.h
index 2b2c1f7..7be9136 100644
--- a/WebCore/platform/graphics/qt/StillImageQt.h
+++ b/WebCore/platform/graphics/qt/StillImageQt.h
@@ -41,12 +41,12 @@ 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 destroyAll = true) { }
+ virtual void destroyDecodedData(bool destroyAll = true) { Q_UNUSED(destroyAll); }
virtual unsigned decodedSize() const { return 0; }
virtual IntSize size() const;
virtual NativeImagePtr nativeImageForCurrentFrame();
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
private:
StillImage(const QPixmap& pixmap);
diff --git a/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h b/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
index 5d85652..9fb6a8b 100644
--- a/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
+++ b/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
@@ -72,7 +72,7 @@ public:
}
protected:
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
private:
NativeImageSkia m_nativeImage;
diff --git a/WebCore/platform/graphics/skia/GradientSkia.cpp b/WebCore/platform/graphics/skia/GradientSkia.cpp
index 3bdddb2..268b17e 100644
--- a/WebCore/platform/graphics/skia/GradientSkia.cpp
+++ b/WebCore/platform/graphics/skia/GradientSkia.cpp
@@ -152,19 +152,21 @@ SkShader* Gradient::platformGradient()
}
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.
-
- // The radius we give to Skia must be positive (and non-zero). If
- // we're given a zero radius, just ask for a very small radius so
- // Skia will still return an object.
- SkScalar radius = m_r1 > 0 ? WebCoreFloatToSkScalar(m_r1) : SK_ScalarMin;
- m_gradient = SkGradientShader::CreateRadial(m_p1,
- radius, colors, pos, static_cast<int>(countUsed), tile);
+ // Since the two-point radial gradient is slower than the plain radial,
+ // only use it if we have to.
+ if (m_p0 != m_p1) {
+ // The radii we give to Skia must be positive. If we're given a
+ // negative radius, ask for zero instead.
+ SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0;
+ SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0;
+ m_gradient = SkGradientShader::CreateTwoPointRadial(m_p0, radius0, m_p1, radius1, colors, pos, static_cast<int>(countUsed), tile);
+ } else {
+ // The radius we give to Skia must be positive (and non-zero). If
+ // we're given a zero radius, just ask for a very small radius so
+ // Skia will still return an object.
+ SkScalar radius = m_r1 > 0 ? WebCoreFloatToSkScalar(m_r1) : SK_ScalarMin;
+ m_gradient = SkGradientShader::CreateRadial(m_p1, radius, colors, pos, static_cast<int>(countUsed), tile);
+ }
} else {
SkPoint pts[2] = { m_p0, m_p1 };
m_gradient = SkGradientShader::CreateLinear(pts, colors, pos,
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index bbb42c9..f1536a6 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -31,11 +31,11 @@
#include "config.h"
#include "GraphicsContext.h"
-#include "GraphicsContextPlatformPrivate.h"
-#include "GraphicsContextPrivate.h"
#include "Color.h"
#include "FloatRect.h"
#include "Gradient.h"
+#include "GraphicsContextPlatformPrivate.h"
+#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
#include "IntRect.h"
#include "NativeImageSkia.h"
@@ -46,9 +46,9 @@
#include "SkBitmap.h"
#include "SkBlurDrawLooper.h"
#include "SkCornerPathEffect.h"
-#include "skia/ext/platform_canvas.h"
-#include "SkiaUtils.h"
#include "SkShader.h"
+#include "SkiaUtils.h"
+#include "skia/ext/platform_canvas.h"
#include <math.h>
#include <wtf/Assertions.h>
@@ -60,6 +60,23 @@ namespace WebCore {
namespace {
+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
+
// "Seatbelt" functions ------------------------------------------------------
//
// These functions check certain graphics primitives for being "safe".
@@ -195,23 +212,6 @@ void addCornerArc(SkPath* path, const SkRect& rect, const IntSize& size, int sta
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
@@ -293,10 +293,13 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
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));
+ // Adding one to the thickness doesn't make the border too thick as
+ // it's painted over afterwards. But without this adjustment the
+ // border appears a little anemic after anti-aliasing.
+ r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1));
path.addOval(r, SkPath::kCCW_Direction);
}
- platformContext()->canvas()->clipPath(path);
+ platformContext()->clipPathAntiAliased(path);
}
void GraphicsContext::addPath(const Path& path)
@@ -356,6 +359,18 @@ void GraphicsContext::clip(const Path& path)
if (!isPathSkiaSafe(getCTM(), p))
return;
+ platformContext()->clipPathAntiAliased(p);
+}
+
+void GraphicsContext::canvasClip(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ const SkPath& p = *path.platformPath();
+ if (!isPathSkiaSafe(getCTM(), p))
+ return;
+
platformContext()->canvas()->clipPath(p);
}
@@ -403,8 +418,11 @@ void GraphicsContext::clipPath(WindRule clipRule)
return;
SkPath path = platformContext()->currentPathInLocalCoordinates();
+ if (!isPathSkiaSafe(getCTM(), path))
+ return;
+
path.setFillType(clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
- platformContext()->canvas()->clipPath(path);
+ platformContext()->clipPathAntiAliased(path);
}
void GraphicsContext::clipToImageBuffer(const FloatRect& rect,
@@ -487,7 +505,7 @@ void GraphicsContext::drawFocusRing(const Color& color)
const Vector<IntRect>& rects = focusRingRects();
unsigned rectCount = rects.size();
- if (0 == rectCount)
+ if (!rectCount)
return;
SkRegion focusRingRegion;
@@ -521,26 +539,28 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
return;
SkPaint paint;
- SkPoint pts[2] = { (SkPoint)point1, (SkPoint)point2 };
- if (!isPointSkiaSafe(getCTM(), pts[0]) || !isPointSkiaSafe(getCTM(), pts[1]))
+ if (!isPointSkiaSafe(getCTM(), point1) || !isPointSkiaSafe(getCTM(), point2))
return;
+ FloatPoint p1 = point1;
+ FloatPoint p2 = point2;
+ bool isVerticalLine = (p1.x() == p2.x());
+ int width = roundf(strokeThickness());
+
// 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);
+ FloatSize disp = p2 - p1;
+ int length = SkScalarRound(disp.width() + disp.height());
platformContext()->setupPaintForStroking(&paint, 0, length);
- int width = roundf(strokeThickness());
- bool isVerticalLine = pts[0].fX == pts[1].fX;
if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) {
// 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.
SkRect r1, r2;
- r1.set(pts[0].fX, pts[0].fY, pts[0].fX + width, pts[0].fY + width);
- r2.set(pts[1].fX, pts[1].fY, pts[1].fX + width, pts[1].fY + width);
+ r1.set(p1.x(), p1.y(), p1.x() + width, p1.y() + width);
+ r2.set(p2.x(), p2.y(), p2.x() + width, p2.y() + width);
if (isVerticalLine) {
r1.offset(-width / 2, 0);
@@ -553,35 +573,11 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
fillPaint.setColor(paint.getColor());
platformContext()->canvas()->drawRect(r1, fillPaint);
platformContext()->canvas()->drawRect(r2, fillPaint);
-
- // Since we've already rendered the endcaps, adjust the endpoints to
- // exclude them from the line itself.
- if (isVerticalLine) {
- pts[0].fY += width;
- pts[1].fY -= width;
- } else {
- pts[0].fX += width;
- pts[1].fX -= width;
- }
}
- // "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.
+ adjustLineToPixelBoundaries(p1, p2, width, penStyle);
+ SkPoint pts[2] = { (SkPoint)p1, (SkPoint)p2 };
- 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);
}
@@ -711,8 +707,6 @@ void GraphicsContext::fillPath()
return;
const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.fillColorSpace;
-
path.setFillType(state.fillRule == RULE_EVENODD ?
SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
@@ -734,14 +728,13 @@ void GraphicsContext::fillRect(const FloatRect& rect)
}
const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.fillColorSpace;
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
platformContext()->canvas()->drawRect(r, paint);
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -772,7 +765,8 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect,
const IntSize& topRight,
const IntSize& bottomLeft,
const IntSize& bottomRight,
- const Color& color)
+ const Color& color,
+ ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -789,7 +783,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect,
// Not all the radii fit, return a rect. This matches the behavior of
// Path::createRoundedRectangle. Without this we attempt to draw a round
// shadow for a square box.
- fillRect(rect, color);
+ fillRect(rect, color, colorSpace);
return;
}
@@ -844,9 +838,9 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
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)
+ if (deviceOrigin.y() == deviceLowerRight.y() && rect.height())
deviceLowerRight.move(0, 1);
- if (deviceOrigin.x() == deviceLowerRight.x() && rect.width() != 0)
+ if (deviceOrigin.x() == deviceLowerRight.x() && rect.width())
deviceLowerRight.move(1, 0);
FloatPoint roundedOrigin(deviceOrigin.x() / deviceScaleX,
@@ -919,7 +913,7 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
return;
}
- size_t count = (dashLength % 2) == 0 ? dashLength : dashLength * 2;
+ size_t count = !(dashLength % 2) ? dashLength : dashLength * 2;
SkScalar* intervals = new SkScalar[count];
for (unsigned int i = 0; i < count; i++)
@@ -957,7 +951,7 @@ void GraphicsContext::setMiterLimit(float limit)
platformContext()->setMiterLimit(limit);
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -984,14 +978,15 @@ void GraphicsContext::setPlatformFillPattern(Pattern* pattern)
void GraphicsContext::setPlatformShadow(const IntSize& size,
int blurInt,
- const Color& color)
+ const Color& color,
+ ColorSpace colorSpace)
{
if (paintingDisabled())
return;
// Detect when there's no effective shadow and clear the looper.
- if (size.width() == 0 && size.height() == 0 && blurInt == 0) {
- platformContext()->setDrawLooper(NULL);
+ if (!size.width() && !size.height() && !blurInt) {
+ platformContext()->setDrawLooper(0);
return;
}
@@ -1026,7 +1021,7 @@ void GraphicsContext::setPlatformShadow(const IntSize& size,
dl->unref();
}
-void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor)
+void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -1125,7 +1120,6 @@ void GraphicsContext::strokePath()
return;
const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.strokeColorSpace;
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
@@ -1142,7 +1136,6 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
return;
const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.strokeColorSpace;
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index 7935ff1..c36f1ce 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -39,6 +39,7 @@
#include "ImageData.h"
#include "PlatformContextSkia.h"
#include "PNGImageEncoder.h"
+#include "SkColorPriv.h"
#include "SkiaUtils.h"
using namespace std;
@@ -104,13 +105,16 @@ Image* ImageBuffer::image() const
void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
{
const SkBitmap& bitmap = *context()->platformContext()->bitmap();
+ if (bitmap.isNull())
+ return;
+
ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
SkAutoLockPixels bitmapLock(bitmap);
for (int y = 0; y < m_size.height(); ++y) {
uint32_t* srcRow = bitmap.getAddr32(0, y);
for (int x = 0; x < m_size.width(); ++x) {
SkColor color = SkPMColorToColor(srcRow[x]);
- srcRow[x] = SkPreMultiplyARGB(lookUpTable[SkColorGetA(color)],
+ srcRow[x] = SkPreMultiplyARGB(SkColorGetA(color),
lookUpTable[SkColorGetR(color)],
lookUpTable[SkColorGetG(color)],
lookUpTable[SkColorGetB(color)]);
@@ -118,16 +122,16 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
}
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+template <Multiply multiplied>
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const SkBitmap& bitmap,
+ const IntSize& size)
{
- ASSERT(context());
-
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())
+ (rect.x() + rect.width()) > size.width() ||
+ (rect.y() + rect.height()) > size.height())
memset(data, 0, result->data()->length());
int originX = rect.x();
@@ -137,8 +141,8 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originX = 0;
}
int endX = rect.x() + rect.width();
- if (endX > m_size.width())
- endX = m_size.width();
+ if (endX > size.width())
+ endX = size.width();
int numColumns = endX - originX;
int originY = rect.y();
@@ -148,11 +152,10 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originY = 0;
}
int endY = rect.y() + rect.height();
- if (endY > m_size.height())
- endY = m_size.height();
+ if (endY > size.height())
+ endY = size.height();
int numRows = endY - originY;
- const SkBitmap& bitmap = *context()->platformContext()->bitmap();
ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
SkAutoLockPixels bitmapLock(bitmap);
@@ -162,12 +165,22 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
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);
+ if (multiplied == Unmultiplied) {
+ SkColor color = srcRow[x];
+ unsigned a = SkColorGetA(color);
+ destPixel[0] = a ? SkColorGetR(color) * 255 / a : 0;
+ destPixel[1] = a ? SkColorGetG(color) * 255 / a : 0;
+ destPixel[2] = a ? SkColorGetB(color) * 255 / a : 0;
+ destPixel[3] = a;
+ } else {
+ // Input and output are both pre-multiplied, we just need to re-arrange the
+ // bytes from the bitmap format to RGBA.
+ destPixel[0] = SkGetPackedR32(srcRow[x]);
+ destPixel[1] = SkGetPackedG32(srcRow[x]);
+ destPixel[2] = SkGetPackedB32(srcRow[x]);
+ destPixel[3] = SkGetPackedA32(srcRow[x]);
+ }
}
destRow += destBytesPerRow;
}
@@ -175,8 +188,19 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect,
- const IntPoint& destPoint)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Unmultiplied>(rect, *context()->platformContext()->bitmap(), m_size);
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Premultiplied>(rect, *context()->platformContext()->bitmap(), m_size);
+}
+
+template <Multiply multiplied>
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint,
+ const SkBitmap& bitmap, const IntSize& size)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -184,27 +208,26 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect,
int originX = sourceRect.x();
int destX = destPoint.x() + sourceRect.x();
ASSERT(destX >= 0);
- ASSERT(destX < m_size.width());
+ ASSERT(destX < size.width());
ASSERT(originX >= 0);
ASSERT(originX < sourceRect.right());
int endX = destPoint.x() + sourceRect.right();
- ASSERT(endX <= m_size.width());
+ ASSERT(endX <= 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(destY < size.height());
ASSERT(originY >= 0);
ASSERT(originY < sourceRect.bottom());
int endY = destPoint.y() + sourceRect.bottom();
- ASSERT(endY <= m_size.height());
+ ASSERT(endY <= size.height());
int numRows = endY - destY;
- const SkBitmap& bitmap = *context()->platformContext()->bitmap();
ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
SkAutoLockPixels bitmapLock(bitmap);
@@ -216,13 +239,27 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect,
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]);
+ if (multiplied == Unmultiplied)
+ destRow[x] = SkPreMultiplyARGB(srcPixel[3], srcPixel[0],
+ srcPixel[1], srcPixel[2]);
+ else
+ destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0],
+ srcPixel[1], srcPixel[2]);
}
srcRow += srcBytesPerRow;
}
}
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Premultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
+}
+
String ImageBuffer::toDataURL(const String&) const
{
// Encode the image into a vector.
diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp
index 45c3dcd..6d8ed22 100644
--- a/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -41,6 +41,7 @@
#include "PlatformContextSkia.h"
#include "PlatformString.h"
#include "SkiaUtils.h"
+#include "SkRect.h"
#include "SkShader.h"
#include "TransformationMatrix.h"
@@ -158,8 +159,8 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm
// 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());
+ SkIRect resizedImageRect = // Represents the size of the resized image.
+ { 0, 0, destRectRounded.width(), destRectRounded.height() };
if (srcIsFull && bitmap.hasResizedBitmap(destRectRounded.width(), destRectRounded.height())) {
// Yay, this bitmap frame already has a resized version.
@@ -196,25 +197,19 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm
} 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);
+ destBitmapSubsetSkI);
// 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 };
+ destBitmapSubsetSkI.offset(destRect.fLeft, destRect.fTop);
+ SkRect offsetDestRect;
+ offsetDestRect.set(destBitmapSubsetSkI);
canvas.drawBitmapRect(resampled, 0, offsetDestRect, &paint);
}
@@ -307,6 +302,7 @@ void Image::drawPattern(GraphicsContext* context,
const FloatRect& floatSrcRect,
const TransformationMatrix& patternTransform,
const FloatPoint& phase,
+ ColorSpace styleColorSpace,
CompositeOperator compositeOp,
const FloatRect& destRect)
{
@@ -410,7 +406,7 @@ void BitmapImage::checkForSolidColor()
}
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
- const FloatRect& srcRect, CompositeOperator compositeOp)
+ const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp)
{
if (!m_source.initialized())
return;
@@ -442,6 +438,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt,
const FloatRect& dstRect,
const FloatRect& srcRect,
+ ColorSpace styleColorSpace,
CompositeOperator compositeOp)
{
FloatRect normDstRect = normalizeRect(dstRect);
diff --git a/WebCore/platform/graphics/skia/ImageSourceSkia.cpp b/WebCore/platform/graphics/skia/ImageSourceSkia.cpp
deleted file mode 100644
index 1647b86..0000000
--- a/WebCore/platform/graphics/skia/ImageSourceSkia.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2008, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "config.h"
-#include "ImageSource.h"
-#include "SharedBuffer.h"
-
-#include "GIFImageDecoder.h"
-#include "ICOImageDecoder.h"
-#include "JPEGImageDecoder.h"
-#include "PNGImageDecoder.h"
-#include "BMPImageDecoder.h"
-#include "XBMImageDecoder.h"
-
-#include "SkBitmap.h"
-
-namespace WebCore {
-
-ImageDecoder* createDecoder(const Vector<char>& data)
-{
- // 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();
-
- // 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)
-{
- 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
-{
- 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());
-
- // 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 index) const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->frameSizeAtIndex(index);
-}
-
-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.
- return buffer->asNewNativeImage();
-}
-
-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();
-}
-
-String ImageSource::filenameExtension() const
-{
- return m_decoder ? m_decoder->filenameExtension() : String();
-}
-
-}
diff --git a/WebCore/platform/graphics/skia/NativeImageSkia.cpp b/WebCore/platform/graphics/skia/NativeImageSkia.cpp
index 477be05..2411897 100644
--- a/WebCore/platform/graphics/skia/NativeImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/NativeImageSkia.cpp
@@ -30,7 +30,7 @@
#include "config.h"
-#if PLATFORM(SKIA)
+#if !PLATFORM(ANDROID)
#include "skia/ext/image_operations.h"
#endif
@@ -65,10 +65,11 @@ bool NativeImageSkia::hasResizedBitmap(int w, int h) const
SkBitmap NativeImageSkia::resizedBitmap(int w, int h) const
{
-#if PLATFORM(SKIA)
+#if !PLATFORM(ANDROID)
if (m_resizedImage.width() != w || m_resizedImage.height() != h)
m_resizedImage = skia::ImageOperations::Resize(*this, skia::ImageOperations::RESIZE_LANCZOS3, w, h);
#endif
+
return m_resizedImage;
}
diff --git a/WebCore/platform/graphics/skia/PathSkia.cpp b/WebCore/platform/graphics/skia/PathSkia.cpp
index 5ac14b9..2cbb759 100644
--- a/WebCore/platform/graphics/skia/PathSkia.cpp
+++ b/WebCore/platform/graphics/skia/PathSkia.cpp
@@ -123,26 +123,31 @@ void Path::addArc(const FloatPoint& p, float r, float sa, float ea, bool anticlo
SkScalar cx = WebCoreFloatToSkScalar(p.x());
SkScalar cy = WebCoreFloatToSkScalar(p.y());
SkScalar radius = WebCoreFloatToSkScalar(r);
+ SkScalar s360 = SkIntToScalar(360);
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)
+ SkScalar startDegrees = WebCoreFloatToSkScalar(sa * 180 / piFloat);
+ SkScalar sweepDegrees = WebCoreFloatToSkScalar(sweep * 180 / piFloat);
+ // Check for a circle.
+ if (sweepDegrees >= s360 || sweepDegrees <= -s360) {
+ // Move to the start position (0 sweep means we add a single point).
+ m_path->arcTo(oval, startDegrees, 0, false);
+ // Draw the circle.
m_path->addOval(oval);
- else {
- SkScalar startDegrees = WebCoreFloatToSkScalar(sa * 180 / piFloat);
- SkScalar sweepDegrees = WebCoreFloatToSkScalar(sweep * 180 / piFloat);
-
+ // Force a moveTo the end position.
+ m_path->arcTo(oval, startDegrees + sweepDegrees, 0, true);
+ } else {
// 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);
+ sweepDegrees -= s360;
} else if (!anticlockwise && sweepDegrees < 0) {
- sweepDegrees += SkIntToScalar(360);
+ sweepDegrees += s360;
}
m_path->arcTo(oval, startDegrees, sweepDegrees, false);
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index e0a292c..dfffa0d 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -45,6 +45,12 @@
#include "SkDashPathEffect.h"
#include <wtf/MathExtras.h>
+#include <wtf/Vector.h>
+
+namespace WebCore
+{
+extern bool isPathSkiaSafe(const SkMatrix& transform, const SkPath& path);
+}
// State -----------------------------------------------------------------------
@@ -90,6 +96,10 @@ struct PlatformContextSkia::State {
WebCore::FloatRect m_clip;
#endif
+ // This is a list of clipping paths which are currently active, in the
+ // order in which they were pushed.
+ WTF::Vector<SkPath> m_antiAliasClipPaths;
+
private:
// Not supported.
void operator=(const State&);
@@ -105,8 +115,8 @@ PlatformContextSkia::State::State()
, m_fillShader(0)
, m_strokeStyle(WebCore::SolidStroke)
, m_strokeColor(WebCore::Color::black)
- , m_strokeThickness(0)
, m_strokeShader(0)
+ , m_strokeThickness(0)
, m_dashRatio(3)
, m_miterLimit(4)
, m_lineCap(SkPaint::kDefault_Cap)
@@ -125,8 +135,8 @@ PlatformContextSkia::State::State(const State& other)
, m_fillShader(other.m_fillShader)
, m_strokeStyle(other.m_strokeStyle)
, m_strokeColor(other.m_strokeColor)
- , m_strokeThickness(other.m_strokeThickness)
, m_strokeShader(other.m_strokeShader)
+ , m_strokeThickness(other.m_strokeThickness)
, m_dashRatio(other.m_dashRatio)
, m_miterLimit(other.m_miterLimit)
, m_lineCap(other.m_lineCap)
@@ -244,6 +254,21 @@ void PlatformContextSkia::beginLayerClippedToImage(const WebCore::FloatRect& rec
}
#endif
+void PlatformContextSkia::clipPathAntiAliased(const SkPath& clipPath)
+{
+ // If we are currently tracking any anti-alias clip paths, then we already
+ // have a layer in place and don't need to add another.
+ bool haveLayerOutstanding = m_state->m_antiAliasClipPaths.size();
+
+ // See comments in applyAntiAliasedClipPaths about how this works.
+ m_state->m_antiAliasClipPaths.append(clipPath);
+
+ if (!haveLayerOutstanding) {
+ SkRect bounds = clipPath.getBounds();
+ canvas()->saveLayerAlpha(&bounds, 255, static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag | SkCanvas::kClipToLayer_SaveFlag));
+ }
+}
+
void PlatformContextSkia::restore()
{
#if defined(__linux__) || PLATFORM(WIN_OS)
@@ -253,6 +278,9 @@ void PlatformContextSkia::restore()
}
#endif
+ if (!m_state->m_antiAliasClipPaths.isEmpty())
+ applyAntiAliasedClipPaths(m_state->m_antiAliasClipPaths);
+
m_stateStack.removeLast();
m_state = &m_stateStack.last();
@@ -278,6 +306,7 @@ void PlatformContextSkia::drawRect(SkRect rect)
SkShader* oldFillShader = m_state->m_fillShader;
oldFillShader->safeRef();
setFillColor(m_state->m_strokeColor);
+ paint.reset();
setupPaintForFilling(&paint);
SkRect topBorder = { rect.fLeft, rect.fTop, rect.fRight, rect.fTop + 1 };
canvas()->drawRect(topBorder, paint);
@@ -295,7 +324,7 @@ void PlatformContextSkia::drawRect(SkRect rect)
void PlatformContextSkia::setupPaintCommon(SkPaint* paint) const
{
-#ifdef SK_DEBUGx
+#if defined(SK_DEBUG)
{
SkPaint defaultPaint;
SkASSERT(*paint == defaultPaint);
@@ -314,6 +343,15 @@ void PlatformContextSkia::setupPaintForFilling(SkPaint* paint) const
paint->setShader(m_state->m_fillShader);
}
+static SkScalar scalarBound(SkScalar v, SkScalar min, SkScalar max)
+{
+ if (v < min)
+ return min;
+ if (v > max)
+ return max;
+ return v;
+}
+
float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, int length) const
{
setupPaintCommon(paint);
@@ -322,10 +360,13 @@ float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, i
paint->setColor(m_state->applyAlpha(m_state->m_strokeColor));
paint->setShader(m_state->m_strokeShader);
paint->setStyle(SkPaint::kStroke_Style);
- paint->setStrokeWidth(SkFloatToScalar(width));
+ // The limits here (512 and 256) were made up but are hopefully large
+ // enough to be reasonable. They are, empirically, small enough not to
+ // cause overflows in Skia.
+ paint->setStrokeWidth(scalarBound(SkFloatToScalar(width), 0, 512));
paint->setStrokeCap(m_state->m_lineCap);
paint->setStrokeJoin(m_state->m_lineJoin);
- paint->setStrokeMiter(SkFloatToScalar(m_state->m_miterLimit));
+ paint->setStrokeMiter(scalarBound(SkFloatToScalar(m_state->m_miterLimit), 0, 256));
if (m_state->m_dash)
paint->setPathEffect(m_state->m_dash);
@@ -543,3 +584,40 @@ void PlatformContextSkia::applyClipFromImage(const WebCore::FloatRect& rect, con
m_canvas->drawBitmap(imageBuffer, SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()), &paint);
}
#endif
+
+void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths)
+{
+ // Anti-aliased clipping:
+ //
+ // Skia's clipping is 1-bit only. Consider what would happen if it were 8-bit:
+ // We have a square canvas, filled with white and we declare a circular
+ // clipping path. Then we fill twice with a black rectangle. The fractional
+ // pixels would first get the correct color (white * alpha + black * (1 -
+ // alpha)), but the second fill would apply the alpha to the already
+ // modified color and the result would be too dark.
+ //
+ // This, anti-aliased clipping needs to be performed after the drawing has
+ // been done. In order to do this, we create a new layer of the canvas in
+ // clipPathAntiAliased and store the clipping path. All drawing is done to
+ // the layer's bitmap while it's in effect. When WebKit calls restore() to
+ // undo the clipping, this function is called.
+ //
+ // Here, we walk the list of clipping paths backwards and, for each, we
+ // clear outside of the clipping path. We only need a single extra layer
+ // for any number of clipping paths.
+ //
+ // When we call restore on the SkCanvas, the layer's bitmap is composed
+ // into the layer below and we end up with correct, anti-aliased clipping.
+
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kClear_Mode);
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kFill_Style);
+
+ for (size_t i = paths.size() - 1; i < paths.size(); --i) {
+ paths[i].setFillType(SkPath::kInverseWinding_FillType);
+ m_canvas->drawPath(paths[i], paint);
+ }
+
+ m_canvas->restore();
+}
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h
index 0c87fc2..53590bf 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -92,6 +92,7 @@ public:
void beginLayerClippedToImage(const WebCore::FloatRect&,
const WebCore::ImageBuffer*);
#endif
+ void clipPathAntiAliased(const SkPath&);
// Sets up the common flags on a paint for antialiasing, effects, etc.
// This is implicitly called by setupPaintFill and setupPaintStroke, but
@@ -172,6 +173,7 @@ private:
// m_canvas that are also in imageBuffer.
void applyClipFromImage(const WebCore::FloatRect&, const SkBitmap&);
#endif
+ void applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths);
// Defines drawing style.
struct State;
diff --git a/WebCore/platform/graphics/skia/SkiaUtils.cpp b/WebCore/platform/graphics/skia/SkiaUtils.cpp
index 662ea5c..377ca06 100644
--- a/WebCore/platform/graphics/skia/SkiaUtils.cpp
+++ b/WebCore/platform/graphics/skia/SkiaUtils.cpp
@@ -131,10 +131,10 @@ 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),
@@ -200,8 +200,13 @@ bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath::
SkRect bounds = originalPath->getBounds();
- // We can immediately return false if the point is outside the bounding rect
- if (!bounds.contains(SkFloatToScalar(point.x()), SkFloatToScalar(point.y())))
+ // We can immediately return false if the point is outside the bounding
+ // rect. We don't use bounds.contains() here, since it would exclude
+ // points on the right and bottom edges of the bounding rect, and we want
+ // to include them.
+ SkScalar fX = SkFloatToScalar(point.x());
+ SkScalar fY = SkFloatToScalar(point.y());
+ if (fX < bounds.fLeft || fX > bounds.fRight || fY < bounds.fTop || fY > bounds.fBottom)
return false;
originalPath->setFillType(ft);
@@ -225,7 +230,7 @@ bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath::
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);
+ clip.setRect(x - 1, y - 1, x + 1, y + 1);
bool contains = rgn.setPath(*path, clip);
diff --git a/WebCore/platform/graphics/transforms/TransformOperations.h b/WebCore/platform/graphics/transforms/TransformOperations.h
index dd56408..08efd23 100644
--- a/WebCore/platform/graphics/transforms/TransformOperations.h
+++ b/WebCore/platform/graphics/transforms/TransformOperations.h
@@ -31,7 +31,7 @@
namespace WebCore {
-class TransformOperations {
+class TransformOperations : public FastAllocBase {
public:
TransformOperations(bool makeIdentity = false);
diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h
index a7fbb3d..802ad3c 100644
--- a/WebCore/platform/graphics/transforms/TransformationMatrix.h
+++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h
@@ -29,6 +29,7 @@
#include "FloatPoint.h"
#include "IntPoint.h"
#include <string.h> //for memcpy
+#include <wtf/FastAllocBase.h>
#if PLATFORM(CG)
#include <CoreGraphics/CGAffineTransform.h>
@@ -36,7 +37,7 @@
#include <cairo.h>
#elif PLATFORM(QT)
#include <QTransform>
-#elif PLATFORM(SKIA) || PLATFORM(SGL)
+#elif PLATFORM(SKIA)
#include <SkMatrix.h>
#elif PLATFORM(WX) && USE(WXGC)
#include <wx/graphics.h>
@@ -49,7 +50,7 @@ class FloatPoint3D;
class FloatRect;
class FloatQuad;
-class TransformationMatrix {
+class TransformationMatrix : public FastAllocBase {
public:
typedef double Matrix4[4][4];
@@ -300,7 +301,7 @@ public:
operator cairo_matrix_t() const;
#elif PLATFORM(QT)
operator QTransform() const;
-#elif PLATFORM(SKIA) || PLATFORM(SGL)
+#elif PLATFORM(SKIA)
operator SkMatrix() const;
#elif PLATFORM(WX) && USE(WXGC)
operator wxGraphicsMatrix() const;
diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp
index 803f5db..e901669 100644
--- a/WebCore/platform/graphics/win/FontCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -297,6 +297,30 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
CGContextRef cgContext = graphicsContext->platformContext();
bool shouldUseFontSmoothing = WebCoreShouldUseFontSmoothing();
+ switch(fontDescription().fontSmoothing()) {
+ case Antialiased: {
+ graphicsContext->setShouldAntialias(true);
+ shouldUseFontSmoothing = false;
+ break;
+ }
+ case SubpixelAntialiased: {
+ graphicsContext->setShouldAntialias(true);
+ shouldUseFontSmoothing = true;
+ break;
+ }
+ case NoSmoothing: {
+ graphicsContext->setShouldAntialias(false);
+ shouldUseFontSmoothing = false;
+ break;
+ }
+ case AutoSmoothing: {
+ // For the AutoSmooth case, don't do anything! Keep the default settings.
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
if (font->platformData().useGDI()) {
if (!shouldUseFontSmoothing || (graphicsContext->textDrawingMode() & cTextStroke)) {
drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
@@ -338,14 +362,14 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
graphicsContext->clearShadow();
Color fillColor = graphicsContext->fillColor();
Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- graphicsContext->setFillColor(shadowFillColor);
+ graphicsContext->setFillColor(shadowFillColor, DeviceColorSpace);
CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width(), point.y() + translation.height() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
if (font->syntheticBoldOffset()) {
CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
- graphicsContext->setFillColor(fillColor);
+ graphicsContext->setFillColor(fillColor, DeviceColorSpace);
}
CGContextSetTextPosition(cgContext, point.x() + translation.width(), point.y() + translation.height());
@@ -356,7 +380,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
}
if (hasSimpleShadow)
- graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor);
+ graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace);
wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle);
}
diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp
index 887bf79..8663623 100644
--- a/WebCore/platform/graphics/win/FontCacheWin.cpp
+++ b/WebCore/platform/graphics/win/FontCacheWin.cpp
@@ -33,8 +33,9 @@
#include "SimpleFontData.h"
#include "StringHash.h"
#include "UnicodeRange.h"
-#include <windows.h>
#include <mlang.h>
+#include <windows.h>
+#include <wtf/StdLibExtras.h>
#if PLATFORM(CG)
#include <ApplicationServices/ApplicationServices.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
@@ -305,7 +306,17 @@ FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fo
// 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");
- return getCachedFontPlatformData(fontDescription, timesStr);
+ if (FontPlatformData* platformFont = getCachedFontPlatformData(fontDescription, timesStr))
+ return platformFont;
+
+ DEFINE_STATIC_LOCAL(String, defaultGUIFontFamily, ());
+ if (defaultGUIFontFamily.isEmpty()) {
+ HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
+ LOGFONT logFont;
+ GetObject(defaultGUIFont, sizeof(logFont), &logFont);
+ defaultGUIFontFamily = String(logFont.lfFaceName, wcsnlen(logFont.lfFaceName, LF_FACESIZE));
+ }
+ return getCachedFontPlatformData(fontDescription, defaultGUIFontFamily);
}
static LONG toGDIFontWeight(FontWeight fontWeight)
diff --git a/WebCore/platform/graphics/win/FontDatabase.cpp b/WebCore/platform/graphics/win/FontDatabase.cpp
index 1308ff0..d0773ea 100644
--- a/WebCore/platform/graphics/win/FontDatabase.cpp
+++ b/WebCore/platform/graphics/win/FontDatabase.cpp
@@ -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
@@ -99,17 +99,12 @@ static RetainPtr<CFPropertyListRef> readFontPlist()
return plist;
}
-static bool populateFontDatabaseFromPlist()
+static bool populateFontDatabaseFromPlist(CFPropertyListRef plist)
{
- RetainPtr<CFPropertyListRef> plist = readFontPlist();
if (!plist)
return false;
- RetainPtr<CFDataRef> data(AdoptCF, CFPropertyListCreateXMLData(0, plist.get()));
- if (!data)
- return false;
-
- wkAddFontsFromPlistRepresentation(data.get());
+ wkAddFontsFromPlist(plist);
return true;
}
@@ -123,15 +118,69 @@ static bool populateFontDatabaseFromFileSystem()
return true;
}
-static void writeFontDatabaseToPlist()
+static CFStringRef fontFilenamesFromRegistryKey()
+{
+ static CFStringRef key = CFSTR("WebKitFontFilenamesFromRegistry");
+ return key;
+}
+
+static void writeFontDatabaseToPlist(CFPropertyListRef cgFontDBPropertyList, CFPropertyListRef filenamesFromRegistry)
{
- RetainPtr<CFDataRef> data(AdoptCF, wkCreateFontsPlistRepresentation());
+ if (!cgFontDBPropertyList)
+ return;
+
+ RetainPtr<CFDataRef> data;
+
+ if (!filenamesFromRegistry || CFGetTypeID(cgFontDBPropertyList) != CFDictionaryGetTypeID())
+ data.adoptCF(CFPropertyListCreateXMLData(kCFAllocatorDefault, cgFontDBPropertyList));
+ else {
+ RetainPtr<CFMutableDictionaryRef> dictionary(AdoptCF, CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 2, static_cast<CFDictionaryRef>(cgFontDBPropertyList)));
+ CFDictionarySetValue(dictionary.get(), fontFilenamesFromRegistryKey(), filenamesFromRegistry);
+ data.adoptCF(CFPropertyListCreateXMLData(kCFAllocatorDefault, dictionary.get()));
+ }
+
if (!data)
return;
safeCreateFile(fontsPlistPath(), data.get());
}
+static RetainPtr<CFArrayRef> fontFilenamesFromRegistry()
+{
+ RetainPtr<CFMutableArrayRef> filenames(AdoptCF, CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
+
+ HKEY key;
+ if (FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), 0, KEY_READ, &key)))
+ return filenames;
+
+ DWORD valueCount;
+ DWORD maxNameLength;
+ DWORD maxValueLength;
+ if (FAILED(RegQueryInfoKey(key, 0, 0, 0, 0, 0, 0, &valueCount, &maxNameLength, &maxValueLength, 0, 0))) {
+ RegCloseKey(key);
+ return filenames;
+ }
+
+ Vector<TCHAR> name(maxNameLength + 1);
+ Vector<BYTE> value(maxValueLength + 1);
+
+ for (size_t i = 0; i < valueCount; ++i) {
+ DWORD nameLength = name.size();
+ DWORD valueLength = value.size();
+ DWORD type;
+ if (FAILED(RegEnumValue(key, i, name.data(), &nameLength, 0, &type, value.data(), &valueLength)))
+ continue;
+ if (type != REG_SZ)
+ continue;
+
+ RetainPtr<CFDataRef> filename(AdoptCF, CFDataCreate(kCFAllocatorDefault, value.data(), valueLength));
+ CFArrayAppendValue(filenames.get(), filename.get());
+ }
+
+ RegCloseKey(key);
+ return filenames;
+}
+
void populateFontDatabase()
{
static bool initialized;
@@ -139,12 +188,27 @@ void populateFontDatabase()
return;
initialized = true;
- if (!systemHasFontsNewerThanFontsPlist())
- if (populateFontDatabaseFromPlist())
+ RetainPtr<CFPropertyListRef> propertyList = readFontPlist();
+ RetainPtr<CFArrayRef> lastFilenamesFromRegistry;
+ if (propertyList && CFGetTypeID(propertyList.get()) == CFDictionaryGetTypeID()) {
+ CFDictionaryRef dictionary = static_cast<CFDictionaryRef>(propertyList.get());
+ CFArrayRef array = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionary, fontFilenamesFromRegistryKey()));
+ if (array && CFGetTypeID(array) == CFArrayGetTypeID())
+ lastFilenamesFromRegistry = array;
+ }
+ RetainPtr<CFArrayRef> currentFilenamesFromRegistry = fontFilenamesFromRegistry();
+ bool registryChanged = !lastFilenamesFromRegistry || !CFEqual(lastFilenamesFromRegistry.get(), currentFilenamesFromRegistry.get());
+
+ if (!registryChanged && !systemHasFontsNewerThanFontsPlist()) {
+ if (populateFontDatabaseFromPlist(propertyList.get()))
return;
+ }
- if (populateFontDatabaseFromFileSystem())
- writeFontDatabaseToPlist();
+ if (populateFontDatabaseFromFileSystem()) {
+ wkAddFontsFromRegistry();
+ RetainPtr<CFPropertyListRef> cgFontDBPropertyList(AdoptCF, wkCreateFontsPlist());
+ writeFontDatabaseToPlist(cgFontDBPropertyList.get(), currentFilenamesFromRegistry.get());
+ }
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/FontPlatformData.h b/WebCore/platform/graphics/win/FontPlatformData.h
index 0660d90..5084469 100644
--- a/WebCore/platform/graphics/win/FontPlatformData.h
+++ b/WebCore/platform/graphics/win/FontPlatformData.h
@@ -78,7 +78,6 @@ public:
#if PLATFORM(CG)
CGFontRef cgFont() const { return m_cgFont.get(); }
#elif PLATFORM(CAIRO)
- void setFont(cairo_t* ft) const;
cairo_font_face_t* fontFace() const { return m_fontFace; }
cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
#endif
diff --git a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
index b56a71c..9fce68a 100644
--- a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
+++ b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
@@ -96,12 +96,6 @@ FontPlatformData::FontPlatformData(const FontPlatformData& source)
m_scaledFont = cairo_scaled_font_reference(source.m_scaledFont);
}
-void FontPlatformData::setFont(cairo_t* cr) const
-{
- ASSERT(m_scaledFont);
-
- cairo_set_scaled_font(cr, m_scaledFont);
-}
FontPlatformData::~FontPlatformData()
{
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index 9eaf54b..137b914 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -65,13 +65,13 @@ GraphicsContext::GraphicsContext(HDC hdc, bool hasAlpha)
: m_common(createGraphicsContextPrivate())
, m_data(new GraphicsContextPlatformPrivate(CGContextWithHDC(hdc, hasAlpha)))
{
- CGContextRelease(m_data->m_cgContext);
+ CGContextRelease(m_data->m_cgContext.get());
m_data->m_hdc = hdc;
setPaintingDisabled(!m_data->m_cgContext);
if (m_data->m_cgContext) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), DeviceColorSpace);
+ setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
}
}
@@ -98,7 +98,7 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo
CGColorSpaceRelease(deviceRGB);
CGImageRef image = CGBitmapContextCreateImage(bitmapContext);
- CGContextDrawImage(m_data->m_cgContext, dstRect, image);
+ CGContextDrawImage(m_data->m_cgContext.get(), dstRect, image);
// Delete all our junk.
CGImageRelease(image);
@@ -121,7 +121,7 @@ void GraphicsContext::drawWindowsBitmap(WindowsBitmap* image, const IntPoint& po
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());
+ CGContextDrawImage(m_data->m_cgContext.get(), CGRectMake(point.x(), point.y(), image->size().width(), image->size().height()), cgImage.get());
}
void GraphicsContext::drawFocusRing(const Color& color)
@@ -243,7 +243,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point,
void GraphicsContextPlatformPrivate::flush()
{
- CGContextFlush(m_cgContext);
+ CGContextFlush(m_cgContext.get());
}
}
diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
index 2489e02..61ae76c 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
@@ -74,8 +74,8 @@ GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha)
if (m_data->cr) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), fillColorSpace());
+ setPlatformStrokeColor(strokeColor(), strokeColorSpace());
}
}
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
new file mode 100644
index 0000000..22faeb8
--- /dev/null
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
@@ -0,0 +1,721 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsLayerCACF.h"
+
+#include "CString.h"
+#include "FloatConversion.h"
+#include "FloatRect.h"
+#include "Image.h"
+#include "PlatformString.h"
+#include "SystemTime.h"
+#include "WKCACFLayer.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/StringExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static inline void copyTransform(CATransform3D& toT3D, const TransformationMatrix& t)
+{
+ toT3D.m11 = narrowPrecisionToFloat(t.m11());
+ toT3D.m12 = narrowPrecisionToFloat(t.m12());
+ toT3D.m13 = narrowPrecisionToFloat(t.m13());
+ toT3D.m14 = narrowPrecisionToFloat(t.m14());
+ toT3D.m21 = narrowPrecisionToFloat(t.m21());
+ toT3D.m22 = narrowPrecisionToFloat(t.m22());
+ toT3D.m23 = narrowPrecisionToFloat(t.m23());
+ toT3D.m24 = narrowPrecisionToFloat(t.m24());
+ toT3D.m31 = narrowPrecisionToFloat(t.m31());
+ toT3D.m32 = narrowPrecisionToFloat(t.m32());
+ toT3D.m33 = narrowPrecisionToFloat(t.m33());
+ toT3D.m34 = narrowPrecisionToFloat(t.m34());
+ toT3D.m41 = narrowPrecisionToFloat(t.m41());
+ toT3D.m42 = narrowPrecisionToFloat(t.m42());
+ toT3D.m43 = narrowPrecisionToFloat(t.m43());
+ toT3D.m44 = narrowPrecisionToFloat(t.m44());
+}
+
+TransformationMatrix CAToTransform3D(const CATransform3D& fromT3D)
+{
+ return TransformationMatrix(
+ fromT3D.m11,
+ fromT3D.m12,
+ fromT3D.m13,
+ fromT3D.m14,
+ fromT3D.m21,
+ fromT3D.m22,
+ fromT3D.m23,
+ fromT3D.m24,
+ fromT3D.m31,
+ fromT3D.m32,
+ fromT3D.m33,
+ fromT3D.m34,
+ fromT3D.m41,
+ fromT3D.m42,
+ fromT3D.m43,
+ fromT3D.m44);
+}
+
+static void setLayerBorderColor(WKCACFLayer* layer, const Color& color)
+{
+ CGColorRef borderColor = createCGColor(color);
+ layer->setBorderColor(borderColor);
+ CGColorRelease(borderColor);
+}
+
+static void clearBorderColor(WKCACFLayer* layer)
+{
+ layer->setBorderColor(0);
+}
+
+static void setLayerBackgroundColor(WKCACFLayer* layer, const Color& color)
+{
+ CGColorRef bgColor = createCGColor(color);
+ layer->setBackgroundColor(bgColor);
+ CGColorRelease(bgColor);
+}
+
+static void clearLayerBackgroundColor(WKCACFLayer* layer)
+{
+ layer->setBackgroundColor(0);
+}
+
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
+{
+ return CompositingCoordinatesBottomUp;
+}
+
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerCACF(client);
+}
+
+GraphicsLayerCACF::GraphicsLayerCACF(GraphicsLayerClient* client)
+ : GraphicsLayer(client)
+ , m_contentsLayerPurpose(NoContentsLayer)
+ , m_contentsLayerHasBackgroundColor(false)
+{
+ m_layer = WKCACFLayer::create(kCACFLayer, this);
+
+ updateDebugIndicators();
+}
+
+GraphicsLayerCACF::~GraphicsLayerCACF()
+{
+ // clean up the WK layer
+ if (m_layer)
+ m_layer->removeFromSuperlayer();
+
+ if (m_transformLayer)
+ m_transformLayer->removeFromSuperlayer();
+}
+
+void GraphicsLayerCACF::setName(const String& inName)
+{
+ String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
+ GraphicsLayer::setName(name);
+
+ m_layer->setName(inName);
+}
+
+NativeLayer GraphicsLayerCACF::nativeLayer() const
+{
+ return m_layer.get();
+}
+
+bool GraphicsLayerCACF::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool childrenChanged = GraphicsLayer::setChildren(children);
+ // FIXME: GraphicsLayer::setChildren calls addChild() for each sublayer, which
+ // will end up calling updateSublayerList() N times.
+ if (childrenChanged)
+ updateSublayerList();
+
+ return childrenChanged;
+}
+
+void GraphicsLayerCACF::addChild(GraphicsLayer* childLayer)
+{
+ GraphicsLayer::addChild(childLayer);
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::addChildAtIndex(GraphicsLayer* childLayer, int index)
+{
+ GraphicsLayer::addChildAtIndex(childLayer, index);
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildBelow(childLayer, sibling);
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
+{
+ GraphicsLayer::addChildAbove(childLayer, sibling);
+ updateSublayerList();
+}
+
+bool GraphicsLayerCACF::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ if (GraphicsLayer::replaceChild(oldChild, newChild)) {
+ updateSublayerList();
+ return true;
+ }
+ return false;
+}
+
+void GraphicsLayerCACF::removeFromParent()
+{
+ GraphicsLayer::removeFromParent();
+ layerForSuperlayer()->removeFromSuperlayer();
+}
+
+void GraphicsLayerCACF::setPosition(const FloatPoint& point)
+{
+ GraphicsLayer::setPosition(point);
+ updateLayerPosition();
+}
+
+void GraphicsLayerCACF::setAnchorPoint(const FloatPoint3D& point)
+{
+ if (point == m_anchorPoint)
+ return;
+
+ GraphicsLayer::setAnchorPoint(point);
+ updateAnchorPoint();
+}
+
+void GraphicsLayerCACF::setSize(const FloatSize& size)
+{
+ if (size == m_size)
+ return;
+
+ GraphicsLayer::setSize(size);
+ updateLayerSize();
+}
+
+void GraphicsLayerCACF::setTransform(const TransformationMatrix& t)
+{
+ if (t == m_transform)
+ return;
+
+ GraphicsLayer::setTransform(t);
+ updateTransform();
+}
+
+void GraphicsLayerCACF::setChildrenTransform(const TransformationMatrix& t)
+{
+ if (t == m_childrenTransform)
+ return;
+
+ GraphicsLayer::setChildrenTransform(t);
+ updateChildrenTransform();
+}
+
+void GraphicsLayerCACF::setPreserves3D(bool preserves3D)
+{
+ if (preserves3D == m_preserves3D)
+ return;
+
+ GraphicsLayer::setPreserves3D(preserves3D);
+ updateLayerPreserves3D();
+}
+
+void GraphicsLayerCACF::setMasksToBounds(bool masksToBounds)
+{
+ if (masksToBounds == m_masksToBounds)
+ return;
+
+ GraphicsLayer::setMasksToBounds(masksToBounds);
+ updateMasksToBounds();
+}
+
+void GraphicsLayerCACF::setDrawsContent(bool drawsContent)
+{
+ if (drawsContent == m_drawsContent)
+ return;
+
+ GraphicsLayer::setDrawsContent(drawsContent);
+ updateLayerDrawsContent();
+}
+
+void GraphicsLayerCACF::setBackgroundColor(const Color& color)
+{
+ if (m_backgroundColorSet && m_backgroundColor == color)
+ return;
+
+ GraphicsLayer::setBackgroundColor(color);
+
+ m_contentsLayerHasBackgroundColor = true;
+ updateLayerBackgroundColor();
+}
+
+void GraphicsLayerCACF::clearBackgroundColor()
+{
+ if (!m_backgroundColorSet)
+ return;
+
+ GraphicsLayer::clearBackgroundColor();
+ clearLayerBackgroundColor(m_contentsLayer.get());
+}
+
+void GraphicsLayerCACF::setContentsOpaque(bool opaque)
+{
+ if (m_contentsOpaque == opaque)
+ return;
+
+ GraphicsLayer::setContentsOpaque(opaque);
+ updateContentsOpaque();
+}
+
+void GraphicsLayerCACF::setBackfaceVisibility(bool visible)
+{
+ if (m_backfaceVisibility == visible)
+ return;
+
+ GraphicsLayer::setBackfaceVisibility(visible);
+ updateBackfaceVisibility();
+}
+
+void GraphicsLayerCACF::setOpacity(float opacity)
+{
+ float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
+
+ if (m_opacity == clampedOpacity)
+ return;
+
+ GraphicsLayer::setOpacity(clampedOpacity);
+ primaryLayer()->setOpacity(opacity);
+}
+
+void GraphicsLayerCACF::setNeedsDisplay()
+{
+ if (drawsContent())
+ m_layer->setNeedsDisplay();
+}
+
+void GraphicsLayerCACF::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ if (drawsContent())
+ m_layer->setNeedsDisplay(rect);
+}
+
+void GraphicsLayerCACF::setContentsRect(const IntRect& rect)
+{
+ if (rect == m_contentsRect)
+ return;
+
+ GraphicsLayer::setContentsRect(rect);
+ updateContentsRect();
+}
+
+void GraphicsLayerCACF::setContentsToImage(Image* image)
+{
+ bool childrenChanged = false;
+
+ if (image) {
+ m_pendingContentsImage = image->nativeImageForCurrentFrame();
+ m_contentsLayerPurpose = ContentsLayerForImage;
+ if (!m_contentsLayer)
+ childrenChanged = true;
+ } else {
+ m_pendingContentsImage = 0;
+ m_contentsLayerPurpose = NoContentsLayer;
+ if (m_contentsLayer)
+ childrenChanged = true;
+ }
+
+ updateContentsImage();
+
+ // This has to happen after updateContentsImage
+ if (childrenChanged)
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::setContentsToVideo(PlatformLayer* videoLayer)
+{
+ bool childrenChanged = false;
+
+ if (videoLayer != m_contentsLayer.get())
+ childrenChanged = true;
+
+ m_contentsLayer = videoLayer;
+ m_contentsLayerPurpose = videoLayer ? ContentsLayerForVideo : NoContentsLayer;
+
+ updateContentsVideo();
+
+ // This has to happen after updateContentsVideo
+ if (childrenChanged)
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::setGeometryOrientation(CompositingCoordinatesOrientation orientation)
+{
+ if (orientation == m_geometryOrientation)
+ return;
+
+ GraphicsLayer::setGeometryOrientation(orientation);
+ updateGeometryOrientation();
+}
+
+PlatformLayer* GraphicsLayerCACF::hostLayerForSublayers() const
+{
+ return m_transformLayer ? m_transformLayer.get() : m_layer.get();
+}
+
+PlatformLayer* GraphicsLayerCACF::layerForSuperlayer() const
+{
+ return m_transformLayer ? m_transformLayer.get() : m_layer.get();
+}
+
+PlatformLayer* GraphicsLayerCACF::platformLayer() const
+{
+ return primaryLayer();
+}
+
+void GraphicsLayerCACF::setDebugBackgroundColor(const Color& color)
+{
+ if (color.isValid())
+ setLayerBackgroundColor(m_layer.get(), color);
+ else
+ clearLayerBackgroundColor(m_layer.get());
+}
+
+void GraphicsLayerCACF::setDebugBorder(const Color& color, float borderWidth)
+{
+ if (color.isValid()) {
+ setLayerBorderColor(m_layer.get(), color);
+ m_layer->setBorderWidth(borderWidth);
+ } else {
+ clearBorderColor(m_layer.get());
+ m_layer->setBorderWidth(0);
+ }
+}
+
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCACF::defaultContentsOrientation() const
+{
+ return CompositingCoordinatesTopDown;
+}
+
+void GraphicsLayerCACF::updateSublayerList()
+{
+ Vector<RefPtr<WKCACFLayer> > newSublayers;
+
+ if (m_transformLayer) {
+ // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
+ newSublayers.append(m_layer.get());
+ } else if (m_contentsLayer) {
+ // FIXME: add the contents layer in the correct order with negative z-order children.
+ // This does not cause visible rendering issues because currently contents layers are only used
+ // for replaced elements that don't have children.
+ newSublayers.append(m_contentsLayer.get());
+ }
+
+ const Vector<GraphicsLayer*>& childLayers = children();
+ size_t numChildren = childLayers.size();
+ for (size_t i = 0; i < numChildren; ++i) {
+ GraphicsLayerCACF* curChild = static_cast<GraphicsLayerCACF*>(childLayers[i]);
+
+ WKCACFLayer* childLayer = curChild->layerForSuperlayer();
+ newSublayers.append(childLayer);
+ }
+
+ for (int i = 0; i < newSublayers.size(); ++i)
+ newSublayers[i]->removeFromSuperlayer();
+
+ if (m_transformLayer) {
+ m_transformLayer->setSublayers(newSublayers);
+
+ if (m_contentsLayer) {
+ // If we have a transform layer, then the contents layer is parented in the
+ // primary layer (which is itself a child of the transform layer).
+ m_layer->removeAllSublayers();
+ m_layer->addSublayer(m_contentsLayer);
+ }
+ } else
+ m_layer->setSublayers(newSublayers);
+}
+
+void GraphicsLayerCACF::updateLayerPosition()
+{
+ // Position is offset on the layer by the layer anchor point.
+ CGPoint posPoint = CGPointMake(m_position.x() + m_anchorPoint.x() * m_size.width(),
+ m_position.y() + m_anchorPoint.y() * m_size.height());
+
+ primaryLayer()->setPosition(posPoint);
+}
+
+void GraphicsLayerCACF::updateLayerSize()
+{
+ CGRect rect = CGRectMake(0, 0, m_size.width(), m_size.height());
+ if (m_transformLayer) {
+ m_transformLayer->setBounds(rect);
+ // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
+ CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
+ m_layer->setPosition(centerPoint);
+ }
+
+ m_layer->setBounds(rect);
+
+ // Note that we don't resize m_contentsLayer. It's up the caller to do that.
+
+ // if we've changed the bounds, we need to recalculate the position
+ // of the layer, taking anchor point into account.
+ updateLayerPosition();
+}
+
+void GraphicsLayerCACF::updateAnchorPoint()
+{
+ primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
+ primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
+ updateLayerPosition();
+}
+
+void GraphicsLayerCACF::updateTransform()
+{
+ CATransform3D transform;
+ copyTransform(transform, m_transform);
+ primaryLayer()->setTransform(transform);
+}
+
+void GraphicsLayerCACF::updateChildrenTransform()
+{
+ CATransform3D transform;
+ copyTransform(transform, m_childrenTransform);
+ primaryLayer()->setSublayerTransform(transform);
+}
+
+void GraphicsLayerCACF::updateMasksToBounds()
+{
+ m_layer->setMasksToBounds(m_masksToBounds);
+ updateDebugIndicators();
+}
+
+void GraphicsLayerCACF::updateContentsOpaque()
+{
+ m_layer->setOpaque(m_contentsOpaque);
+}
+
+void GraphicsLayerCACF::updateBackfaceVisibility()
+{
+ m_layer->setDoubleSided(m_backfaceVisibility);
+}
+
+void GraphicsLayerCACF::updateLayerPreserves3D()
+{
+ if (m_preserves3D && !m_transformLayer) {
+ // Create the transform layer.
+ m_transformLayer = WKCACFLayer::create(kCACFTransformLayer, this);
+
+#ifndef NDEBUG
+ m_transformLayer->setName(String().format("Transform Layer CATransformLayer(%p) GraphicsLayer(%p)", m_transformLayer.get(), this));
+#endif
+ // Copy the position from this layer.
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+
+ CGPoint point = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
+ m_layer->setPosition(point);
+
+ m_layer->setAnchorPoint(CGPointMake(0.5f, 0.5f));
+ m_layer->setTransform(CATransform3DIdentity);
+
+ // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
+ m_layer->setOpacity(1);
+
+ // Move this layer to be a child of the transform layer.
+ if (m_layer->superlayer())
+ m_layer->superlayer()->replaceSublayer(m_layer.get(), m_transformLayer.get());
+ m_transformLayer->addSublayer(m_layer.get());
+
+ updateSublayerList();
+ } else if (!m_preserves3D && m_transformLayer) {
+ // Relace the transformLayer in the parent with this layer.
+ m_layer->removeFromSuperlayer();
+ m_transformLayer->superlayer()->replaceSublayer(m_transformLayer.get(), m_layer.get());
+
+ // Release the transform layer.
+ m_transformLayer = 0;
+
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+
+ updateSublayerList();
+ }
+
+ updateOpacityOnLayer();
+}
+
+void GraphicsLayerCACF::updateLayerDrawsContent()
+{
+ if (m_drawsContent)
+ m_layer->setNeedsDisplay();
+ else
+ m_layer->setContents(nil);
+
+ updateDebugIndicators();
+}
+
+void GraphicsLayerCACF::updateLayerBackgroundColor()
+{
+ if (!m_contentsLayer)
+ return;
+
+ // We never create the contents layer just for background color yet.
+ if (m_backgroundColorSet)
+ setLayerBackgroundColor(m_contentsLayer.get(), m_backgroundColor);
+ else
+ clearLayerBackgroundColor(m_contentsLayer.get());
+}
+
+void GraphicsLayerCACF::updateContentsImage()
+{
+ if (m_pendingContentsImage) {
+ if (!m_contentsLayer.get()) {
+ RefPtr<WKCACFLayer> imageLayer = WKCACFLayer::create(kCACFLayer, this);
+#ifndef NDEBUG
+ imageLayer->setName("Image Layer");
+#endif
+ setupContentsLayer(imageLayer.get());
+ m_contentsLayer = imageLayer;
+ // m_contentsLayer will be parented by updateSublayerList
+ }
+
+ // FIXME: maybe only do trilinear if the image is being scaled down,
+ // but then what if the layer size changes?
+ m_contentsLayer->setMinificationFilter(kCACFFilterTrilinear);
+ m_contentsLayer->setContents(m_pendingContentsImage.get());
+ m_pendingContentsImage = 0;
+
+ updateContentsRect();
+ } else {
+ // No image.
+ // m_contentsLayer will be removed via updateSublayerList.
+ m_contentsLayer = 0;
+ }
+}
+
+void GraphicsLayerCACF::updateContentsVideo()
+{
+ // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList().
+ if (m_contentsLayer) {
+ setupContentsLayer(m_contentsLayer.get());
+ updateContentsRect();
+ }
+}
+
+void GraphicsLayerCACF::updateContentsRect()
+{
+ if (!m_contentsLayer)
+ return;
+
+ CGPoint point = CGPointMake(m_contentsRect.x(),
+ m_contentsRect.y());
+ CGRect rect = CGRectMake(0.0f,
+ 0.0f,
+ m_contentsRect.width(),
+ m_contentsRect.height());
+
+ m_contentsLayer->setPosition(point);
+ m_contentsLayer->setBounds(rect);
+}
+
+void GraphicsLayerCACF::updateGeometryOrientation()
+{
+ switch (geometryOrientation()) {
+ case CompositingCoordinatesTopDown:
+ m_layer->setGeometryFlipped(false);
+ break;
+
+ case CompositingCoordinatesBottomUp:
+ m_layer->setGeometryFlipped(true);
+ break;
+ }
+ // Geometry orientation is mapped onto children transform in older QuartzCores,
+ // so is handled via setGeometryOrientation().
+}
+
+void GraphicsLayerCACF::setupContentsLayer(WKCACFLayer* contentsLayer)
+{
+ if (contentsLayer == m_contentsLayer)
+ return;
+
+ if (m_contentsLayer) {
+ m_contentsLayer->removeFromSuperlayer();
+ m_contentsLayer = 0;
+ }
+
+ if (contentsLayer) {
+ m_contentsLayer = contentsLayer;
+
+ if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) {
+ CATransform3D flipper = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ m_contentsLayer->setTransform(flipper);
+ m_contentsLayer->setAnchorPoint(CGPointMake(0.0f, 1.0f));
+ } else
+ m_contentsLayer->setAnchorPoint(CGPointMake(0.0f, 0.0f));
+
+ // Insert the content layer first. Video elements require this, because they have
+ // shadow content that must display in front of the video.
+ m_layer->insertSublayer(m_contentsLayer.get(), 0);
+
+ updateContentsRect();
+
+ if (showDebugBorders()) {
+ setLayerBorderColor(m_contentsLayer.get(), Color(0, 0, 128, 180));
+ m_contentsLayer->setBorderWidth(1.0f);
+ }
+ }
+ updateDebugIndicators();
+}
+
+// This function simply mimics the operation of GraphicsLayerCA
+void GraphicsLayerCACF::updateOpacityOnLayer()
+{
+ primaryLayer()->setOpacity(m_opacity);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.h b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
new file mode 100644
index 0000000..93ddf25
--- /dev/null
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 GraphicsLayerCACF_h_
+#define GraphicsLayerCACF_h_
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsLayer.h"
+#include "GraphicsContext.h"
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+class WKCACFLayer;
+
+class GraphicsLayerCACF : public GraphicsLayer {
+public:
+
+ GraphicsLayerCACF(GraphicsLayerClient*);
+ virtual ~GraphicsLayerCACF();
+
+ virtual void setName(const String& inName);
+
+ // for hosting this GraphicsLayer in a native layer hierarchy
+ virtual NativeLayer nativeLayer() const;
+
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
+ virtual void addChild(GraphicsLayer *layer);
+ virtual void addChildAtIndex(GraphicsLayer *layer, int index);
+ virtual void addChildAbove(GraphicsLayer *layer, GraphicsLayer *sibling);
+ virtual void addChildBelow(GraphicsLayer *layer, GraphicsLayer *sibling);
+ virtual bool replaceChild(GraphicsLayer *oldChild, GraphicsLayer *newChild);
+
+ virtual void removeFromParent();
+
+ virtual void setPosition(const FloatPoint& inPoint);
+ virtual void setAnchorPoint(const FloatPoint3D& inPoint);
+ virtual void setSize(const FloatSize& inSize);
+
+ virtual void setTransform(const TransformationMatrix&);
+
+ virtual void setChildrenTransform(const TransformationMatrix&);
+
+ virtual void setPreserves3D(bool);
+ virtual void setMasksToBounds(bool);
+ virtual void setDrawsContent(bool);
+
+ virtual void setBackgroundColor(const Color&);
+ virtual void clearBackgroundColor();
+
+ virtual void setContentsOpaque(bool);
+ virtual void setBackfaceVisibility(bool);
+
+ virtual void setOpacity(float opacity);
+
+ virtual void setNeedsDisplay();
+ virtual void setNeedsDisplayInRect(const FloatRect&);
+
+ virtual void setContentsRect(const IntRect&);
+
+ virtual void setContentsToImage(Image*);
+ virtual void setContentsToVideo(PlatformLayer*);
+
+ virtual PlatformLayer* platformLayer() const;
+
+ virtual void setDebugBackgroundColor(const Color&);
+ virtual void setDebugBorder(const Color&, float borderWidth);
+
+ virtual void setGeometryOrientation(CompositingCoordinatesOrientation);
+
+ void notifySyncRequired() { if (m_client) m_client->notifySyncRequired(this); }
+
+private:
+ void updateOpacityOnLayer();
+
+ WKCACFLayer* primaryLayer() const { return m_transformLayer.get() ? m_transformLayer.get() : m_layer.get(); }
+ WKCACFLayer* hostLayerForSublayers() const;
+ WKCACFLayer* layerForSuperlayer() const;
+
+ CompositingCoordinatesOrientation defaultContentsOrientation() const;
+ void updateSublayerList();
+ void updateLayerPosition();
+ void updateLayerSize();
+ void updateAnchorPoint();
+ void updateTransform();
+ void updateChildrenTransform();
+ void updateMasksToBounds();
+ void updateContentsOpaque();
+ void updateBackfaceVisibility();
+ void updateLayerPreserves3D();
+ void updateLayerDrawsContent();
+ void updateLayerBackgroundColor();
+
+ void updateContentsImage();
+ void updateContentsVideo();
+ void updateContentsRect();
+ void updateGeometryOrientation();
+
+ void setupContentsLayer(WKCACFLayer*);
+ WKCACFLayer* contentsLayer() const { return m_contentsLayer.get(); }
+
+ RefPtr<WKCACFLayer> m_layer;
+ RefPtr<WKCACFLayer> m_transformLayer;
+ RefPtr<WKCACFLayer> m_contentsLayer;
+
+ enum ContentsLayerPurpose {
+ NoContentsLayer = 0,
+ ContentsLayerForImage,
+ ContentsLayerForVideo
+ };
+
+ ContentsLayerPurpose m_contentsLayerPurpose;
+ bool m_contentsLayerHasBackgroundColor : 1;
+ RetainPtr<CGImageRef> m_pendingContentsImage;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // GraphicsLayerCACF_h_
diff --git a/WebCore/platform/graphics/win/IconWin.cpp b/WebCore/platform/graphics/win/IconWin.cpp
index 61f1fd3..d71ca00 100644
--- a/WebCore/platform/graphics/win/IconWin.cpp
+++ b/WebCore/platform/graphics/win/IconWin.cpp
@@ -47,20 +47,22 @@ Icon::~Icon()
DestroyIcon(m_hIcon);
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
- SHFILEINFO sfi;
- memset(&sfi, 0, sizeof(sfi));
-
- String tmpFilename = filename;
- if (!SHGetFileInfo(tmpFilename.charactersWithNullTermination(), 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SHELLICONSIZE | SHGFI_SMALLICON))
+ if (filenames.isEmpty())
return 0;
- return adoptRef(new Icon(sfi.hIcon));
-}
+ if (filenames.size() == 1) {
+ SHFILEINFO sfi;
+ memset(&sfi, 0, sizeof(sfi));
+
+ String tmpFilename = filenames[0];
+ 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>&)
-{
#if PLATFORM(WINCE)
return 0;
#else
diff --git a/WebCore/platform/graphics/win/ImageCGWin.cpp b/WebCore/platform/graphics/win/ImageCGWin.cpp
index 8a8e943..2c6d41d 100644
--- a/WebCore/platform/graphics/win/ImageCGWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCGWin.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "Image.h"
#include "BitmapImage.h"
+#include "BitmapInfo.h"
#include "GraphicsContext.h"
#include <ApplicationServices/ApplicationServices.h>
@@ -34,6 +35,30 @@
namespace WebCore {
+PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap)
+{
+ DIBSECTION dibSection;
+ if (!GetObject(hBitmap, sizeof(DIBSECTION), &dibSection))
+ return 0;
+
+ ASSERT(dibSection.dsBm.bmBitsPixel == 32);
+ if (dibSection.dsBm.bmBitsPixel != 32)
+ return 0;
+
+ ASSERT(dibSection.dsBm.bmBits);
+ if (!dibSection.dsBm.bmBits)
+ return 0;
+
+ RetainPtr<CGColorSpaceRef> deviceRGB(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGContextRef> bitmapContext(AdoptCF, CGBitmapContextCreate(dibSection.dsBm.bmBits, dibSection.dsBm.bmWidth, dibSection.dsBm.bmHeight, 8,
+ dibSection.dsBm.bmWidthBytes, deviceRGB.get(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
+
+ // The BitmapImage takes ownership of this.
+ CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext.get());
+
+ return adoptRef(new BitmapImage(cgImage));
+}
+
bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
{
ASSERT(bmp);
@@ -52,9 +77,9 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
IntSize imageSize = BitmapImage::size();
if (size)
- drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), CompositeCopy);
+ drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), DeviceColorSpace, CompositeCopy);
else
- draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), CompositeCopy);
+ draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, CompositeCopy);
// Do cleanup
CGContextRelease(cgContext);
@@ -63,7 +88,7 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
return true;
}
-void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator compositeOp)
+void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
size_t frames = frameCount();
for (size_t i = 0; i < frames; ++i) {
@@ -71,7 +96,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
if (CGImageGetHeight(image) == static_cast<size_t>(srcSize.height()) && CGImageGetWidth(image) == static_cast<size_t>(srcSize.width())) {
size_t currentFrame = m_currentFrame;
m_currentFrame = i;
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), styleColorSpace, compositeOp);
m_currentFrame = currentFrame;
return;
}
@@ -79,7 +104,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
// No image of the correct size was found, fallback to drawing the current frame
IntSize imageSize = BitmapImage::size();
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), styleColorSpace, compositeOp);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/ImageCairoWin.cpp b/WebCore/platform/graphics/win/ImageCairoWin.cpp
index 591375f..e3c5ea0 100644
--- a/WebCore/platform/graphics/win/ImageCairoWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCairoWin.cpp
@@ -28,12 +28,33 @@
#include "BitmapImage.h"
#include "GraphicsContext.h"
#include <cairo.h>
+#include <cairo-win32.h>
#include <windows.h>
#include "PlatformString.h"
namespace WebCore {
+PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap)
+{
+ DIBSECTION dibSection;
+ if (!GetObject(hBitmap, sizeof(DIBSECTION), &dibSection))
+ return 0;
+
+ ASSERT(dibSection.dsBm.bmBitsPixel == 32);
+ if (dibSection.dsBm.bmBitsPixel != 32)
+ return 0;
+
+ ASSERT(dibSection.dsBm.bmBits);
+ if (!dibSection.dsBm.bmBits)
+ return 0;
+
+ cairo_surface_t* image = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, dibSection.dsBm.bmWidth, dibSection.dsBm.bmHeight);
+
+ // The BitmapImage object takes over ownership of the cairo_surface_t*, so no need to destroy here.
+ return adoptRef(new BitmapImage(image));
+}
+
bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
{
ASSERT(bmp);
@@ -61,9 +82,9 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
IntSize imageSize = BitmapImage::size();
if (size)
- drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), CompositeCopy);
+ drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), DeviceColorSpace, CompositeCopy);
else
- draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), CompositeCopy);
+ draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, CompositeCopy);
// Do cleanup
cairo_destroy(targetRef);
@@ -71,7 +92,7 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
return true;
}
-void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator compositeOp)
+void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
size_t frames = frameCount();
for (size_t i = 0; i < frames; ++i) {
@@ -79,7 +100,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
if (cairo_image_surface_get_height(image) == static_cast<size_t>(srcSize.height()) && cairo_image_surface_get_width(image) == static_cast<size_t>(srcSize.width())) {
size_t currentFrame = m_currentFrame;
m_currentFrame = i;
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), DeviceColorSpace, compositeOp);
m_currentFrame = currentFrame;
return;
}
@@ -87,7 +108,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
// No image of the correct size was found, fallback to drawing the current frame
IntSize imageSize = BitmapImage::size();
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, compositeOp);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/IntPointWin.cpp b/WebCore/platform/graphics/win/IntPointWin.cpp
index a6ce0bb..73db199 100644
--- a/WebCore/platform/graphics/win/IntPointWin.cpp
+++ b/WebCore/platform/graphics/win/IntPointWin.cpp
@@ -23,6 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
#include "IntPoint.h"
#include <windows.h>
diff --git a/WebCore/platform/graphics/win/IntRectWin.cpp b/WebCore/platform/graphics/win/IntRectWin.cpp
index 6228be8..fe25a7f 100644
--- a/WebCore/platform/graphics/win/IntRectWin.cpp
+++ b/WebCore/platform/graphics/win/IntRectWin.cpp
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
@@ -23,6 +24,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
#include "IntRect.h"
#include <windows.h>
diff --git a/WebCore/platform/graphics/win/IntSizeWin.cpp b/WebCore/platform/graphics/win/IntSizeWin.cpp
index 8a27cdb..26e68da 100644
--- a/WebCore/platform/graphics/win/IntSizeWin.cpp
+++ b/WebCore/platform/graphics/win/IntSizeWin.cpp
@@ -23,6 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
#include "IntSize.h"
#include <windows.h>
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index eb7334e..a5beea1 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -33,6 +33,8 @@
#include "QTMovieWin.h"
#include "ScrollView.h"
#include "StringHash.h"
+#include "TimeRanges.h"
+#include "Timer.h"
#include <wtf/HashSet.h>
#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>
@@ -86,6 +88,50 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
{
}
+class TaskTimer : TimerBase {
+public:
+ static void initialize();
+
+private:
+ static void setTaskTimerDelay(double);
+ static void stopTaskTimer();
+
+ void fired();
+
+ static TaskTimer* s_timer;
+};
+
+TaskTimer* TaskTimer::s_timer = 0;
+
+void TaskTimer::initialize()
+{
+ if (s_timer)
+ return;
+
+ s_timer = new TaskTimer;
+
+ QTMovieWin::setTaskTimerFuncs(setTaskTimerDelay, stopTaskTimer);
+}
+
+void TaskTimer::setTaskTimerDelay(double delayInSeconds)
+{
+ ASSERT(s_timer);
+
+ s_timer->startOneShot(delayInSeconds);
+}
+
+void TaskTimer::stopTaskTimer()
+{
+ ASSERT(s_timer);
+
+ s_timer->stop();
+}
+
+void TaskTimer::fired()
+{
+ QTMovieWin::taskTimerFired();
+}
+
void MediaPlayerPrivate::load(const String& url)
{
if (!QTMovieWin::initializeQuickTime()) {
@@ -95,6 +141,9 @@ void MediaPlayerPrivate::load(const String& url)
return;
}
+ // Initialize the task timer.
+ TaskTimer::initialize();
+
if (m_networkState != MediaPlayer::Loading) {
m_networkState = MediaPlayer::Loading;
m_player->networkStateChanged();
@@ -241,6 +290,13 @@ bool MediaPlayerPrivate::hasVideo() const
return m_qtMovie->hasVideo();
}
+bool MediaPlayerPrivate::hasAudio() const
+{
+ if (!m_qtMovie)
+ return false;
+ return m_qtMovie->hasAudio();
+}
+
void MediaPlayerPrivate::setVolume(float volume)
{
if (!m_qtMovie)
@@ -262,16 +318,34 @@ void MediaPlayerPrivate::setPreservesPitch(bool preservesPitch)
m_qtMovie->setPreservesPitch(preservesPitch);
}
+bool MediaPlayerPrivate::hasClosedCaptions() const
+{
+ if (!m_qtMovie)
+ return false;
+ return m_qtMovie->hasClosedCaptions();
+}
+
+void MediaPlayerPrivate::setClosedCaptionsVisible(bool visible)
+{
+ if (!m_qtMovie)
+ return;
+ m_qtMovie->setClosedCaptionsVisible(visible);
+}
+
int MediaPlayerPrivate::dataRate() const
{
// This is not used at the moment
return 0;
}
-float MediaPlayerPrivate::maxTimeBuffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
+ RefPtr<TimeRanges> timeRanges = TimeRanges::create();
+ float loaded = maxTimeLoaded();
// rtsp streams are not buffered
- return m_isStreaming ? 0 : maxTimeLoaded();
+ if (!m_isStreaming && loaded > 0)
+ timeRanges->add(0, loaded);
+ return timeRanges.release();
}
float MediaPlayerPrivate::maxTimeSeekable() const
@@ -575,4 +649,3 @@ bool MediaPlayerPrivate::hasSingleSecurityOrigin() const
}
#endif
-
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
index f584148..2bccbbf 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
@@ -49,10 +49,14 @@ public:
static void registerMediaEngine(MediaEngineRegistrar);
~MediaPlayerPrivate();
-
+
+private:
+ MediaPlayerPrivate(MediaPlayer*);
+
IntSize naturalSize() const;
bool hasVideo() const;
-
+ bool hasAudio() const;
+
void load(const String& url);
void cancelLoad();
@@ -76,7 +80,7 @@ public:
MediaPlayer::NetworkState networkState() const { return m_networkState; }
MediaPlayer::ReadyState readyState() const { return m_readyState; }
- float maxTimeBuffered() const;
+ PassRefPtr<TimeRanges> buffered() const;
float maxTimeSeekable() const;
unsigned bytesLoaded() const;
bool totalBytesKnown() const;
@@ -92,8 +96,8 @@ public:
bool hasSingleSecurityOrigin() const;
-private:
- MediaPlayerPrivate(MediaPlayer*);
+ bool hasClosedCaptions() const;
+ void setClosedCaptionsVisible(bool);
void updateStates();
void doSeek();
diff --git a/WebCore/platform/graphics/win/QTMovieWin.cpp b/WebCore/platform/graphics/win/QTMovieWin.cpp
index aaa61f1..2d4c2ea 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.cpp
+++ b/WebCore/platform/graphics/win/QTMovieWin.cpp
@@ -45,6 +45,12 @@ using namespace std;
static const long minimumQuickTimeVersion = 0x07300000; // 7.3
+static const long closedCaptionTrackType = 'clcp';
+static const long subTitleTrackType = 'sbtl';
+static const long mpeg4ObjectDescriptionTrackType = 'odsm';
+static const long mpeg4SceneDescriptionTrackType = 'sdsm';
+static const long closedCaptionDisplayPropertyID = 'disp';
+
// Resizing GWorlds is slow, give them a minimum size so size of small
// videos can be animated smoothly
static const int cGWorldMinWidth = 640;
@@ -62,10 +68,13 @@ static HashSet<QTMovieWinPrivate*>* gTaskList;
static Vector<CFStringRef>* gSupportedTypes = 0;
static SInt32 quickTimeVersion = 0;
+static QTMovieWin::SetTaskTimerDelayFunc gSetTaskTimerDelay = 0;
+static QTMovieWin::StopTaskTimerFunc gStopTaskTimer = 0;
+
static void updateTaskTimer(int maxInterval = 1000)
{
if (!gTaskList->size()) {
- stopSharedTimer();
+ gStopTaskTimer();
return;
}
@@ -73,7 +82,7 @@ static void updateTaskTimer(int maxInterval = 1000)
QTGetTimeUntilNextTask(&intervalInMS, 1000);
if (intervalInMS > maxInterval)
intervalInMS = maxInterval;
- setSharedTimerFireDelay(static_cast<float>(intervalInMS) / 1000);
+ gSetTaskTimerDelay(static_cast<float>(intervalInMS) / 1000);
}
class QTMovieWinPrivate : public Noncopyable {
@@ -166,7 +175,7 @@ QTMovieWinPrivate::~QTMovieWinPrivate()
CFRelease(m_currentURL);
}
-static void taskTimerFired()
+void QTMovieWin::taskTimerFired()
{
// The hash content might change during task()
Vector<QTMovieWinPrivate*> tasks;
@@ -754,10 +763,10 @@ void QTMovieWin::disableUnsupportedTracks(unsigned& enabledTrackCount, unsigned&
allowedTrackTypes->add(SoundMediaType);
allowedTrackTypes->add(TextMediaType);
allowedTrackTypes->add(BaseMediaType);
- allowedTrackTypes->add('clcp'); // Closed caption
- allowedTrackTypes->add('sbtl'); // Subtitle
- allowedTrackTypes->add('odsm'); // MPEG-4 object descriptor stream
- allowedTrackTypes->add('sdsm'); // MPEG-4 scene description stream
+ allowedTrackTypes->add(closedCaptionTrackType);
+ allowedTrackTypes->add(subTitleTrackType);
+ allowedTrackTypes->add(mpeg4ObjectDescriptionTrackType);
+ allowedTrackTypes->add(mpeg4SceneDescriptionTrackType);
allowedTrackTypes->add(TimeCodeMediaType);
allowedTrackTypes->add(TimeCode64MediaType);
}
@@ -867,6 +876,34 @@ bool QTMovieWin::hasVideo() const
return (GetMovieIndTrackType(m_private->m_movie, 1, VisualMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly));
}
+bool QTMovieWin::hasAudio() const
+{
+ if (!m_private->m_movie)
+ return false;
+ return (GetMovieIndTrackType(m_private->m_movie, 1, AudioMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly));
+}
+
+
+bool QTMovieWin::hasClosedCaptions() const
+{
+ if (!m_private->m_movie)
+ return false;
+ return GetMovieIndTrackType(m_private->m_movie, 1, closedCaptionTrackType, movieTrackMediaType);
+}
+
+void QTMovieWin::setClosedCaptionsVisible(bool visible)
+{
+ if (!m_private->m_movie)
+ return;
+
+ Track ccTrack = GetMovieIndTrackType(m_private->m_movie, 1, closedCaptionTrackType, movieTrackMediaType);
+ if (!ccTrack)
+ return;
+
+ Boolean doDisplay = visible;
+ QTSetTrackProperty(ccTrack, closedCaptionTrackType, closedCaptionDisplayPropertyID, sizeof(doDisplay), &doDisplay);
+}
+
pascal OSErr movieDrawingCompleteProc(Movie movie, long data)
{
UppParam param;
@@ -990,6 +1027,12 @@ void QTMovieWin::getSupportedType(unsigned index, const UChar*& str, unsigned& l
}
+void QTMovieWin::setTaskTimerFuncs(SetTaskTimerDelayFunc setTaskTimerDelay, StopTaskTimerFunc stopTaskTimer)
+{
+ gSetTaskTimerDelay = setTaskTimerDelay;
+ gStopTaskTimer = stopTaskTimer;
+}
+
bool QTMovieWin::initializeQuickTime()
{
static bool initialized = false;
@@ -1009,7 +1052,6 @@ bool QTMovieWin::initializeQuickTime()
return false;
}
EnterMovies();
- setSharedTimerFiredFunction(taskTimerFired);
gMovieDrawingCompleteUPP = NewMovieDrawingCompleteUPP(movieDrawingCompleteProc);
initializationSucceeded = true;
}
@@ -1020,7 +1062,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
- setSharedTimerInstanceHandle(hinstDLL);
return TRUE;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
diff --git a/WebCore/platform/graphics/win/QTMovieWin.h b/WebCore/platform/graphics/win/QTMovieWin.h
index f46efd3..778f9aa 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.h
+++ b/WebCore/platform/graphics/win/QTMovieWin.h
@@ -59,6 +59,11 @@ class QTMOVIEWIN_API QTMovieWin {
public:
static bool initializeQuickTime();
+ typedef void (*SetTaskTimerDelayFunc)(double);
+ typedef void (*StopTaskTimerFunc)();
+ static void setTaskTimerFuncs(SetTaskTimerDelayFunc, StopTaskTimerFunc);
+ static void taskTimerFired();
+
QTMovieWin(QTMovieWinClient*);
~QTMovieWin();
@@ -91,6 +96,10 @@ public:
void setDisabled(bool);
bool hasVideo() const;
+ bool hasAudio() const;
+
+ bool hasClosedCaptions() const;
+ void setClosedCaptionsVisible(bool);
static unsigned countSupportedTypes();
static void getSupportedType(unsigned index, const UChar*& str, unsigned& len);
diff --git a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
index 0343007..e845d85 100644
--- a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
+++ b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
@@ -34,11 +34,11 @@
#include "Font.h"
#include "FontCache.h"
#include "FontDescription.h"
-#include "MathExtras.h"
#include <cairo.h>
#include <cairo-win32.h>
#include <mlang.h>
#include <tchar.h>
+#include <wtf/MathExtras.h>
namespace WebCore {
@@ -119,10 +119,4 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
return width * metricsMultiplier;
}
-void SimpleFontData::setFont(cairo_t* cr) const
-{
- ASSERT(cr);
- m_platformData.setFont(cr);
-}
-
}
diff --git a/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp b/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
new file mode 100644
index 0000000..e97b530
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WKCACFContextFlusher.h"
+
+#include <wtf/StdLibExtras.h>
+#include <QuartzCore/CACFContext.h>
+
+namespace WebCore {
+
+WKCACFContextFlusher& WKCACFContextFlusher::shared()
+{
+ DEFINE_STATIC_LOCAL(WKCACFContextFlusher, flusher, ());
+ return flusher;
+}
+
+WKCACFContextFlusher::WKCACFContextFlusher()
+{
+}
+
+WKCACFContextFlusher::~WKCACFContextFlusher()
+{
+}
+
+void WKCACFContextFlusher::addContext(CACFContextRef context)
+{
+ ASSERT(context);
+
+ m_contexts.add(context);
+ CFRetain(context);
+}
+
+void WKCACFContextFlusher::removeContext(CACFContextRef context)
+{
+ ASSERT(context);
+
+ ContextSet::iterator found = m_contexts.find(context);
+ if (found == m_contexts.end())
+ return;
+
+ CFRelease(*found);
+ m_contexts.remove(found);
+}
+
+void WKCACFContextFlusher::flushAllContexts()
+{
+ // addContext might get called beneath CACFContextFlush, and we don't want m_contexts to change while
+ // we're iterating over it, so we move the contexts into a local ContextSet and iterate over that instead.
+ ContextSet contextsToFlush;
+ contextsToFlush.swap(m_contexts);
+
+ ContextSet::const_iterator end = contextsToFlush.end();
+ for (ContextSet::const_iterator it = contextsToFlush.begin(); it != end; ++it) {
+ CACFContextRef context = *it;
+ CACFContextFlush(context);
+ CFRelease(context);
+ }
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/WKCACFContextFlusher.h b/WebCore/platform/graphics/win/WKCACFContextFlusher.h
new file mode 100644
index 0000000..9ce76aa
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFContextFlusher.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 WKCACFContextFlusher_h
+#define WKCACFContextFlusher_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <wtf/Noncopyable.h>
+
+#include <wtf/HashSet.h>
+
+typedef struct _CACFContext* CACFContextRef;
+
+namespace WebCore {
+
+class WKCACFContextFlusher : public Noncopyable {
+public:
+ static WKCACFContextFlusher& shared();
+
+ void addContext(CACFContextRef);
+ void removeContext(CACFContextRef);
+
+ void flushAllContexts();
+
+private:
+ WKCACFContextFlusher();
+ ~WKCACFContextFlusher();
+
+ typedef HashSet<CACFContextRef> ContextSet;
+ ContextSet m_contexts;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // WKCACFContextFlusher_h
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp
new file mode 100644
index 0000000..21e010d
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WKCACFLayer.h"
+
+#include "WKCACFContextFlusher.h"
+
+#include <stdio.h>
+#include <QuartzCore/CACFContext.h>
+#include <QuartzCore/CARender.h>
+
+#pragma comment(lib, "QuartzCore")
+
+namespace WebCore {
+
+using namespace std;
+
+static void displayInContext(CACFLayerRef layer, CGContextRef context)
+{
+ ASSERT_ARG(layer, WKCACFLayer::layer(layer));
+ WKCACFLayer::layer(layer)->display(context);
+}
+
+// FIXME: It might be good to have a way of ensuring that all WKCACFLayers eventually
+// get destroyed in debug builds. A static counter could accomplish this pretty easily.
+
+WKCACFLayer::WKCACFLayer(CFStringRef className, GraphicsLayerCACF* owner)
+ : m_layer(AdoptCF, CACFLayerCreate(className))
+ , m_needsDisplayOnBoundsChange(false)
+ , m_owner(owner)
+{
+ CACFLayerSetUserData(layer(), this);
+ CACFLayerSetDisplayCallback(layer(), displayInContext);
+}
+
+WKCACFLayer::~WKCACFLayer()
+{
+ // Our superlayer should be holding a reference to us, so there should be no way for us to be destroyed while we still have a superlayer.
+ ASSERT(!superlayer());
+
+ CACFLayerSetUserData(layer(), 0);
+ CACFLayerSetDisplayCallback(layer(), 0);
+}
+
+void WKCACFLayer::display(PlatformGraphicsContext* context)
+{
+ if (!m_owner)
+ return;
+
+ CGContextSaveGState(context);
+
+ CGRect layerBounds = bounds();
+ if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
+ CGContextScaleCTM(context, 1, -1);
+ CGContextTranslateCTM(context, 0, -layerBounds.size.height);
+ }
+
+ if (m_owner->client()) {
+ GraphicsContext graphicsContext(context);
+
+ // It's important to get the clip from the context, because it may be significantly
+ // smaller than the layer bounds (e.g. tiled layers)
+ CGRect clipBounds = CGContextGetClipBoundingBox(context);
+ IntRect clip(enclosingIntRect(clipBounds));
+ m_owner->paintGraphicsLayerContents(graphicsContext, clip);
+ }
+#ifndef NDEBUG
+ else {
+ ASSERT_NOT_REACHED();
+
+ // FIXME: ideally we'd avoid calling -setNeedsDisplay on a layer that is a plain color,
+ // so CA never makes backing store for it (which is what -setNeedsDisplay will do above).
+ CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 1.0f);
+ CGContextFillRect(context, layerBounds);
+ }
+#endif
+
+ if (m_owner->showRepaintCounter()) {
+ char text[16]; // that's a lot of repaints
+ _snprintf(text, sizeof(text), "%d", m_owner->incrementRepaintCount());
+
+ CGContextSaveGState(context);
+ CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f);
+
+ CGRect aBounds = layerBounds;
+
+ aBounds.size.width = 10 + 12 * strlen(text);
+ aBounds.size.height = 25;
+ CGContextFillRect(context, aBounds);
+
+ CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 1.0f);
+
+ CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0f, -1.0f));
+ CGContextSelectFont(context, "Helvetica", 25, kCGEncodingMacRoman);
+ CGContextShowTextAtPoint(context, aBounds.origin.x + 3.0f, aBounds.origin.y + 20.0f, text, strlen(text));
+
+ CGContextRestoreGState(context);
+ }
+
+ CGContextRestoreGState(context);
+}
+
+void WKCACFLayer::becomeRootLayerForContext(CACFContextRef context)
+{
+ CACFContextSetLayer(context, layer());
+ setNeedsCommit();
+}
+
+void WKCACFLayer::setNeedsCommit()
+{
+ CACFContextRef context = CACFLayerGetContext(rootLayer()->layer());
+
+ // The context might now be set yet. This happens if a property gets set
+ // before placing the layer in the tree. In this case we don't need to
+ // worry about remembering the context because we will when the layer is
+ // added to the tree.
+ if (context)
+ WKCACFContextFlusher::shared().addContext(context);
+
+ // Call notifySyncRequired(), which in this implementation plumbs through to
+ // call setRootLayerNeedsDisplay() on the WebView, which causes the CACFRenderer
+ // to render a frame.
+ if (m_owner)
+ m_owner->notifySyncRequired();
+}
+
+void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
+{
+ insertSublayer(sublayer, numSublayers());
+}
+
+void WKCACFLayer::insertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
+{
+ index = min(index, numSublayers());
+ CACFLayerInsertSublayer(layer(), sublayer->layer(), index);
+ setNeedsCommit();
+}
+
+void WKCACFLayer::insertSublayerAboveLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
+{
+ if (!reference) {
+ insertSublayer(sublayer, 0);
+ return;
+ }
+
+ int referenceIndex = indexOfSublayer(reference);
+ if (referenceIndex == -1) {
+ addSublayer(sublayer);
+ return;
+ }
+
+ insertSublayer(sublayer, referenceIndex + 1);
+}
+
+void WKCACFLayer::insertSublayerBelowLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
+{
+ if (!reference) {
+ insertSublayer(sublayer, 0);
+ return;
+ }
+
+ int referenceIndex = indexOfSublayer(reference);
+ if (referenceIndex == -1) {
+ addSublayer(sublayer);
+ return;
+ }
+
+ insertSublayer(sublayer, referenceIndex);
+}
+
+void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer> newLayer)
+{
+ ASSERT_ARG(reference, reference);
+ ASSERT_ARG(reference, reference->superlayer() == this);
+
+ if (reference == newLayer)
+ return;
+
+ if (!newLayer) {
+ removeSublayer(reference);
+ return;
+ }
+
+ newLayer->removeFromSuperlayer();
+
+ int referenceIndex = indexOfSublayer(reference);
+ ASSERT(referenceIndex != -1);
+ if (referenceIndex == -1)
+ return;
+
+ // FIXME: Can we make this more efficient? The current CACF API doesn't seem to give us a way to do so.
+ reference->removeFromSuperlayer();
+ insertSublayer(newLayer, referenceIndex);
+}
+
+void WKCACFLayer::removeFromSuperlayer()
+{
+ WKCACFLayer* superlayer = this->superlayer();
+ if (!superlayer)
+ return;
+
+ superlayer->removeSublayer(this);
+ CACFLayerRemoveFromSuperlayer(layer());
+ superlayer->setNeedsCommit();
+}
+
+void WKCACFLayer::removeSublayer(const WKCACFLayer* sublayer)
+{
+ int foundIndex = indexOfSublayer(sublayer);
+ if (foundIndex == -1)
+ return;
+
+ CACFLayerRemoveFromSuperlayer(sublayer->layer());
+ setNeedsCommit();
+}
+
+int WKCACFLayer::indexOfSublayer(const WKCACFLayer* reference)
+{
+ CACFLayerRef ref = reference->layer();
+ if (!ref)
+ return -1;
+
+ CFArrayRef sublayers = CACFLayerGetSublayers(layer());
+ size_t n = CFArrayGetCount(sublayers);
+
+ for (size_t i = 0; i < n; ++i)
+ if (CFArrayGetValueAtIndex(sublayers, i) == ref)
+ return i;
+
+ return -1;
+}
+
+WKCACFLayer* WKCACFLayer::ancestorOrSelfWithSuperlayer(WKCACFLayer* superlayer) const
+{
+ WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
+ for (WKCACFLayer* ancestor = this->superlayer(); ancestor; layer = ancestor, ancestor = ancestor->superlayer()) {
+ if (ancestor == superlayer)
+ return layer;
+ }
+ return 0;
+}
+
+void WKCACFLayer::setBounds(const CGRect& rect)
+{
+ if (CGRectEqualToRect(rect, bounds()))
+ return;
+
+ CACFLayerSetBounds(layer(), rect);
+ setNeedsCommit();
+
+ if (m_needsDisplayOnBoundsChange)
+ setNeedsDisplay();
+}
+
+void WKCACFLayer::setFrame(const CGRect& rect)
+{
+ CGRect oldFrame = frame();
+ if (CGRectEqualToRect(rect, oldFrame))
+ return;
+
+ CACFLayerSetFrame(layer(), rect);
+ setNeedsCommit();
+
+ if (m_needsDisplayOnBoundsChange)
+ setNeedsDisplay();
+}
+
+WKCACFLayer* WKCACFLayer::rootLayer() const
+{
+ WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
+ for (WKCACFLayer* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
+ return layer;
+}
+
+void WKCACFLayer::removeAllSublayers()
+{
+ CACFLayerSetSublayers(layer(), 0);
+ setNeedsCommit();
+}
+
+void WKCACFLayer::setSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
+{
+ if (sublayers.isEmpty())
+ CACFLayerSetSublayers(layer(), 0);
+ else {
+ // Create a vector of CACFLayers.
+ Vector<const void*> layers;
+ for (size_t i = 0; i < sublayers.size(); i++)
+ layers.append(sublayers[i]->layer());
+
+ RetainPtr<CFArrayRef> layersArray(AdoptCF, CFArrayCreate(0, layers.data(), layers.size(), 0));
+ CACFLayerSetSublayers(layer(), layersArray.get());
+ }
+
+ setNeedsCommit();
+}
+
+void WKCACFLayer::moveSublayers(WKCACFLayer* fromLayer, WKCACFLayer* toLayer)
+{
+ if (!fromLayer || !toLayer)
+ return;
+
+ CACFLayerSetSublayers(toLayer->layer(), CACFLayerGetSublayers(fromLayer->layer()));
+ fromLayer->setNeedsCommit();
+ toLayer->setNeedsCommit();
+}
+
+WKCACFLayer* WKCACFLayer::superlayer() const
+{
+ CACFLayerRef super = CACFLayerGetSuperlayer(layer());
+ if (!super)
+ return 0;
+ return WKCACFLayer::layer(super);
+}
+
+void WKCACFLayer::setNeedsDisplay(const CGRect& dirtyRect)
+{
+ if (m_owner)
+ CACFLayerSetNeedsDisplay(layer(), &dirtyRect);
+ setNeedsCommit();
+}
+
+void WKCACFLayer::setNeedsDisplay()
+{
+ if (m_owner)
+ CACFLayerSetNeedsDisplay(layer(), 0);
+ setNeedsCommit();
+}
+
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h
new file mode 100644
index 0000000..6655f7a
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFLayer.h
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 WKCACFLayer_h
+#define WKCACFLayer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "StringHash.h"
+
+#include <wtf/RefCounted.h>
+
+#include <QuartzCore/CACFLayer.h>
+#include <QuartzCore/CACFVector.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+
+#include "GraphicsContext.h"
+#include "GraphicsLayerCACF.h"
+#include "PlatformString.h"
+#include "TransformationMatrix.h"
+
+namespace WebCore {
+
+class WKCACFAnimation;
+class WKCACFTimingFunction;
+
+class WKCACFLayer : public RefCounted<WKCACFLayer> {
+public:
+ static PassRefPtr<WKCACFLayer> create(CFStringRef className, GraphicsLayerCACF* owner = 0) { return adoptRef(new WKCACFLayer(className, owner)); }
+ static WKCACFLayer* layer(CACFLayerRef layer) { return static_cast<WKCACFLayer*>(CACFLayerGetUserData(layer)); }
+
+ ~WKCACFLayer();
+
+ // Makes this layer the root when the passed context is rendered
+ void becomeRootLayerForContext(CACFContextRef);
+
+ static RetainPtr<CFTypeRef> cfValue(float value) { return RetainPtr<CFTypeRef>(AdoptCF, CFNumberCreate(0, kCFNumberFloat32Type, &value)); }
+ static RetainPtr<CFTypeRef> cfValue(const TransformationMatrix& value)
+ {
+ CATransform3D t;
+ t.m11 = value.m11();
+ t.m12 = value.m12();
+ t.m13 = value.m13();
+ t.m14 = value.m14();
+ t.m21 = value.m21();
+ t.m22 = value.m22();
+ t.m23 = value.m23();
+ t.m24 = value.m24();
+ t.m31 = value.m31();
+ t.m32 = value.m32();
+ t.m33 = value.m33();
+ t.m34 = value.m34();
+ t.m41 = value.m41();
+ t.m42 = value.m42();
+ t.m43 = value.m43();
+ t.m44 = value.m44();
+ return RetainPtr<CFTypeRef>(AdoptCF, CACFVectorCreateTransform(t));
+ }
+ static RetainPtr<CFTypeRef> cfValue(const FloatPoint& value)
+ {
+ CGPoint p;
+ p.x = value.x(); p.y = value.y();
+ return RetainPtr<CFTypeRef>(AdoptCF, CACFVectorCreatePoint(p));
+ }
+ static RetainPtr<CFTypeRef> cfValue(const FloatRect& rect)
+ {
+ CGRect r;
+ r.origin.x = rect.x();
+ r.origin.y = rect.y();
+ r.size.width = rect.width();
+ r.size.height = rect.height();
+ CGFloat v[4] = { CGRectGetMinX(r), CGRectGetMinY(r), CGRectGetMaxX(r), CGRectGetMaxY(r) };
+ return RetainPtr<CFTypeRef>(AdoptCF, CACFVectorCreate(4, v));
+ }
+ static RetainPtr<CFTypeRef> cfValue(const Color& color)
+ {
+ return RetainPtr<CFTypeRef>(AdoptCF, CGColorCreateGenericRGB(color.red(), color.green(), color.blue(), color.alpha()));
+ }
+
+ void display(PlatformGraphicsContext*);
+
+ bool isTransformLayer() const { return CACFLayerGetClass(layer()) == kCACFTransformLayer; }
+
+ void addSublayer(PassRefPtr<WKCACFLayer> sublayer);
+ void insertSublayer(PassRefPtr<WKCACFLayer>, size_t index);
+ void insertSublayerAboveLayer(PassRefPtr<WKCACFLayer>, const WKCACFLayer* reference);
+ void insertSublayerBelowLayer(PassRefPtr<WKCACFLayer>, const WKCACFLayer* reference);
+ void replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer>);
+ void removeFromSuperlayer();
+ static void moveSublayers(WKCACFLayer* fromLayer, WKCACFLayer* toLayer);
+
+ WKCACFLayer* ancestorOrSelfWithSuperlayer(WKCACFLayer*) const;
+
+ void setAnchorPoint(const CGPoint& p) { CACFLayerSetAnchorPoint(layer(), p); setNeedsCommit(); }
+ CGPoint anchorPoint() const { return CACFLayerGetAnchorPoint(layer()); }
+
+ void setAnchorPointZ(CGFloat z) { CACFLayerSetAnchorPointZ(layer(), z); setNeedsCommit(); }
+ CGFloat anchorPointZ() const { return CACFLayerGetAnchorPointZ(layer()); }
+
+ void setBackgroundColor(CGColorRef color) { CACFLayerSetBackgroundColor(layer(), color); setNeedsCommit(); }
+ CGColorRef backgroundColor() const { return CACFLayerGetBackgroundColor(layer()); }
+
+ void setBorderColor(CGColorRef color) { CACFLayerSetBorderColor(layer(), color); setNeedsCommit(); }
+ CGColorRef borderColor() const { return CACFLayerGetBorderColor(layer()); }
+
+ void setBorderWidth(CGFloat width) { CACFLayerSetBorderWidth(layer(), width); setNeedsCommit(); }
+ CGFloat borderWidth() const { return CACFLayerGetBorderWidth(layer()); }
+
+ void setBounds(const CGRect&);
+ CGRect bounds() const { return CACFLayerGetBounds(layer()); }
+
+ void setClearsContext(bool clears) { CACFLayerSetClearsContext(layer(), clears); setNeedsCommit(); }
+ bool clearsContext() const { return CACFLayerGetClearsContext(layer()); }
+
+ void setContents(CGImageRef contents) { CACFLayerSetContents(layer(), contents); setNeedsCommit(); }
+ CGImageRef contents() const { return static_cast<CGImageRef>(const_cast<void*>(CACFLayerGetContents(layer()))); }
+
+ void setContentsRect(const CGRect& contentsRect) { CACFLayerSetContentsRect(layer(), contentsRect); setNeedsCommit(); }
+ CGRect contentsRect() const { return CACFLayerGetContentsRect(layer()); }
+
+ void setContentsGravity(CFStringRef str) { CACFLayerSetContentsGravity(layer(), str); setNeedsCommit(); }
+ CFStringRef contentsGravity() const { return CACFLayerGetContentsGravity(layer()); }
+
+ void setDoubleSided(bool b) { CACFLayerSetDoubleSided(layer(), b); setNeedsCommit(); }
+ bool doubleSided() const { return CACFLayerIsDoubleSided(layer()); }
+
+ void setEdgeAntialiasingMask(uint32_t mask) { CACFLayerSetEdgeAntialiasingMask(layer(), mask); setNeedsCommit(); }
+ uint32_t edgeAntialiasingMask() const { return CACFLayerGetEdgeAntialiasingMask(layer()); }
+
+ void setFilters(CFArrayRef filters) { CACFLayerSetFilters(layer(), filters); setNeedsCommit(); }
+ CFArrayRef filters() const { return CACFLayerGetFilters(layer()); }
+
+ void setFrame(const CGRect&);
+ CGRect frame() const { return CACFLayerGetFrame(layer()); }
+
+ void setHidden(bool hidden) { CACFLayerSetHidden(layer(), hidden); setNeedsCommit(); }
+ bool isHidden() const { return CACFLayerIsHidden(layer()); }
+
+ void setMasksToBounds(bool b) { CACFLayerSetMasksToBounds(layer(), b); }
+ bool masksToBounds() const { return CACFLayerGetMasksToBounds(layer()); }
+
+ void setMagnificationFilter(const String& string) { CACFLayerSetMagnificationFilter(layer(), RetainPtr<CFStringRef>(AdoptCF, string.createCFString()).get()); }
+ String magnificationFilter() const { return CACFLayerGetMagnificationFilter(layer()); }
+
+ void setMinificationFilter(const String& string) { CACFLayerSetMinificationFilter(layer(), RetainPtr<CFStringRef>(AdoptCF, string.createCFString()).get()); }
+ String minificationFilter() const { return CACFLayerGetMinificationFilter(layer()); }
+
+ void setMinificationFilterBias(float bias) { CACFLayerSetMinificationFilterBias(layer(), bias); }
+ float minificationFilterBias() const { return CACFLayerGetMinificationFilterBias(layer()); }
+
+ void setName(const String& name) { CACFLayerSetName(layer(), RetainPtr<CFStringRef>(AdoptCF, name.createCFString()).get()); }
+ String name() const { return CACFLayerGetName(layer()); }
+
+ void setNeedsDisplay(const CGRect& dirtyRect);
+ void setNeedsDisplay();
+
+ void setNeedsDisplayOnBoundsChange(bool needsDisplay) { m_needsDisplayOnBoundsChange = needsDisplay; }
+
+ void setOpacity(float opacity) { CACFLayerSetOpacity(layer(), opacity); setNeedsCommit(); }
+ float opacity() const { return CACFLayerGetOpacity(layer()); }
+
+ void setOpaque(bool b) { CACFLayerSetOpaque(layer(), b); setNeedsCommit(); }
+ bool opaque() const { return CACFLayerIsOpaque(layer()); }
+
+ void setPosition(const CGPoint& position) { CACFLayerSetPosition(layer(), position); setNeedsCommit(); }
+ CGPoint position() const { return CACFLayerGetPosition(layer()); }
+
+ void setZPosition(CGFloat position) { CACFLayerSetZPosition(layer(), position); setNeedsCommit(); }
+ CGFloat zPosition() const { return CACFLayerGetZPosition(layer()); }
+
+ void setSpeed(float speed) { CACFLayerSetSpeed(layer(), speed); }
+ CFTimeInterval speed() const { CACFLayerGetSpeed(layer()); }
+
+ void setTimeOffset(CFTimeInterval t) { CACFLayerSetTimeOffset(layer(), t); }
+ CFTimeInterval timeOffset() const { CACFLayerGetTimeOffset(layer()); }
+
+ WKCACFLayer* rootLayer() const;
+
+ void setSortsSublayers(bool sorts) { CACFLayerSetSortsSublayers(layer(), sorts); setNeedsCommit(); }
+ bool sortsSublayers() const { return CACFLayerGetSortsSublayers(layer()); }
+
+ void removeAllSublayers();
+
+ void setSublayers(const Vector<RefPtr<WKCACFLayer> >&);
+
+ void setSublayerTransform(const CATransform3D& transform) { CACFLayerSetSublayerTransform(layer(), transform); setNeedsCommit(); }
+ CATransform3D sublayerTransform() const { return CACFLayerGetSublayerTransform(layer()); }
+
+ WKCACFLayer* superlayer() const;
+
+ void setTransform(const CATransform3D& transform) { CACFLayerSetTransform(layer(), transform); setNeedsCommit(); }
+ CATransform3D transform() const { return CACFLayerGetTransform(layer()); }
+
+ void setGeometryFlipped(bool flipped) { CACFLayerSetGeometryFlipped(layer(), flipped); setNeedsCommit(); }
+ bool geometryFlipped() const { return CACFLayerIsGeometryFlipped(layer()); }
+
+ WKCACFLayer(CFStringRef className, GraphicsLayerCACF* owner);
+
+private:
+ void setNeedsCommit();
+ CACFLayerRef layer() const { return m_layer.get(); }
+ size_t numSublayers() const
+ {
+ CFArrayRef sublayers = CACFLayerGetSublayers(layer());
+ return sublayers ? CFArrayGetCount(sublayers) : 0;
+ }
+
+ // Returns the index of the passed layer in this layer's sublayers list
+ // or -1 if not found
+ int indexOfSublayer(const WKCACFLayer*);
+
+ // This should only be called from removeFromSuperlayer.
+ void removeSublayer(const WKCACFLayer*);
+
+ RetainPtr<CACFLayerRef> m_layer;
+ bool m_needsDisplayOnBoundsChange;
+ GraphicsLayerCACF* m_owner;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // WKCACFLayer_h
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
new file mode 100644
index 0000000..9fbd0fc
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WKCACFLayerRenderer.h"
+
+#include "WKCACFContextFlusher.h"
+#include "WKCACFLayer.h"
+#include <CoreGraphics/CGSRegion.h>
+#include <QuartzCore/CACFContext.h>
+#include <QuartzCore/CARenderOGL.h>
+#include <wtf/HashMap.h>
+#include <wtf/OwnArrayPtr.h>
+#include <d3d9.h>
+#include <d3dx9.h>
+#include <dxerr9.h>
+
+#pragma comment(lib, "d3d9")
+#pragma comment(lib, "d3dx9")
+#pragma comment(lib, "QuartzCore")
+
+static IDirect3D9* s_d3d = 0;
+static IDirect3D9* d3d()
+{
+ if (s_d3d)
+ return s_d3d;
+
+ if (!LoadLibrary(TEXT("d3d9.dll")))
+ return 0;
+
+ s_d3d = Direct3DCreate9(D3D_SDK_VERSION);
+
+ return s_d3d;
+}
+
+inline static CGRect winRectToCGRect(RECT rc)
+{
+ return CGRectMake(rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top));
+}
+
+inline static CGRect winRectToCGRect(RECT rc, RECT relativeToRect)
+{
+ return CGRectMake(rc.left, (relativeToRect.bottom-rc.bottom), (rc.right - rc.left), (rc.bottom - rc.top));
+}
+
+namespace WebCore {
+
+typedef HashMap<CACFContextRef, WKCACFLayerRenderer*> ContextToWindowMap;
+
+static ContextToWindowMap& windowsForContexts()
+{
+ DEFINE_STATIC_LOCAL(ContextToWindowMap, map, ());
+ return map;
+}
+
+static D3DPRESENT_PARAMETERS initialPresentationParameters()
+{
+ D3DPRESENT_PARAMETERS parameters = {0};
+ parameters.Windowed = TRUE;
+ parameters.SwapEffect = D3DSWAPEFFECT_COPY;
+ parameters.BackBufferCount = 1;
+ parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
+ parameters.MultiSampleType = D3DMULTISAMPLE_NONE;
+
+ return parameters;
+}
+
+bool WKCACFLayerRenderer::acceleratedCompositingAvailable()
+{
+ static bool available;
+ static bool tested;
+
+ if (tested)
+ return available;
+
+ tested = true;
+ HMODULE library = LoadLibrary(TEXT("d3d9.dll"));
+ if (!library)
+ return false;
+
+ FreeLibrary(library);
+ library = LoadLibrary(TEXT("QuartzCore.dll"));
+ if (!library)
+ return false;
+
+ FreeLibrary(library);
+ available = true;
+ return available;
+}
+
+void WKCACFLayerRenderer::didFlushContext(CACFContextRef context)
+{
+ WKCACFLayerRenderer* window = windowsForContexts().get(context);
+ if (!window)
+ return;
+
+ window->renderSoon();
+}
+
+PassOwnPtr<WKCACFLayerRenderer> WKCACFLayerRenderer::create()
+{
+ if (!acceleratedCompositingAvailable())
+ return 0;
+ return new WKCACFLayerRenderer;
+}
+
+WKCACFLayerRenderer::WKCACFLayerRenderer()
+ : m_triedToCreateD3DRenderer(false)
+ , m_renderContext(0)
+ , m_renderer(0)
+ , m_hostWindow(0)
+ , m_renderTimer(this, &WKCACFLayerRenderer::renderTimerFired)
+ , m_scrollFrameWidth(1) // Default to 1 to avoid 0 size frames
+ , m_scrollFrameHeight(1) // Default to 1 to avoid 0 size frames
+{
+}
+
+WKCACFLayerRenderer::~WKCACFLayerRenderer()
+{
+ destroyRenderer();
+}
+
+void WKCACFLayerRenderer::setScrollFrame(int width, int height, int scrollX, int scrollY)
+{
+ m_scrollFrameWidth = width;
+ m_scrollFrameHeight = height;
+
+ CGRect contentsRect = CGRectMake(scrollX, scrollY, width, height);
+ m_scrollLayer->setFrame(contentsRect);
+
+ if (m_rootChildLayer) {
+ contentsRect.origin.x = 0;
+ contentsRect.origin.y = 0;
+ m_rootChildLayer->setFrame(contentsRect);
+ }
+}
+
+void WKCACFLayerRenderer::setRootContents(CGImageRef image)
+{
+ ASSERT(m_rootLayer);
+ m_rootLayer->setContents(image);
+ renderSoon();
+}
+
+void WKCACFLayerRenderer::setRootChildLayer(WebCore::PlatformLayer* layer)
+{
+ if (!m_scrollLayer)
+ return;
+
+ m_scrollLayer->removeAllSublayers();
+ if (layer) {
+ m_scrollLayer->addSublayer(layer);
+
+ // Set the frame
+ layer->setFrame(CGRectMake(0, 0, m_scrollFrameWidth, m_scrollFrameHeight));
+ }
+
+ m_rootChildLayer = layer;
+
+}
+
+void WKCACFLayerRenderer::setNeedsDisplay()
+{
+ ASSERT(m_rootLayer);
+ m_rootLayer->setNeedsDisplay();
+ renderSoon();
+}
+
+void WKCACFLayerRenderer::createRenderer()
+{
+ if (m_triedToCreateD3DRenderer)
+ return;
+
+ m_triedToCreateD3DRenderer = true;
+ D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
+
+ if (!d3d() || !::IsWindow(m_hostWindow))
+ return;
+
+ // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the
+ // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero
+ // size eventually, and then the backbuffer size will get reset.
+ RECT rect;
+ GetClientRect(m_hostWindow, &rect);
+
+ if (rect.left-rect.right == 0 || rect.bottom-rect.top == 0) {
+ parameters.BackBufferWidth = 1;
+ parameters.BackBufferHeight = 1;
+ }
+
+ if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &parameters, &m_d3dDevice)))
+ return;
+
+ D3DXMATRIXA16 projection;
+ D3DXMatrixOrthoOffCenterRH(&projection, rect.left, rect.right, rect.top, rect.bottom, -1.0f, 1.0f);
+
+ m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
+
+ m_context.adoptCF(CACFContextCreate(0));
+ windowsForContexts().set(m_context.get(), this);
+
+ m_renderContext = static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get()));
+ m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0);
+
+ // Create the root hierarchy
+ m_rootLayer = WKCACFLayer::create(kCACFLayer);
+ m_scrollLayer = WKCACFLayer::create(kCACFLayer);
+
+ m_rootLayer->addSublayer(m_scrollLayer);
+ m_scrollLayer->setMasksToBounds(true);
+
+#ifndef NDEBUG
+ CGColorRef debugColor = createCGColor(Color(255, 0, 0, 204));
+ m_rootLayer->setBackgroundColor(debugColor);
+ CGColorRelease(debugColor);
+#endif
+
+ if (IsWindow(m_hostWindow)) {
+ m_rootLayer->setFrame(bounds());
+
+ // For now this will include the scroll bars. Later in the setScrollFrame
+ // we will fix it
+ m_scrollLayer->setFrame(bounds());
+ }
+
+ if (m_context)
+ m_rootLayer->becomeRootLayerForContext(m_context.get());
+}
+
+void WKCACFLayerRenderer::destroyRenderer()
+{
+ if (m_context) {
+ windowsForContexts().remove(m_context.get());
+ WKCACFContextFlusher::shared().removeContext(m_context.get());
+ }
+
+ if (m_renderer)
+ CARenderOGLDestroy(m_renderer);
+ m_renderer = 0;
+ m_d3dDevice = 0;
+ if (s_d3d)
+ s_d3d->Release();
+
+ s_d3d = 0;
+ m_rootLayer = 0;
+ m_scrollLayer = 0;
+ m_rootChildLayer = 0;
+
+ m_triedToCreateD3DRenderer = false;
+}
+
+void WKCACFLayerRenderer::resize()
+{
+ if (!m_d3dDevice)
+ return;
+
+ resetDevice();
+
+ if (m_rootLayer) {
+ m_rootLayer->setFrame(bounds());
+ WKCACFContextFlusher::shared().flushAllContexts();
+ }
+}
+
+static void getDirtyRects(HWND window, Vector<CGRect>& outRects)
+{
+ ASSERT_ARG(outRects, outRects.isEmpty());
+
+ RECT clientRect;
+ if (!GetClientRect(window, &clientRect))
+ return;
+
+ HRGN region = CreateRectRgn(0, 0, 0, 0);
+ int regionType = GetUpdateRgn(window, region, false);
+ if (regionType != COMPLEXREGION) {
+ RECT dirtyRect;
+ if (GetUpdateRect(window, &dirtyRect, false))
+ outRects.append(winRectToCGRect(dirtyRect, clientRect));
+ return;
+ }
+
+ DWORD dataSize = GetRegionData(region, 0, 0);
+ OwnArrayPtr<unsigned char> regionDataBuffer(new unsigned char[dataSize]);
+ RGNDATA* regionData = reinterpret_cast<RGNDATA*>(regionDataBuffer.get());
+ if (!GetRegionData(region, dataSize, regionData))
+ return;
+
+ outRects.resize(regionData->rdh.nCount);
+
+ RECT* rect = reinterpret_cast<RECT*>(regionData->Buffer);
+ for (size_t i = 0; i < outRects.size(); ++i, ++rect)
+ outRects[i] = winRectToCGRect(*rect, clientRect);
+
+ DeleteObject(region);
+}
+
+void WKCACFLayerRenderer::renderTimerFired(Timer<WKCACFLayerRenderer>*)
+{
+ paint();
+}
+
+void WKCACFLayerRenderer::paint()
+{
+ if (!m_d3dDevice)
+ return;
+
+ Vector<CGRect> dirtyRects;
+ getDirtyRects(m_hostWindow, dirtyRects);
+ render(dirtyRects);
+}
+
+void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects)
+{
+ ASSERT(m_d3dDevice);
+
+ // Flush the root layer to the render tree.
+ WKCACFContextFlusher::shared().flushAllContexts();
+
+ CGRect bounds = this->bounds();
+
+ CFTimeInterval t = CACurrentMediaTime();
+
+ // Give the renderer some space to use. This needs to be valid until the
+ // CARenderUpdateFinish() call below.
+ char space[4096];
+ CARenderUpdate* u = CARenderUpdateBegin(space, sizeof(space), t, 0, 0, &bounds);
+ if (!u)
+ return;
+
+ CARenderContextLock(m_renderContext);
+ CARenderUpdateAddContext(u, m_renderContext);
+ CARenderContextUnlock(m_renderContext);
+
+ for (size_t i = 0; i < dirtyRects.size(); ++i)
+ CARenderUpdateAddRect(u, &dirtyRects[i]);
+
+ HRESULT err = S_OK;
+ do {
+ CGSRegionObj rgn = CARenderUpdateCopyRegion(u);
+
+ if (!rgn)
+ break;
+
+ // FIXME: don't need to clear dirty region if layer tree is opaque.
+
+ Vector<D3DRECT, 64> rects;
+ CGSRegionEnumeratorObj e = CGSRegionEnumerator(rgn);
+ for (const CGRect* r = CGSNextRect(e); r; r = CGSNextRect(e)) {
+ D3DRECT rect;
+ rect.x1 = r->origin.x;
+ rect.x2 = rect.x1 + r->size.width;
+ rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height);
+ rect.y2 = rect.y1 + r->size.height;
+
+ rects.append(rect);
+ }
+ CGSReleaseRegionEnumerator(e);
+ CGSReleaseRegion(rgn);
+
+ if (rects.isEmpty())
+ break;
+
+ m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0);
+
+ m_d3dDevice->BeginScene();
+ CARenderOGLRender(m_renderer, u);
+ m_d3dDevice->EndScene();
+
+ err = m_d3dDevice->Present(0, 0, 0, 0);
+
+ if (err == D3DERR_DEVICELOST) {
+ // Lost device situation.
+ CARenderOGLPurge(m_renderer);
+ resetDevice();
+ CARenderUpdateAddRect(u, &bounds);
+ }
+ } while (err == D3DERR_DEVICELOST);
+
+ CARenderUpdateFinish(u);
+}
+
+void WKCACFLayerRenderer::renderSoon()
+{
+ if (!m_renderTimer.isActive())
+ m_renderTimer.startOneShot(0);
+}
+
+CGRect WKCACFLayerRenderer::bounds() const
+{
+ RECT clientRect;
+ GetClientRect(m_hostWindow, &clientRect);
+
+ return winRectToCGRect(clientRect);
+}
+
+void WKCACFLayerRenderer::initD3DGeometry()
+{
+ ASSERT(m_d3dDevice);
+
+ CGRect bounds = this->bounds();
+
+ float x0 = bounds.origin.x;
+ float y0 = bounds.origin.y;
+ float x1 = x0 + bounds.size.width;
+ float y1 = y0 + bounds.size.height;
+
+ D3DXMATRIXA16 projection;
+ D3DXMatrixOrthoOffCenterRH(&projection, x0, x1, y0, y1, -1.0f, 1.0f);
+
+ m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
+}
+
+void WKCACFLayerRenderer::resetDevice()
+{
+ ASSERT(m_d3dDevice);
+
+ D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
+ m_d3dDevice->Reset(&parameters);
+ initD3DGeometry();
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
new file mode 100644
index 0000000..12cde48
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 WKCACFLayerRenderer_h
+#define WKCACFLayerRenderer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "COMPtr.h"
+#include "Timer.h"
+#include "WKCACFLayer.h"
+
+#include <wtf/Noncopyable.h>
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/RetainPtr.h>
+
+#include <CoreGraphics/CGGeometry.h>
+
+interface IDirect3DDevice9;
+typedef struct _CACFContext* CACFContextRef;
+typedef struct _CARenderContext CARenderContext;
+typedef struct _CARenderOGLContext CARenderOGLContext;
+
+namespace WebCore {
+
+// FIXME: Currently there is a WKCACFLayerRenderer for each WebView and each
+// has its own CARenderOGLContext and Direct3DDevice9, which is inefficient.
+// (https://bugs.webkit.org/show_bug.cgi?id=31855)
+class WKCACFLayerRenderer : public Noncopyable {
+public:
+ static PassOwnPtr<WKCACFLayerRenderer> create();
+ ~WKCACFLayerRenderer();
+
+ static bool acceleratedCompositingAvailable();
+ static void didFlushContext(CACFContextRef);
+
+ void setScrollFrame(int width, int height, int scrollX, int scrollY);
+ void setRootContents(CGImageRef);
+ void setRootChildLayer(WebCore::PlatformLayer* layer);
+ void setNeedsDisplay();
+ void setHostWindow(HWND window) { m_hostWindow = window; createRenderer(); }
+
+ void createRenderer();
+ void destroyRenderer();
+ void resize();
+ void renderSoon();
+
+protected:
+ WKCACFLayer* rootLayer() const { return m_rootLayer.get(); }
+
+private:
+ WKCACFLayerRenderer();
+
+ void renderTimerFired(Timer<WKCACFLayerRenderer>*);
+
+ CGRect bounds() const;
+
+ void initD3DGeometry();
+ void resetDevice();
+
+ void render(const Vector<CGRect>& dirtyRects = Vector<CGRect>());
+ void paint();
+
+ bool m_triedToCreateD3DRenderer;
+ COMPtr<IDirect3DDevice9> m_d3dDevice;
+ RefPtr<WKCACFLayer> m_rootLayer;
+ RefPtr<WKCACFLayer> m_viewLayer;
+ RefPtr<WKCACFLayer> m_scrollLayer;
+ RefPtr<WKCACFLayer> m_rootChildLayer;
+ RetainPtr<CACFContextRef> m_context;
+ CARenderContext* m_renderContext;
+ CARenderOGLContext* m_renderer;
+ HWND m_hostWindow;
+ Timer<WKCACFLayerRenderer> m_renderTimer;
+ int m_scrollFrameWidth, m_scrollFrameHeight;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // WKCACFLayerRenderer_h
diff --git a/WebCore/platform/graphics/wince/ColorWince.cpp b/WebCore/platform/graphics/wince/ColorWince.cpp
new file mode 100644
index 0000000..820b9d2
--- /dev/null
+++ b/WebCore/platform/graphics/wince/ColorWince.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007-2008 Torch Mobile, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Color.h"
+
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+Color focusRingColor()
+{
+ return Color(0, 0, 0);
+}
+
+void setFocusRingColorChangeFunction(void (*)())
+{
+ notImplemented();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
index 7c6853c..699ff25 100644
--- a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
@@ -33,6 +33,11 @@ static CustomFontCache* g_customFontCache = 0;
bool renameFont(SharedBuffer* fontData, const String& fontName);
+void setCustomFontCache(CustomFontCache* cache)
+{
+ g_customFontCache = cache;
+}
+
FontCustomPlatformData::~FontCustomPlatformData()
{
if (g_customFontCache && !m_name.isEmpty())
@@ -66,11 +71,12 @@ static String createUniqueFontName()
return fontName.replace('/', '_');
}
-FontCustomPlatformData* createFontCustomPlatformData(CachedFont* cachedFont)
+FontCustomPlatformData* createFontCustomPlatformData(const SharedBuffer* buffer)
{
- if (g_customFontCache && cachedFont->CachedResource::data()) {
+ if (g_customFontCache) {
String fontName = createUniqueFontName();
- if (renameFont(cachedFont->CachedResource::data(), fontName) && g_customFontCache->registerFont(fontName, cachedFont))
+ RefPtr<SharedBuffer> localBuffer = SharedBuffer::create(buffer->data(), buffer->size());
+ if (renameFont(localBuffer.get(), fontName) && g_customFontCache->registerFont(fontName, localBuffer.get()))
return new FontCustomPlatformData(fontName);
}
return 0;
diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.h b/WebCore/platform/graphics/wince/FontCustomPlatformData.h
index b1f64a0..89d1fdd 100644
--- a/WebCore/platform/graphics/wince/FontCustomPlatformData.h
+++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.h
@@ -32,7 +32,7 @@ namespace WebCore {
class CustomFontCache {
public:
- virtual bool registerFont(const String& fontName, CachedFont*) = 0;
+ virtual bool registerFont(const String& fontName, const SharedBuffer*) = 0;
virtual void unregisterFont(const String& fontName) = 0;
};
@@ -48,8 +48,8 @@ namespace WebCore {
String m_name;
};
- FontCustomPlatformData* createFontCustomPlatformData(CachedFont*);
-
+ FontCustomPlatformData* createFontCustomPlatformData(const SharedBuffer*);
+ void setCustomFontCache(CustomFontCache*);
}
#endif
diff --git a/WebCore/platform/graphics/wince/GradientWince.cpp b/WebCore/platform/graphics/wince/GradientWince.cpp
new file mode 100644
index 0000000..49fa970
--- /dev/null
+++ b/WebCore/platform/graphics/wince/GradientWince.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, 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 "Gradient.h"
+
+#include "GraphicsContext.h"
+
+namespace WebCore {
+
+void Gradient::platformDestroy()
+{
+}
+
+static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b)
+{
+ return a.stop < b.stop;
+}
+
+const Vector<Gradient::ColorStop>& Gradient::getStops() const
+{
+ if (!m_stopsSorted) {
+ if (m_stops.size())
+ std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
+ m_stopsSorted = true;
+ }
+ return m_stops;
+}
+
+void Gradient::fill(GraphicsContext* c, const FloatRect& r)
+{
+ c->fillRect(r, this);
+}
+
+}
diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
index c114c0e..f22e6c9 100644
--- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
+++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
@@ -947,7 +947,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
}
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled() || !m_data->m_opacity)
return;
@@ -1051,12 +1051,12 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int wi
notImplemented();
}
-void GraphicsContext::setPlatformFillColor(const Color& col)
+void GraphicsContext::setPlatformFillColor(const Color& col, ColorSpace colorSpace)
{
notImplemented();
}
-void GraphicsContext::setPlatformStrokeColor(const Color& col)
+void GraphicsContext::setPlatformStrokeColor(const Color& col, ColorSpace colorSpace)
{
notImplemented();
}
@@ -1088,7 +1088,7 @@ void GraphicsContext::clearRect(const FloatRect& rect)
return;
}
- fillRect(rect, Color(Color::white));
+ fillRect(rect, Color(Color::white), DeviceColorSpace);
}
void GraphicsContext::strokeRect(const FloatRect& rect, float width)
@@ -1219,6 +1219,11 @@ void GraphicsContext::clip(const Path& path)
notImplemented();
}
+void GraphicsContext::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
void GraphicsContext::clipOut(const Path&)
{
notImplemented();
@@ -1233,7 +1238,7 @@ static inline IntPoint rectCenterPoint(const RECT& rect)
{
return IntPoint(rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2);
}
-void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& c)
+void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& c, ColorSpace colorSpace)
{
ScopeDCProvider dcProvider(m_data);
if (!m_data->m_dc)
@@ -1350,7 +1355,7 @@ Color gradientAverageColor(const Gradient* gradient)
void GraphicsContext::fillPath()
{
- Color c = m_common->state.fillColorSpace == GradientColorSpace && m_common->state.fillGradient
+ Color c = m_common->state.fillGradient
? gradientAverageColor(m_common->state.fillGradient.get())
: fillColor();
@@ -1444,7 +1449,7 @@ void GraphicsContext::fillRect(const FloatRect& r, const Gradient* gradient)
if (numStops == 1) {
const Gradient::ColorStop& stop = stops.first();
Color color(stop.red, stop.green, stop.blue, stop.alpha);
- fillRect(r, color);
+ fillRect(r, color, DeviceColorSpace);
return;
}
@@ -1534,13 +1539,13 @@ void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
void GraphicsContext::fillRect(const FloatRect& rect)
{
- if (m_common->state.fillColorSpace == GradientColorSpace && m_common->state.fillGradient)
+ if (m_common->state.fillGradient)
fillRect(rect, m_common->state.fillGradient.get());
else
- fillRect(rect, fillColor());
+ fillRect(rect, fillColor(), DeviceColorSpace);
}
-void GraphicsContext::setPlatformShadow(const IntSize&, int, const Color&)
+void GraphicsContext::setPlatformShadow(const IntSize&, int, const Color&, ColorSpace)
{
notImplemented();
}
diff --git a/WebCore/platform/graphics/wince/ImageBufferData.h b/WebCore/platform/graphics/wince/ImageBufferData.h
new file mode 100644
index 0000000..01b7d06
--- /dev/null
+++ b/WebCore/platform/graphics/wince/ImageBufferData.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ImageBufferData_h
+#define ImageBufferData_h
+
+namespace WebCore {
+
+ class IntSize;
+ class ImageBufferData {
+ public:
+ ImageBufferData(const IntSize& size);
+ RefPtr<SharedBitmap> m_bitmap;
+ };
+
+} // namespace WebCore
+
+#endif // ImageBufferData_h
diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp
new file mode 100644
index 0000000..3417f5f
--- /dev/null
+++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, 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 "ImageBuffer.h"
+
+#include "Base64.h"
+#include "GraphicsContext.h"
+#include "Image.h"
+#include "ImageData.h"
+#include "JPEGEncoder.h"
+#include "PNGEncoder.h"
+#include "SharedBitmap.h"
+
+namespace WebCore {
+
+class BufferedImage: public Image {
+
+public:
+ BufferedImage(const ImageBufferData* data)
+ : m_data(data)
+ {
+ }
+
+ virtual IntSize size() const { return IntSize(m_data->m_bitmap->width(), m_data->m_bitmap->height()); }
+ virtual void destroyDecodedData(bool destroyAll = true) {}
+ virtual unsigned decodedSize() const { return 0; }
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
+ const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+
+ const ImageBufferData* m_data;
+};
+
+void BufferedImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+{
+ IntRect intDstRect = enclosingIntRect(dstRect);
+ IntRect intSrcRect(srcRect);
+ m_data->m_bitmap->draw(ctxt, intDstRect, intSrcRect, compositeOp);
+}
+
+void BufferedImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const TransformationMatrix& patternTransform,
+ const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+{
+ m_data->m_bitmap->drawPattern(ctxt, tileRectIn, patternTransform, phase, op, destRect, size());
+}
+
+ImageBufferData::ImageBufferData(const IntSize& size)
+: m_bitmap(SharedBitmap::createInstance(false, size.width(), size.height(), false))
+{
+ // http://www.w3.org/TR/2009/WD-html5-20090212/the-canvas-element.html#canvaspixelarray
+ // "When the canvas is initialized it must be set to fully transparent black."
+ m_bitmap->resetPixels(true);
+ m_bitmap->setHasAlpha(true);
+}
+
+ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace colorSpace, bool& success)
+ : m_data(size)
+ , m_size(size)
+{
+ // FIXME: colorSpace is not used
+ UNUSED_PARAM(colorSpace);
+
+ m_context.set(new GraphicsContext(0));
+ m_context->setBitmap(m_data.m_bitmap);
+ success = true;
+}
+
+ImageBuffer::~ImageBuffer()
+{
+}
+
+GraphicsContext* ImageBuffer::context() const
+{
+ return m_context.get();
+}
+
+Image* ImageBuffer::image() const
+{
+ if (!m_image)
+ m_image = adoptRef(new BufferedImage(&m_data));
+
+ return m_image.get();
+}
+
+template <bool premultiplied> PassRefPtr<ImageData>
+static getImageData(const IntRect& rect, const SharedBitmap* bitmap)
+{
+ PassRefPtr<ImageData> imageData = ImageData::create(rect.width(), rect.height());
+
+ const unsigned char* src = static_cast<const unsigned char*>(bitmap->bytes());
+ if (!src)
+ return imageData;
+
+ IntRect sourceRect(0, 0, bitmap->width(), bitmap->height());
+ sourceRect.intersect(rect);
+ if (sourceRect.isEmpty())
+ return imageData;
+
+ unsigned char* dst = imageData->data()->data()->data();
+ memset(dst, 0, imageData->data()->data()->length());
+ src += (sourceRect.y() * bitmap->width() + sourceRect.x()) * 4;
+ dst += ((sourceRect.y() - rect.y()) * imageData->width() + sourceRect.x() - rect.x()) * 4;
+ int bytesToCopy = sourceRect.width() * 4;
+ int srcSkip = (bitmap->width() - sourceRect.width()) * 4;
+ int dstSkip = (imageData->width() - sourceRect.width()) * 4;
+ const unsigned char* dstEnd = dst + sourceRect.height() * imageData->width() * 4;
+ while (dst < dstEnd) {
+ const unsigned char* dstRowEnd = dst + bytesToCopy;
+ while (dst < dstRowEnd) {
+ // Convert ARGB little endian to RGBA big endian
+ int blue = *src++;
+ int green = *src++;
+ int red = *src++;
+ int alpha = *src++;
+ if (premultiplied) {
+ *dst++ = static_cast<unsigned char>((red * alpha + 254) / 255);
+ *dst++ = static_cast<unsigned char>((green * alpha + 254) / 255);
+ *dst++ = static_cast<unsigned char>((blue * alpha + 254) / 255);
+ *dst++ = static_cast<unsigned char>(alpha);
+ } else {
+ *dst++ = static_cast<unsigned char>(red);
+ *dst++ = static_cast<unsigned char>(green);
+ *dst++ = static_cast<unsigned char>(blue);
+ *dst++ = static_cast<unsigned char>(alpha);
+ ++src;
+ }
+ }
+ src += srcSkip;
+ dst += dstSkip;
+ }
+
+ return imageData;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<false>(rect, m_data.m_bitmap.get());
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<true>(rect, m_data.m_bitmap.get());
+}
+
+template <bool premultiplied>
+static void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint, SharedBitmap* bitmap)
+{
+ unsigned char* dst = (unsigned char*)bitmap->bytes();
+ if (!dst)
+ return;
+
+ IntRect destRect(destPoint, sourceRect.size());
+ destRect.intersect(IntRect(0, 0, bitmap->width(), bitmap->height()));
+
+ if (destRect.isEmpty())
+ return;
+
+ const unsigned char* src = source->data()->data()->data();
+ dst += (destRect.y() * bitmap->width() + destRect.x()) * 4;
+ src += (sourceRect.y() * source->width() + sourceRect.x()) * 4;
+ int bytesToCopy = destRect.width() * 4;
+ int dstSkip = (bitmap->width() - destRect.width()) * 4;
+ int srcSkip = (source->width() - destRect.width()) * 4;
+ const unsigned char* dstEnd = dst + destRect.height() * bitmap->width() * 4;
+ while (dst < dstEnd) {
+ const unsigned char* dstRowEnd = dst + bytesToCopy;
+ while (dst < dstRowEnd) {
+ // Convert RGBA big endian to ARGB little endian
+ int red = *src++;
+ int green = *src++;
+ int blue = *src++;
+ int alpha = *src++;
+ if (premultiplied) {
+ *dst++ = static_cast<unsigned char>(blue * 255 / alpha);
+ *dst++ = static_cast<unsigned char>(green * 255 / alpha);
+ *dst++ = static_cast<unsigned char>(red * 255 / alpha);
+ *dst++ = static_cast<unsigned char>(alpha);
+ } else {
+ *dst++ = static_cast<unsigned char>(blue);
+ *dst++ = static_cast<unsigned char>(green);
+ *dst++ = static_cast<unsigned char>(red);
+ *dst++ = static_cast<unsigned char>(alpha);
+ }
+ }
+ src += srcSkip;
+ dst += dstSkip;
+ }
+}
+
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<false>(source, sourceRect, destPoint, m_data.m_bitmap.get());
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<true>(source, sourceRect, destPoint, m_data.m_bitmap.get());
+}
+
+String ImageBuffer::toDataURL(const String& mimeType) const
+{
+ if (!m_data.m_bitmap->bytes())
+ return "data:,";
+
+ Vector<char> output;
+ const char* header;
+ if (mimeType.lower() == "image/png") {
+ if (!compressBitmapToPng(m_data.m_bitmap.get(), output))
+ return "data:,";
+ header = "data:image/png;base64,";
+ } else {
+ if (!compressBitmapToJpeg(m_data.m_bitmap.get(), output))
+ return "data:,";
+ header = "data:image/jpeg;base64,";
+ }
+
+ Vector<char> base64;
+ base64Encode(output, base64);
+
+ output.clear();
+
+ Vector<char> url;
+ url.append(header, strlen(header));
+ url.append(base64);
+
+ return String(url.data(), url.size());
+}
+
+}
diff --git a/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h b/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h
new file mode 100644
index 0000000..2d6c358
--- /dev/null
+++ b/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile 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 MediaPlayerPrivateWince_h
+#define MediaPlayerPrivateWince_h
+
+#if ENABLE(VIDEO)
+
+#include "MediaPlayerPrivate.h"
+#include "Timer.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+ class GraphicsContext;
+ class IntSize;
+ class IntRect;
+ class String;
+
+ class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
+ public:
+ static void registerMediaEngine(MediaEngineRegistrar);
+
+ ~MediaPlayerPrivate();
+
+ IntSize naturalSize() const;
+ bool hasVideo() const;
+
+ void load(const String& url);
+ void cancelLoad();
+
+ void play();
+ void pause();
+
+ bool paused() const;
+ bool seeking() const;
+
+ float duration() const;
+ float currentTime() const;
+ void seek(float time);
+ void setEndTime(float);
+
+ void setRate(float);
+ void setVolume(float);
+
+ int dataRate() const;
+
+ MediaPlayer::NetworkState networkState() const { return m_networkState; }
+ MediaPlayer::ReadyState readyState() const { return m_readyState; }
+
+ PassRefPtr<TimeRanges> buffered() const;
+ float maxTimeSeekable() const;
+ unsigned bytesLoaded() const;
+ bool totalBytesKnown() const;
+ unsigned totalBytes() const;
+
+ void setVisible(bool);
+ void setSize(const IntSize&);
+
+ void loadStateChanged();
+ void didEnd();
+
+ void paint(GraphicsContext*, const IntRect&);
+
+ private:
+ MediaPlayerPrivate(MediaPlayer*);
+
+ void updateStates();
+ void doSeek();
+ void cancelSeek();
+ void seekTimerFired(Timer<MediaPlayerPrivate>*);
+ float maxTimeLoaded() const;
+ void sawUnsupportedTracks();
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ void setMediaPlayerProxy(WebMediaPlayerProxy*);
+ void setPoster(const String& url);
+ void deliverNotification(MediaPlayerProxyNotificationType);
+#endif
+
+ // engine support
+ static MediaPlayerPrivateInterface* create(MediaPlayer*);
+ static void getSupportedTypes(HashSet<String>& types);
+ static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
+ static bool isAvailable();
+
+ MediaPlayer* m_player;
+ float m_seekTo;
+ float m_endTime;
+ Timer<MediaPlayerPrivate> m_seekTimer;
+ MediaPlayer::NetworkState m_networkState;
+ MediaPlayer::ReadyState m_readyState;
+ unsigned m_enabledTrackCount;
+ unsigned m_totalTrackCount;
+ bool m_hasUnsupportedTracks;
+ bool m_startedPlaying;
+ bool m_isStreaming;
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ WebMediaPlayerProxy* m_proxy;
+#endif
+ };
+
+}
+
+#endif
+
+#endif
diff --git a/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp b/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp
new file mode 100644
index 0000000..ceb5a7c
--- /dev/null
+++ b/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, 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.
+ */
+
+#if ENABLE(VIDEO)
+
+#include "config.h"
+#include "MediaPlayerProxy.h"
+
+#include "Bridge.h"
+#include "DocumentLoader.h"
+#include "HTMLPlugInElement.h"
+#include "HTMLVideoElement.h"
+#include "JSDOMBinding.h"
+#include "JSPluginElementFunctions.h"
+#include "MediaPlayer.h"
+#include "Node.h"
+#include "PlatformString.h"
+#include "PluginView.h"
+#include "RenderPartObject.h"
+#include "RenderWidget.h"
+#include "Widget.h"
+#include "c_class.h"
+#include "c_instance.h"
+#include "c_runtime.h"
+#include "npruntime_impl.h"
+#include <runtime/Identifier.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+using namespace Bindings;
+using namespace HTMLNames;
+
+WebMediaPlayerProxy::WebMediaPlayerProxy(MediaPlayer* player)
+ : m_mediaPlayer(player)
+ , m_init(false)
+ , m_hasSentResponseToPlugin(false)
+{
+ if (!m_init)
+ initEngine();
+}
+
+WebMediaPlayerProxy::~WebMediaPlayerProxy()
+{
+ m_instance.release();
+}
+
+ScriptInstance WebMediaPlayerProxy::pluginInstance()
+{
+ if (!m_instance) {
+ RenderObject* r = element()->renderer();
+ if (!r || !r->isWidget())
+ return 0;
+
+ Frame* frame = element()->document()->frame();
+
+ RenderWidget* renderWidget = static_cast<RenderWidget*>(element()->renderer());
+ if (renderWidget && renderWidget->widget())
+ m_instance = frame->script()->createScriptInstanceForWidget(renderWidget->widget());
+ }
+
+ return m_instance;
+}
+
+void WebMediaPlayerProxy::load(const String& url)
+{
+ if (!m_init)
+ initEngine();
+ if (m_init)
+ invokeMethod("play");
+}
+
+void WebMediaPlayerProxy::initEngine()
+{
+ HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient());
+ String url = element->initialURL();
+
+ if (url.isEmpty())
+ return;
+
+ Frame* frame = element->document()->frame();
+ Vector<String> paramNames;
+ Vector<String> paramValues;
+ String serviceType;
+
+ // add all attributes set on the embed object
+ if (NamedNodeMap* attributes = element->attributes()) {
+ for (unsigned i = 0; i < attributes->length(); ++i) {
+ Attribute* it = attributes->attributeItem(i);
+ paramNames.append(it->name().localName().string());
+ paramValues.append(it->value().string());
+ }
+ }
+ serviceType = "application/x-mplayer2";
+ frame->loader()->requestObject(static_cast<RenderPartObject*>(element->renderer()), url, nullAtom, serviceType, paramNames, paramValues);
+ m_init = true;
+
+}
+
+HTMLMediaElement* WebMediaPlayerProxy::element()
+{
+ return static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient());
+
+}
+
+void WebMediaPlayerProxy::invokeMethod(const String& methodName)
+{
+ Frame* frame = element()->document()->frame();
+ RootObject *root = frame->script()->bindingRootObject();
+ if (!root)
+ return;
+ ExecState *exec = root->globalObject()->globalExec();
+ Instance* instance = pluginInstance().get();
+ if (!instance)
+ return;
+
+ instance->begin();
+ Class *aClass = instance->getClass();
+ Identifier iden(exec, methodName);
+ MethodList methodList = aClass->methodsNamed(iden, instance);
+ ArgList args;
+ instance->invokeMethod(exec, methodList , args);
+ instance->end();
+}
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/wince/MediaPlayerProxy.h b/WebCore/platform/graphics/wince/MediaPlayerProxy.h
new file mode 100644
index 0000000..05f9b21
--- /dev/null
+++ b/WebCore/platform/graphics/wince/MediaPlayerProxy.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef MediaPlayerProxy_h
+#define MediaPlayerProxy_h
+
+#if ENABLE(VIDEO)
+
+#include "ScriptInstance.h"
+
+namespace WebCore {
+
+ class IntRect;
+ class IntSize;
+ class String;
+ class MediaPlayer;
+ class PluginView;
+ class HTMLMediaElement;
+
+ enum MediaPlayerProxyNotificationType {
+ MediaPlayerNotificationPlayPauseButtonPressed,
+ Idle,
+ Loading,
+ Loaded,
+ FormatError,
+ NetworkError,
+ DecodeError
+ };
+
+ class WebMediaPlayerProxy {
+ public:
+ WebMediaPlayerProxy(MediaPlayer* player);
+ ~WebMediaPlayerProxy();
+
+ MediaPlayer* mediaPlayer() {return m_mediaPlayer;}
+ void initEngine();
+ void load(const String& url);
+ HTMLMediaElement* element();
+ void invokeMethod(const String& methodName);
+ ScriptInstance pluginInstance();
+
+ private:
+ MediaPlayer* m_mediaPlayer;
+ bool m_init;
+ WebCore::PluginView* m_pluginView;
+ bool m_hasSentResponseToPlugin;
+ ScriptInstance m_instance;
+ };
+
+}
+#endif // ENABLE(VIDEO)
+
+#endif
diff --git a/WebCore/platform/graphics/wince/PathWince.cpp b/WebCore/platform/graphics/wince/PathWince.cpp
new file mode 100644
index 0000000..7589ccb
--- /dev/null
+++ b/WebCore/platform/graphics/wince/PathWince.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "Path.h"
+
+#include "FloatRect.h"
+#include "NotImplemented.h"
+#include "PlatformPathWince.h"
+#include "PlatformString.h"
+#include "TransformationMatrix.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+Path::Path()
+ : m_path(new PlatformPath())
+{
+}
+
+Path::Path(const Path& other)
+ : m_path(new PlatformPath(*other.m_path))
+{
+}
+
+Path::~Path()
+{
+ delete m_path;
+}
+
+Path& Path::operator=(const Path& other)
+{
+ if (&other != this) {
+ delete m_path;
+ m_path = new PlatformPath(*other.m_path);
+ }
+ return *this;
+}
+
+bool Path::contains(const FloatPoint& point, WindRule rule) const
+{
+ return m_path->contains(point, rule);
+}
+
+void Path::translate(const FloatSize& size)
+{
+ m_path->translate(size);
+}
+
+FloatRect Path::boundingRect() const
+{
+ return m_path->boundingRect();
+}
+
+void Path::moveTo(const FloatPoint& point)
+{
+ m_path->moveTo(point);
+}
+
+void Path::addLineTo(const FloatPoint& point)
+{
+ m_path->addLineTo(point);
+}
+
+void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+{
+ m_path->addQuadCurveTo(cp, p);
+}
+
+void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+{
+ m_path->addBezierCurveTo(cp1, cp2, p);
+}
+
+void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
+{
+ m_path->addArcTo(p1, p2, radius);
+}
+
+void Path::closeSubpath()
+{
+ m_path->closeSubpath();
+}
+
+void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool anticlockwise)
+{
+ m_path->addEllipse(p, r, r, sar, ear, anticlockwise);
+}
+
+void Path::addRect(const FloatRect& r)
+{
+ m_path->addRect(r);
+}
+
+void Path::addEllipse(const FloatRect& r)
+{
+ m_path->addEllipse(r);
+}
+
+void Path::clear()
+{
+ m_path->clear();
+}
+
+bool Path::isEmpty() const
+{
+ return m_path->isEmpty();
+}
+
+String Path::debugString() const
+{
+ return m_path->debugString();
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ m_path->apply(info, function);
+}
+
+void Path::transform(const TransformationMatrix& t)
+{
+ m_path->transform(t);
+}
+
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier *)
+{
+ notImplemented();
+ return FloatRect();
+}
+
+bool Path::strokeContains(StrokeStyleApplier*, const FloatPoint&) const
+{
+ notImplemented();
+ return false;
+}
+
+bool Path::hasCurrentPoint() const
+{
+ // Not sure if this is correct. At the meantime, we do what other ports
+ // do.
+ // See https://bugs.webkit.org/show_bug.cgi?id=27266,
+ // https://bugs.webkit.org/show_bug.cgi?id=27187, and
+ // http://trac.webkit.org/changeset/45873
+ return !isEmpty();
+}
+
+}
diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.cpp b/WebCore/platform/graphics/wince/PlatformPathWince.cpp
new file mode 100644
index 0000000..66fad50
--- /dev/null
+++ b/WebCore/platform/graphics/wince/PlatformPathWince.cpp
@@ -0,0 +1,810 @@
+/*
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "PlatformPathWince.h"
+
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "Path.h"
+#include "PlatformString.h"
+#include "TransformationMatrix.h"
+#include "WinceGraphicsExtras.h"
+#include <wtf/MathExtras.h>
+#include <wtf/OwnPtr.h>
+
+#include <windows.h>
+
+namespace WebCore {
+
+// Implemented in GraphicsContextWince.cpp
+void getEllipsePointByAngle(double angle, double a, double b, float& x, float& y);
+
+static void quadCurve(int segments, Vector<PathPoint>& pts, const PathPoint* control)
+{
+ const float step = 1.0 / segments;
+ register float tA = 0.0;
+ register float tB = 1.0;
+
+ float c1x = control[0].x();
+ float c1y = control[0].y();
+ float c2x = control[1].x();
+ float c2y = control[1].y();
+ float c3x = control[2].x();
+ float c3y = control[2].y();
+
+ const int offset = pts.size();
+ pts.resize(offset + segments);
+ PathPoint pp;
+ pp.m_x = c1x;
+ pp.m_y = c1y;
+
+ for (int i = 1; i < segments; ++i) {
+ tA += step;
+ tB -= step;
+
+ const float a = tB * tB;
+ const float b = 2.0 * tA * tB;
+ const float c = tA * tA;
+
+ pp.m_x = c1x * a + c2x * b + c3x * c;
+ pp.m_y = c1y * a + c2y * b + c3y * c;
+
+ pts[offset + i - 1] = pp;
+ }
+
+ pp.m_x = c3x;
+ pp.m_y = c3y;
+ pts[offset + segments - 1] = pp;
+}
+
+static inline void bezier(int segments, Vector<PathPoint>& pts, const PathPoint* control)
+{
+ const float step = 1.0 / segments;
+ register float tA = 0.0;
+ register float tB = 1.0;
+
+ float c1x = control[0].x();
+ float c1y = control[0].y();
+ float c2x = control[1].x();
+ float c2y = control[1].y();
+ float c3x = control[2].x();
+ float c3y = control[2].y();
+ float c4x = control[3].x();
+ float c4y = control[3].y();
+
+ const int offset = pts.size();
+ pts.resize(offset + segments);
+ PathPoint pp;
+ pp.m_x = c1x;
+ pp.m_y = c1y;
+
+ for (int i = 1; i < segments; ++i) {
+ tA += step;
+ tB -= step;
+ const float tAsq = tA * tA;
+ const float tBsq = tB * tB;
+
+ const float a = tBsq * tB;
+ const float b = 3.0 * tA * tBsq;
+ const float c = 3.0 * tB * tAsq;
+ const float d = tAsq * tA;
+
+ pp.m_x = c1x * a + c2x * b + c3x * c + c4x * d;
+ pp.m_y = c1y * a + c2y * b + c3y * c + c4y * d;
+
+ pts[offset + i - 1] = pp;
+ }
+
+ pp.m_x = c4x;
+ pp.m_y = c4y;
+ pts[offset + segments - 1] = pp;
+}
+
+static bool containsPoint(const FloatRect& r, const FloatPoint& p)
+{
+ return p.x() >= r.x() && p.y() >= r.y() && p.x() < r.right() && p.y() < r.bottom();
+}
+
+static void normalizeAngle(float& angle)
+{
+ angle = fmod(angle, 2 * piFloat);
+ if (angle < 0)
+ angle += 2 * piFloat;
+ if (angle < 0.00001f)
+ angle = 0;
+}
+
+static void transformArcPoint(float& x, float& y, const FloatPoint& c)
+{
+ x += c.x();
+ y += c.y();
+}
+
+static void inflateRectToContainPoint(FloatRect& r, float x, float y)
+{
+ if (r.isEmpty()) {
+ r.setX(x);
+ r.setY(y);
+ r.setSize(FloatSize(1, 1));
+ return;
+ }
+ if (x < r.x()) {
+ r.setWidth(r.right() - x);
+ r.setX(x);
+ } else {
+ float w = x - r.x() + 1;
+ if (w > r.width())
+ r.setWidth(w);
+ }
+ if (y < r.y()) {
+ r.setHeight(r.bottom() - y);
+ r.setY(y);
+ } else {
+ float h = y - r.y() + 1;
+ if (h > r.height())
+ r.setHeight(h);
+ }
+}
+
+// return 0-based value: 0 - first Quadrant ( 0 - 90 degree)
+static inline int quadrant(const PathPoint& point, const PathPoint& origin)
+{
+ return point.m_x < origin.m_x ?
+ (point.m_y < origin.m_y ? 2 : 1)
+ : (point.m_y < origin.m_y ? 3 : 0);
+}
+
+static inline bool isQuadrantOnLeft(int q) { return q == 1 || q == 2; }
+static inline bool isQuadrantOnRight(int q) { return q == 0 || q == 3; }
+static inline bool isQuadrantOnTop(int q) { return q == 2 || q == 3; }
+static inline bool isQuadrantOnBottom(int q) { return q == 0 || q == 1; }
+
+static inline int nextQuadrant(int q) { return q == 3 ? 0 : q + 1; }
+static inline int quadrantDiff(int q1, int q2)
+{
+ int d = q1 - q2;
+ while (d < 0)
+ d += 4;
+ return d;
+}
+
+struct PathVector {
+ float m_x;
+ float m_y;
+
+ PathVector() : m_x(0), m_y(0) {}
+ PathVector(float x, float y) : m_x(x), m_y(y) {}
+ double angle() const { return atan2(m_y, m_x); }
+ operator double () const { return angle(); }
+ double length() const { return _hypot(m_x, m_y); }
+};
+
+PathVector operator-(const PathPoint& p1, const PathPoint& p2)
+{
+ return PathVector(p1.m_x - p2.m_x, p1.m_y - p2.m_y);
+}
+
+static void addArcPoint(PathPolygon& poly, const PathPoint& center, const PathPoint& radius, double angle)
+{
+ PathPoint p;
+ getEllipsePointByAngle(angle, radius.m_x, radius.m_y, p.m_x, p.m_y);
+ transformArcPoint(p.m_x, p.m_y, center);
+ if (poly.isEmpty() || poly.last() != p)
+ poly.append(p);
+}
+
+static void addArcPoints(PathPolygon& poly, const PlatformPathElement::ArcTo& data)
+{
+ const PathPoint& startPoint = poly.last();
+ double curAngle = startPoint - data.m_center;
+ double endAngle = data.m_end - data.m_center;
+ double angleStep = 2. / std::max(data.m_radius.m_x, data.m_radius.m_y);
+ if (data.m_clockwise) {
+ if (endAngle <= curAngle || startPoint == data.m_end)
+ endAngle += 2 * piDouble;
+ } else {
+ angleStep = -angleStep;
+ if (endAngle >= curAngle || startPoint == data.m_end)
+ endAngle -= 2 * piDouble;
+ }
+
+ for (curAngle += angleStep; data.m_clockwise ? curAngle < endAngle : curAngle > endAngle; curAngle += angleStep)
+ addArcPoint(poly, data.m_center, data.m_radius, curAngle);
+
+ if (poly.isEmpty() || poly.last() != data.m_end)
+ poly.append(data.m_end);
+}
+
+static void drawPolygons(HDC dc, const Vector<PathPolygon>& polygons, bool fill, const TransformationMatrix* transformation)
+{
+ MemoryAllocationCanFail canFail;
+ for (Vector<PathPolygon>::const_iterator i = polygons.begin(); i != polygons.end(); ++i) {
+ int npoints = i->size();
+ if (!npoints)
+ continue;
+
+ POINT* winPoints = 0;
+ if (fill) {
+ if (npoints > 2)
+ winPoints = new POINT[npoints + 1];
+ } else
+ winPoints = new POINT[npoints];
+
+ if (winPoints) {
+ if (transformation) {
+ for (int i2 = 0; i2 < npoints; ++i2) {
+ FloatPoint trPoint = transformation->mapPoint(i->at(i2));
+ winPoints[i2].x = stableRound(trPoint.x());
+ winPoints[i2].y = stableRound(trPoint.y());
+ }
+ } else {
+ for (int i2 = 0; i2 < npoints; ++i2) {
+ winPoints[i2].x = stableRound(i->at(i2).x());
+ winPoints[i2].y = stableRound(i->at(i2).y());
+ }
+ }
+
+ if (fill && winPoints[npoints - 1] != winPoints[0]) {
+ winPoints[npoints].x = winPoints[0].x;
+ winPoints[npoints].y = winPoints[0].y;
+ ++npoints;
+ }
+
+ if (fill)
+ ::Polygon(dc, winPoints, npoints);
+ else
+ ::Polyline(dc, winPoints, npoints);
+ delete[] winPoints;
+ }
+ }
+}
+
+
+int PlatformPathElement::numControlPoints() const
+{
+ switch (m_type) {
+ case PathMoveTo:
+ case PathLineTo:
+ return 1;
+ case PathQuadCurveTo:
+ case PathArcTo:
+ return 2;
+ case PathBezierCurveTo:
+ return 3;
+ default:
+ ASSERT(m_type == PathCloseSubpath);
+ return 0;
+ }
+}
+
+int PlatformPathElement::numPoints() const
+{
+ switch (m_type) {
+ case PathMoveTo:
+ case PathLineTo:
+ case PathArcTo:
+ return 1;
+ case PathQuadCurveTo:
+ return 2;
+ case PathBezierCurveTo:
+ return 3;
+ default:
+ ASSERT(m_type == PathCloseSubpath);
+ return 0;
+ }
+}
+
+void PathPolygon::move(const FloatSize& offset)
+{
+ for (Vector<PathPoint>::iterator i = begin(); i < end(); ++i)
+ i->move(offset);
+}
+
+void PathPolygon::transform(const TransformationMatrix& t)
+{
+ for (Vector<PathPoint>::iterator i = begin(); i < end(); ++i)
+ *i = t.mapPoint(*i);
+}
+
+bool PathPolygon::contains(const FloatPoint& point) const
+{
+ if (size() < 3)
+ return false;
+
+ // Test intersections between the polygon and the vertical line: x = point.x()
+
+ int intersected = 0;
+ const PathPoint* point1 = &last();
+ Vector<PathPoint>::const_iterator last = end();
+ // wasNegative: -1 means unknown, 0 means false, 1 means true.
+ int wasNegative = -1;
+ for (Vector<PathPoint>::const_iterator i = begin(); i != last; ++i) {
+ const PathPoint& point2 = *i;
+ if (point1->x() != point.x()) {
+ if (point2.x() == point.x()) {
+ // We are getting on the vertical line
+ wasNegative = point1->x() < point.x() ? 1 : 0;
+ } else if (point2.x() < point.x() != point1->x() < point.x()) {
+ float y = (point2.y() - point1->y()) / (point2.x() - point1->x()) * (point.x() - point1->x()) + point1->y();
+ if (y >= point.y())
+ ++intersected;
+ }
+ } else {
+ // We were on the vertical line
+
+ // handle special case
+ if (point1->y() == point.y())
+ return true;
+
+ if (point1->y() > point.y()) {
+ if (point2.x() == point.x()) {
+ // see if the point is on this segment
+ if (point2.y() <= point.y())
+ return true;
+
+ // We are still on the line
+ } else {
+ // We are leaving the line now.
+ // We have to get back to see which side we come from. If we come from
+ // the same side we are leaving, no intersection should be counted
+ if (wasNegative < 0) {
+ Vector<PathPoint>::const_iterator jLast = i;
+ Vector<PathPoint>::const_iterator j = i;
+ do {
+ if (j == begin())
+ j = last;
+ else
+ --j;
+ if (j->x() != point.x()) {
+ if (j->x() > point.x())
+ wasNegative = 0;
+ else
+ wasNegative = 1;
+ break;
+ }
+ } while (j != jLast);
+
+ if (wasNegative < 0)
+ return false;
+ }
+ if (wasNegative ? point2.x() > point.x() : point2.x() < point.x())
+ ++intersected;
+ }
+ } else if (point2.x() == point.x() && point2.y() >= point.y())
+ return true;
+ }
+ point1 = &point2;
+ }
+
+ return intersected & 1;
+}
+
+void PlatformPathElement::move(const FloatSize& offset)
+{
+ int n = numControlPoints();
+ for (int i = 0; i < n; ++i)
+ m_data.m_points[i].move(offset);
+}
+
+void PlatformPathElement::transform(const TransformationMatrix& t)
+{
+ int n = numControlPoints();
+ for (int i = 0; i < n; ++i) {
+ FloatPoint p = t.mapPoint(m_data.m_points[i]);
+ m_data.m_points[i].set(p.x(), p.y());
+ }
+}
+
+void PlatformPathElement::inflateRectToContainMe(FloatRect& r, const FloatPoint& lastPoint) const
+{
+ if (m_type == PathArcTo) {
+ const ArcTo& data = m_data.m_arcToData;
+ PathPoint startPoint;
+ startPoint = lastPoint;
+ PathPoint endPoint = data.m_end;
+ if (!data.m_clockwise)
+ std::swap(startPoint, endPoint);
+
+ int q0 = quadrant(startPoint, data.m_center);
+ int q1 = quadrant(endPoint, data.m_center);
+ bool containsExtremes[4] = { false }; // bottom, left, top, right
+ static const PathPoint extremeVectors[4] = { { 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 0 } };
+ if (q0 == q1) {
+ if (startPoint.m_x == endPoint.m_x || isQuadrantOnBottom(q0) != startPoint.m_x > endPoint.m_x) {
+ for (int i = 0; i < 4; ++i)
+ containsExtremes[i] = true;
+ }
+ } else {
+ int extreme = q0;
+ int diff = quadrantDiff(q1, q0);
+ for (int i = 0; i < diff; ++i) {
+ containsExtremes[extreme] = true;
+ extreme = nextQuadrant(extreme);
+ }
+ }
+
+ inflateRectToContainPoint(r, startPoint.m_x, startPoint.m_y);
+ inflateRectToContainPoint(r, endPoint.m_x, endPoint.m_y);
+ for (int i = 0; i < 4; ++i) {
+ if (containsExtremes[i])
+ inflateRectToContainPoint(r, data.m_center.m_x + data.m_radius.m_x * extremeVectors[i].m_x, data.m_center.m_y + data.m_radius.m_y * extremeVectors[i].m_y);
+ }
+ } else {
+ int n = numPoints();
+ for (int i = 0; i < n; ++i)
+ inflateRectToContainPoint(r, m_data.m_points[i].m_x, m_data.m_points[i].m_y);
+ }
+}
+
+PathElementType PlatformPathElement::type() const
+{
+ switch (m_type) {
+ case PathMoveTo:
+ return PathElementMoveToPoint;
+ case PathLineTo:
+ return PathElementAddLineToPoint;
+ case PathArcTo:
+ // FIXME: there's no arcTo type for PathElement
+ return PathElementAddLineToPoint;
+ // return PathElementAddQuadCurveToPoint;
+ case PathQuadCurveTo:
+ return PathElementAddQuadCurveToPoint;
+ case PathBezierCurveTo:
+ return PathElementAddCurveToPoint;
+ default:
+ ASSERT(m_type == PathCloseSubpath);
+ return PathElementCloseSubpath;
+ }
+}
+
+PlatformPath::PlatformPath()
+ : m_penLifted(true)
+{
+ m_currentPoint.clear();
+}
+
+void PlatformPath::ensureSubpath()
+{
+ if (m_penLifted) {
+ m_penLifted = false;
+ m_subpaths.append(PathPolygon());
+ m_subpaths.last().append(m_currentPoint);
+ } else
+ ASSERT(!m_subpaths.isEmpty());
+}
+
+void PlatformPath::addToSubpath(const PlatformPathElement& e)
+{
+ if (e.platformType() == PlatformPathElement::PathMoveTo) {
+ m_penLifted = true;
+ m_currentPoint = e.pointAt(0);
+ } else if (e.platformType() == PlatformPathElement::PathCloseSubpath) {
+ m_penLifted = true;
+ if (!m_subpaths.isEmpty()) {
+ if (m_currentPoint != m_subpaths.last()[0]) {
+ // According to W3C, we have to draw a line from current point to the initial point
+ m_subpaths.last().append(m_subpaths.last()[0]);
+ m_currentPoint = m_subpaths.last()[0];
+ }
+ } else
+ m_currentPoint.clear();
+ } else {
+ ensureSubpath();
+ switch (e.platformType()) {
+ case PlatformPathElement::PathLineTo:
+ m_subpaths.last().append(e.pointAt(0));
+ break;
+ case PlatformPathElement::PathArcTo:
+ addArcPoints(m_subpaths.last(), e.arcTo());
+ break;
+ case PlatformPathElement::PathQuadCurveTo:
+ {
+ PathPoint control[] = {
+ m_currentPoint,
+ e.pointAt(0),
+ e.pointAt(1),
+ };
+ // FIXME: magic number?
+ quadCurve(50, m_subpaths.last(), control);
+ }
+ break;
+ case PlatformPathElement::PathBezierCurveTo:
+ {
+ PathPoint control[] = {
+ m_currentPoint,
+ e.pointAt(0),
+ e.pointAt(1),
+ e.pointAt(2),
+ };
+ // FIXME: magic number?
+ bezier(100, m_subpaths.last(), control);
+ }
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ m_currentPoint = m_subpaths.last().last();
+ }
+}
+
+void PlatformPath::append(const PlatformPathElement& e)
+{
+ e.inflateRectToContainMe(m_boundingRect, lastPoint());
+ addToSubpath(e);
+ m_elements.append(e);
+}
+
+void PlatformPath::append(const PlatformPath& p)
+{
+ const PlatformPathElements& e = p.elements();
+ for (PlatformPathElements::const_iterator it(e.begin()); it != e.end(); ++it) {
+ addToSubpath(*it);
+ it->inflateRectToContainMe(m_boundingRect, lastPoint());
+ m_elements.append(*it);
+ }
+}
+
+void PlatformPath::clear()
+{
+ m_elements.clear();
+ m_boundingRect = FloatRect();
+ m_subpaths.clear();
+ m_currentPoint.clear();
+ m_penLifted = true;
+}
+
+void PlatformPath::strokePath(HDC dc, const TransformationMatrix* transformation) const
+{
+ drawPolygons(dc, m_subpaths, false, transformation);
+}
+
+void PlatformPath::fillPath(HDC dc, const TransformationMatrix* transformation) const
+{
+ HGDIOBJ oldPen = SelectObject(dc, GetStockObject(NULL_PEN));
+ drawPolygons(dc, m_subpaths, true, transformation);
+ SelectObject(dc, oldPen);
+}
+
+void PlatformPath::translate(const FloatSize& size)
+{
+ for (PlatformPathElements::iterator it(m_elements.begin()); it != m_elements.end(); ++it)
+ it->move(size);
+
+ m_boundingRect.move(size);
+ for (Vector<PathPolygon>::iterator it = m_subpaths.begin(); it != m_subpaths.end(); ++it)
+ it->move(size);
+}
+
+void PlatformPath::transform(const TransformationMatrix& t)
+{
+ for (PlatformPathElements::iterator it(m_elements.begin()); it != m_elements.end(); ++it)
+ it->transform(t);
+
+ m_boundingRect = t.mapRect(m_boundingRect);
+ for (Vector<PathPolygon>::iterator it = m_subpaths.begin(); it != m_subpaths.end(); ++it)
+ it->transform(t);
+}
+
+bool PlatformPath::contains(const FloatPoint& point, WindRule rule) const
+{
+ // optimization: check the bounding rect first
+ if (!containsPoint(m_boundingRect, point))
+ return false;
+
+ for (Vector<PathPolygon>::const_iterator i = m_subpaths.begin(); i != m_subpaths.end(); ++i) {
+ if (i->contains(point))
+ return true;
+ }
+
+ return false;
+}
+
+void PlatformPath::moveTo(const FloatPoint& point)
+{
+ PlatformPathElement::MoveTo data = { { point.x(), point.y() } };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::addLineTo(const FloatPoint& point)
+{
+ PlatformPathElement::LineTo data = { { point.x(), point.y() } };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+{
+ PlatformPathElement::QuadCurveTo data = { { cp.x(), cp.y() }, { p.x(), p.y() } };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+{
+ PlatformPathElement::BezierCurveTo data = { { cp1.x(), cp1.y() }, { cp2.x(), cp2.y() }, { p.x(), p.y() } };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::addArcTo(const FloatPoint& fp1, const FloatPoint& fp2, float radius)
+{
+ const PathPoint& p0 = m_currentPoint;
+ PathPoint p1;
+ p1 = fp1;
+ PathPoint p2;
+ p2 = fp2;
+ if (!radius || p0 == p1 || p1 == p2) {
+ addLineTo(p1);
+ return;
+ }
+
+ PathVector v01 = p0 - p1;
+ PathVector v21 = p2 - p1;
+
+ // sin(A - B) = sin(A) * cos(B) - sin(B) * cos(A)
+ double cross = v01.m_x * v21.m_y - v01.m_y * v21.m_x;
+
+ if (fabs(cross) < 1E-10) {
+ // on one line
+ addLineTo(p1);
+ return;
+ }
+
+ double d01 = v01.length();
+ double d21 = v21.length();
+ double angle = (piDouble - abs(asin(cross / (d01 * d21)))) * 0.5;
+ double span = radius * tan(angle);
+ double rate = span / d01;
+ PathPoint startPoint;
+ startPoint.m_x = p1.m_x + v01.m_x * rate;
+ startPoint.m_y = p1.m_y + v01.m_y * rate;
+
+ addLineTo(startPoint);
+
+ PathPoint endPoint;
+ rate = span / d21;
+ endPoint.m_x = p1.m_x + v21.m_x * rate;
+ endPoint.m_y = p1.m_y + v21.m_y * rate;
+
+ PathPoint midPoint;
+ midPoint.m_x = (startPoint.m_x + endPoint.m_x) * 0.5;
+ midPoint.m_y = (startPoint.m_y + endPoint.m_y) * 0.5;
+
+ PathVector vm1 = midPoint - p1;
+ double dm1 = vm1.length();
+ double d = _hypot(radius, span);
+
+ PathPoint centerPoint;
+ rate = d / dm1;
+ centerPoint.m_x = p1.m_x + vm1.m_x * rate;
+ centerPoint.m_y = p1.m_y + vm1.m_y * rate;
+
+ PlatformPathElement::ArcTo data = {
+ endPoint,
+ centerPoint,
+ { radius, radius },
+ cross < 0
+ };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::closeSubpath()
+{
+ PlatformPathElement pe;
+ append(pe);
+}
+
+// add a circular arc centred at p with radius r from start angle sar (radians) to end angle ear
+void PlatformPath::addEllipse(const FloatPoint& p, float a, float b, float sar, float ear, bool anticlockwise)
+{
+ float startX, startY, endX, endY;
+
+ normalizeAngle(sar);
+ normalizeAngle(ear);
+
+ getEllipsePointByAngle(sar, a, b, startX, startY);
+ getEllipsePointByAngle(ear, a, b, endX, endY);
+
+ transformArcPoint(startX, startY, p);
+ transformArcPoint(endX, endY, p);
+
+ FloatPoint start(startX, startY);
+ moveTo(start);
+
+ PlatformPathElement::ArcTo data = { { endX, endY }, { p.x(), p.y() }, { a, b }, !anticlockwise };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+
+void PlatformPath::addRect(const FloatRect& r)
+{
+ moveTo(r.location());
+
+ float right = r.right() - 1;
+ float bottom = r.bottom() - 1;
+ addLineTo(FloatPoint(right, r.y()));
+ addLineTo(FloatPoint(right, bottom));
+ addLineTo(FloatPoint(r.x(), bottom));
+ addLineTo(r.location());
+}
+
+void PlatformPath::addEllipse(const FloatRect& r)
+{
+ FloatSize radius(r.width() * 0.5, r.height() * 0.5);
+ addEllipse(r.location() + radius, radius.width(), radius.height(), 0, 0, true);
+}
+
+String PlatformPath::debugString() const
+{
+ String ret;
+ for (PlatformPathElements::const_iterator i(m_elements.begin()); i != m_elements.end(); ++i) {
+ switch (i->platformType()) {
+ case PlatformPathElement::PathMoveTo:
+ case PlatformPathElement::PathLineTo:
+ ret += String::format("M %f %f\n", i->pointAt(0).m_x, i->pointAt(0).m_y);
+ break;
+ case PlatformPathElement::PathArcTo:
+ ret += String::format("A %f %f %f %f %f %f %c\n"
+ , i->arcTo().m_end.m_x, i->arcTo().m_end.m_y
+ , i->arcTo().m_center.m_x, i->arcTo().m_center.m_y
+ , i->arcTo().m_radius.m_x, i->arcTo().m_radius.m_y
+ , i->arcTo().m_clockwise? 'Y' : 'N');
+ break;
+ case PlatformPathElement::PathQuadCurveTo:
+ ret += String::format("Q %f %f %f %f\n"
+ , i->pointAt(0).m_x, i->pointAt(0).m_y
+ , i->pointAt(1).m_x, i->pointAt(1).m_y);
+ break;
+ case PlatformPathElement::PathBezierCurveTo:
+ ret += String::format("B %f %f %f %f %f %f\n"
+ , i->pointAt(0).m_x, i->pointAt(0).m_y
+ , i->pointAt(1).m_x, i->pointAt(1).m_y
+ , i->pointAt(2).m_x, i->pointAt(2).m_y);
+ break;
+ default:
+ ASSERT(i->platformType() == PlatformPathElement::PathCloseSubpath);
+ ret += "S\n";
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void PlatformPath::apply(void* info, PathApplierFunction function) const
+{
+ PathElement pelement;
+ FloatPoint points[3];
+ pelement.points = points;
+
+ for (PlatformPathElements::const_iterator it(m_elements.begin()); it != m_elements.end(); ++it) {
+ pelement.type = it->type();
+ int n = it->numPoints();
+ for (int i = 0; i < n; ++i)
+ points[i] = it->pointAt(i);
+ function(info, &pelement);
+ }
+}
+
+} // namespace Webcore
diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.h b/WebCore/platform/graphics/wince/PlatformPathWince.h
new file mode 100644
index 0000000..fca00a7
--- /dev/null
+++ b/WebCore/platform/graphics/wince/PlatformPathWince.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef PlatformPathWince_h
+#define PlatformPathWince_h
+
+namespace WebCore {
+
+ class GraphicsContext;
+
+ struct PathPoint {
+ float m_x;
+ float m_y;
+ const float& x() const { return m_x; }
+ const float& y() const { return m_y; }
+ void set(float x, float y)
+ {
+ m_x = x;
+ m_y = y;
+ };
+ operator FloatPoint() const { return FloatPoint(m_x, m_y); }
+ void move(const FloatSize& offset)
+ {
+ m_x += offset.width();
+ m_y += offset.height();
+ }
+ PathPoint& operator=(const FloatPoint& p)
+ {
+ m_x = p.x();
+ m_y = p.y();
+ return *this;
+ }
+ void clear() { m_x = m_y = 0; }
+ };
+
+ struct PathPolygon: public Vector<PathPoint> {
+ void move(const FloatSize& offset);
+ void transform(const TransformationMatrix& t);
+ bool contains(const FloatPoint& point) const;
+ };
+
+ class PlatformPathElement {
+ public:
+ enum PlaformPathElementType {
+ PathMoveTo,
+ PathLineTo,
+ PathArcTo,
+ PathQuadCurveTo,
+ PathBezierCurveTo,
+ PathCloseSubpath,
+ };
+
+ struct MoveTo {
+ PathPoint m_end;
+ };
+
+ struct LineTo {
+ PathPoint m_end;
+ };
+
+ struct ArcTo {
+ PathPoint m_end;
+ PathPoint m_center;
+ PathPoint m_radius;
+ bool m_clockwise;
+ };
+
+ struct QuadCurveTo {
+ PathPoint m_point0;
+ PathPoint m_point1;
+ };
+
+ struct BezierCurveTo {
+ PathPoint m_point0;
+ PathPoint m_point1;
+ PathPoint m_point2;
+ };
+
+ PlatformPathElement(): m_type(PathCloseSubpath) { m_data.m_points[0].set(0, 0); }
+ PlatformPathElement(const MoveTo& data): m_type(PathMoveTo) { m_data.m_moveToData = data; }
+ PlatformPathElement(const LineTo& data): m_type(PathLineTo) { m_data.m_lineToData = data; }
+ PlatformPathElement(const ArcTo& data): m_type(PathArcTo) { m_data.m_arcToData = data; }
+ PlatformPathElement(const QuadCurveTo& data): m_type(PathQuadCurveTo) { m_data.m_quadCurveToData = data; }
+ PlatformPathElement(const BezierCurveTo& data): m_type(PathBezierCurveTo) { m_data.m_bezierCurveToData = data; }
+
+ const MoveTo& moveTo() const { return m_data.m_moveToData; }
+ const LineTo& lineTo() const { return m_data.m_lineToData; }
+ const ArcTo& arcTo() const { return m_data.m_arcToData; }
+ const QuadCurveTo& quadCurveTo() const { return m_data.m_quadCurveToData; }
+ const BezierCurveTo& bezierCurveTo() const { return m_data.m_bezierCurveToData; }
+ const PathPoint& lastPoint() const
+ {
+ int n = numPoints();
+ return n > 1 ? m_data.m_points[n - 1] : m_data.m_points[0];
+ }
+ const PathPoint& pointAt(int index) const { return m_data.m_points[index]; }
+ int numPoints() const;
+ int numControlPoints() const;
+ void move(const FloatSize& offset);
+ void transform(const TransformationMatrix& t);
+ PathElementType type() const;
+ PlaformPathElementType platformType() const { return m_type; }
+ void inflateRectToContainMe(FloatRect& r, const FloatPoint& lastPoint) const;
+
+ private:
+ PlaformPathElementType m_type;
+ union {
+ MoveTo m_moveToData;
+ LineTo m_lineToData;
+ ArcTo m_arcToData;
+ QuadCurveTo m_quadCurveToData;
+ BezierCurveTo m_bezierCurveToData;
+ PathPoint m_points[4];
+ } m_data;
+ };
+
+ typedef Vector<PlatformPathElement> PlatformPathElements;
+
+ class PlatformPath {
+ public:
+ PlatformPath();
+ const PlatformPathElements& elements() const { return m_elements; }
+ void append(const PlatformPathElement& e);
+ void append(const PlatformPath& p);
+ void clear();
+ bool isEmpty() const { return m_elements.isEmpty(); }
+
+ void strokePath(HDC, const TransformationMatrix* tr) const;
+ void fillPath(HDC, const TransformationMatrix* tr) const;
+ FloatPoint lastPoint() const { return m_elements.isEmpty() ? FloatPoint(0, 0) : m_elements.last().lastPoint(); }
+
+ const FloatRect& boundingRect() const { return m_boundingRect; }
+ bool contains(const FloatPoint& point, WindRule rule) const;
+ void translate(const FloatSize& size);
+ void transform(const TransformationMatrix& t);
+
+ void moveTo(const FloatPoint&);
+ void addLineTo(const FloatPoint&);
+ void addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& point);
+ void addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint&);
+ void addArcTo(const FloatPoint&, const FloatPoint&, float radius);
+ void closeSubpath();
+ void addEllipse(const FloatPoint& p, float a, float b, float sar, float ear, bool anticlockwise);
+ void addRect(const FloatRect& r);
+ void addEllipse(const FloatRect& r);
+ String debugString() const;
+ void apply(void* info, PathApplierFunction function) const;
+
+ private:
+ void ensureSubpath();
+ void addToSubpath(const PlatformPathElement& e);
+
+ PlatformPathElements m_elements;
+ FloatRect m_boundingRect;
+ Vector<PathPolygon> m_subpaths;
+ PathPoint m_currentPoint;
+ bool m_penLifted;
+ };
+
+}
+
+#endif // PlatformPathWince_h
diff --git a/WebCore/platform/graphics/wince/WinceGraphicsExtras.h b/WebCore/platform/graphics/wince/WinceGraphicsExtras.h
new file mode 100644
index 0000000..2a6fae1
--- /dev/null
+++ b/WebCore/platform/graphics/wince/WinceGraphicsExtras.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef WinceGraphicsExtras_h
+#define WinceGraphicsExtras_h
+
+// This file is used to contain small utilities used by WINCE graphics code.
+
+namespace WebCore {
+ // Always round to same direction. 0.5 is rounded to 1,
+ // and -0.5 (0.5 - 1) is rounded to 0 (1 - 1), so that it
+ // is consistent when transformation shifts.
+ static inline int stableRound(double d)
+ {
+ if (d > 0)
+ return static_cast<int>(d + 0.5);
+
+ int i = static_cast<int>(d);
+ return i - d > 0.5 ? i - 1 : i;
+ }
+}
+
+#endif WinceGraphicsExtras_h
diff --git a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
index de92fcd..fd3322f 100644
--- a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
+++ b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
@@ -111,7 +111,7 @@ unsigned FontPlatformData::computeHash() const {
// a font whose properties are equal should generate the same hash
uintptr_t hashCodes[6] = { thisFont->GetPointSize(), thisFont->GetFamily(), thisFont->GetStyle(),
thisFont->GetWeight(), thisFont->GetUnderlined(),
- StringImpl::computeHash(thisFont->GetFaceName().mb_str(wxConvUTF8)) };
+ StringImpl::computeHash(thisFont->GetFaceName().utf8_str()) };
return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
}
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 59e388e..9c05ce5 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -119,8 +119,8 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
setPaintingDisabled(!context);
if (context) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), DeviceColorSpace);
+ setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
}
#if USE(WXGC)
m_data->context = (wxGCDC*)context;
@@ -252,7 +252,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
delete [] polygon;
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -262,7 +262,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
}
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -344,6 +344,11 @@ void GraphicsContext::clip(const Path&)
notImplemented();
}
+void GraphicsContext::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
{
notImplemented();
@@ -433,7 +438,7 @@ void GraphicsContext::addPath(const Path& path)
notImplemented();
}
-void GraphicsContext::setPlatformStrokeColor(const Color& color)
+void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -452,7 +457,7 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness)
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -506,4 +511,127 @@ void GraphicsContext::fillRect(const FloatRect& rect)
return;
}
+void GraphicsContext::setPlatformShadow(IntSize const&,int,Color const&, ColorSpace)
+{
+ notImplemented();
+}
+
+void GraphicsContext::clearPlatformShadow()
+{
+ notImplemented();
+}
+
+void GraphicsContext::beginTransparencyLayer(float)
+{
+ notImplemented();
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+ notImplemented();
+}
+
+void GraphicsContext::clearRect(const FloatRect&)
+{
+ notImplemented();
+}
+
+void GraphicsContext::strokeRect(const FloatRect&, float)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setLineCap(LineCap)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setLineJoin(LineJoin)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setMiterLimit(float)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setAlpha(float)
+{
+ notImplemented();
+}
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
+{
+ notImplemented();
+}
+
+#if PLATFORM(WIN_OS)
+HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
+{
+ if (dstRect.isEmpty())
+ return 0;
+
+ // Create a bitmap DC in which to draw.
+ BITMAPINFO bitmapInfo;
+ bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bitmapInfo.bmiHeader.biWidth = dstRect.width();
+ bitmapInfo.bmiHeader.biHeight = dstRect.height();
+ bitmapInfo.bmiHeader.biPlanes = 1;
+ bitmapInfo.bmiHeader.biBitCount = 32;
+ bitmapInfo.bmiHeader.biCompression = BI_RGB;
+ bitmapInfo.bmiHeader.biSizeImage = 0;
+ bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biClrUsed = 0;
+ bitmapInfo.bmiHeader.biClrImportant = 0;
+
+ void* pixels = 0;
+ HBITMAP bitmap = ::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
+ if (!bitmap)
+ return 0;
+
+ HDC displayDC = ::GetDC(0);
+ HDC bitmapDC = ::CreateCompatibleDC(displayDC);
+ ::ReleaseDC(0, displayDC);
+
+ ::SelectObject(bitmapDC, bitmap);
+
+ // Fill our buffer with clear if we're going to alpha blend.
+ if (supportAlphaBlend) {
+ BITMAP bmpInfo;
+ GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
+ int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+ memset(bmpInfo.bmBits, 0, bufferSize);
+ }
+ return bitmapDC;
+}
+
+void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
+{
+ if (hdc) {
+
+ if (!dstRect.isEmpty()) {
+
+ HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+ BITMAP info;
+ GetObject(bitmap, sizeof(info), &info);
+ ASSERT(info.bmBitsPixel == 32);
+
+ wxBitmap bmp;
+ bmp.SetHBITMAP(bitmap);
+#if !wxCHECK_VERSION(2,9,0)
+ if (supportAlphaBlend)
+ bmp.UseAlpha();
+#endif
+ m_data->context->DrawBitmap(bmp, dstRect.x(), dstRect.y(), supportAlphaBlend);
+
+ ::DeleteObject(bitmap);
+ }
+
+ ::DeleteDC(hdc);
+ }
+}
+#endif
+
}
diff --git a/WebCore/platform/graphics/wx/IconWx.cpp b/WebCore/platform/graphics/wx/IconWx.cpp
new file mode 100644
index 0000000..d3cc961
--- /dev/null
+++ b/WebCore/platform/graphics/wx/IconWx.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 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
+ * 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 "Icon.h"
+
+#include "GraphicsContext.h"
+#include "PlatformString.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+Icon::~Icon()
+{
+}
+
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
+{
+ notImplemented();
+ return 0;
+}
+
+void Icon::paint(GraphicsContext* ctx, const IntRect& rect)
+{
+ notImplemented();
+}
+
+}
+
diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
index e71dbde..49f3f3b 100644
--- a/WebCore/platform/graphics/wx/ImageBufferWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
@@ -53,13 +53,24 @@ GraphicsContext* ImageBuffer::context() const
return 0;
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
notImplemented();
return 0;
}
-void ImageBuffer::putImageData(ImageData*, const IntRect&, const IntPoint&)
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ notImplemented();
+ return 0;
+}
+
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ notImplemented();
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
{
notImplemented();
}
diff --git a/WebCore/platform/graphics/wx/ImageSourceWx.cpp b/WebCore/platform/graphics/wx/ImageSourceWx.cpp
deleted file mode 100644
index 06c165d..0000000
--- a/WebCore/platform/graphics/wx/ImageSourceWx.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Computer, Kevin Ollivier. 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 "ImageSource.h"
-
-#include "BMPImageDecoder.h"
-#include "GIFImageDecoder.h"
-#include "ICOImageDecoder.h"
-#include "JPEGImageDecoder.h"
-#include "NotImplemented.h"
-#include "PNGImageDecoder.h"
-#include "SharedBuffer.h"
-#include "XBMImageDecoder.h"
-
-#include <wx/defs.h>
-#include <wx/bitmap.h>
-#if USE(WXGC)
-#include <wx/graphics.h>
-#endif
-#include <wx/image.h>
-#include <wx/rawbmp.h>
-
-namespace WebCore {
-
-ImageDecoder* createDecoder(const SharedBuffer& data)
-{
- // 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();
-
- // 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);
-}
-
-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)
- delete m_decoder;
- m_decoder = createDecoder(*data);
- if (!m_decoder)
- 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 index) const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->frameSizeAtIndex(index);
-}
-
-int ImageSource::repetitionCount()
-{
- if (!m_decoder)
- return cAnimationNone;
-
- return m_decoder->repetitionCount();
-}
-
-String ImageSource::filenameExtension() const
-{
- notImplemented();
- return String();
-}
-
-size_t ImageSource::frameCount() const
-{
- return m_decoder ? m_decoder->frameCount() : 0;
-}
-
-bool ImageSource::frameIsCompleteAtIndex(size_t index)
-{
- // FIXME: should we be testing the RGBA32Buffer's status as well?
- return (m_decoder && m_decoder->frameBufferAtIndex(index) != 0);
-}
-
-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);
-}
-
-NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
-{
- if (!m_decoder)
- return 0;
-
- RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
- if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
- return 0;
-
- return buffer->asNewNativeImage();
-}
-
-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;
-
- float duration = buffer->duration() / 1000.0f;
-
- // Follow other ports (and WinIE's) behavior to slow annoying ads that
- // specify a 0 duration.
- if (duration < 0.051f)
- return 0.100f;
- return 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();
-}
-
-}
diff --git a/WebCore/platform/graphics/wx/ImageWx.cpp b/WebCore/platform/graphics/wx/ImageWx.cpp
index b0a993e..ff60d6f 100644
--- a/WebCore/platform/graphics/wx/ImageWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageWx.cpp
@@ -31,6 +31,7 @@
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "ImageObserver.h"
+#include "NotImplemented.h"
#include "TransformationMatrix.h"
#include <math.h>
@@ -45,9 +46,6 @@
#include <wx/image.h>
#include <wx/thread.h>
-// This function loads resources from WebKit
-Vector<char> loadResourceIntoArray(const char*);
-
namespace WebCore {
// this is in GraphicsContextWx.cpp
@@ -72,7 +70,9 @@ bool FrameData::clear(bool clearMetadata)
PassRefPtr<Image> Image::loadPlatformResource(const char *name)
{
- Vector<char> arr = loadResourceIntoArray(name);
+ // FIXME: We need to have some 'placeholder' graphics for things like missing
+ // plugins or broken images.
+ Vector<char> arr;
RefPtr<Image> img = BitmapImage::create();
RefPtr<SharedBuffer> buffer = SharedBuffer::create(arr.data(), arr.size());
img->setData(buffer, true);
@@ -86,13 +86,13 @@ void BitmapImage::initPlatformData()
// Drawing Routines
-void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
if (!m_source.initialized())
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, dst, solidColor(), op);
+ fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
return;
}
@@ -176,7 +176,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
observer->didDraw(this);
}
-void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& dstRect)
+void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& dstRect)
{
if (!m_source.initialized())
return;
@@ -261,4 +261,9 @@ void BitmapImage::invalidatePlatformData()
}
+void Image::drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& destRect)
+{
+ notImplemented();
+}
+
}
diff --git a/WebCore/platform/graphics/wx/IntSizeWx.cpp b/WebCore/platform/graphics/wx/IntSizeWx.cpp
new file mode 100644
index 0000000..8c82854
--- /dev/null
+++ b/WebCore/platform/graphics/wx/IntSizeWx.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 Kevin Watters. 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 "IntSize.h"
+
+#include <wx/defs.h>
+#include <wx/gdicmn.h>
+
+namespace WebCore {
+
+IntSize::IntSize(const wxSize& s)
+ : m_width(s.x)
+ , m_height(s.y)
+{
+}
+
+IntSize::operator wxSize() const
+{
+ return wxSize(m_width, m_height);
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
index 2368f83..85979de 100644
--- a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
+++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
@@ -67,6 +67,7 @@ void SimpleFontData::platformCharWidthInit()
void SimpleFontData::platformDestroy()
{
delete m_smallCapsFontData;
+ m_smallCapsFontData = 0;
}
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const