summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-04-27 16:31:00 +0100
committerSteve Block <steveblock@google.com>2010-05-11 14:42:12 +0100
commitdcc8cf2e65d1aa555cce12431a16547e66b469ee (patch)
tree92a8d65cd5383bca9749f5327fb5e440563926e6 /WebCore/platform/graphics
parentccac38a6b48843126402088a309597e682f40fe6 (diff)
downloadexternal_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'WebCore/platform/graphics')
-rw-r--r--WebCore/platform/graphics/BitmapImage.cpp26
-rw-r--r--WebCore/platform/graphics/Color.h1
-rw-r--r--WebCore/platform/graphics/FloatPoint.h4
-rw-r--r--WebCore/platform/graphics/FloatRect.h9
-rw-r--r--WebCore/platform/graphics/FloatSize.h1
-rw-r--r--WebCore/platform/graphics/Font.cpp7
-rw-r--r--WebCore/platform/graphics/Font.h21
-rw-r--r--WebCore/platform/graphics/FontFastPath.cpp11
-rw-r--r--WebCore/platform/graphics/GlyphMetricsMap.cpp (renamed from WebCore/platform/graphics/GlyphWidthMap.cpp)22
-rw-r--r--WebCore/platform/graphics/GlyphMetricsMap.h (renamed from WebCore/platform/graphics/GlyphWidthMap.h)57
-rw-r--r--WebCore/platform/graphics/GlyphPageTreeNode.cpp4
-rw-r--r--WebCore/platform/graphics/Gradient.h6
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h2
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.cpp23
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.h60
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.cpp74
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.h27
-rw-r--r--WebCore/platform/graphics/Icon.h7
-rw-r--r--WebCore/platform/graphics/Image.cpp5
-rw-r--r--WebCore/platform/graphics/Image.h4
-rw-r--r--WebCore/platform/graphics/IntPoint.h15
-rw-r--r--WebCore/platform/graphics/IntPointHash.h48
-rw-r--r--WebCore/platform/graphics/IntRect.h10
-rw-r--r--WebCore/platform/graphics/IntSize.h2
-rw-r--r--WebCore/platform/graphics/MediaPlayer.cpp48
-rw-r--r--WebCore/platform/graphics/MediaPlayer.h17
-rw-r--r--WebCore/platform/graphics/MediaPlayerPrivate.h2
-rw-r--r--WebCore/platform/graphics/Path.cpp2
-rw-r--r--WebCore/platform/graphics/Path.h5
-rw-r--r--WebCore/platform/graphics/Pattern.h3
-rw-r--r--WebCore/platform/graphics/SimpleFontData.cpp8
-rw-r--r--WebCore/platform/graphics/SimpleFontData.h31
-rw-r--r--WebCore/platform/graphics/Tile.h78
-rw-r--r--WebCore/platform/graphics/TiledBackingStore.cpp378
-rw-r--r--WebCore/platform/graphics/TiledBackingStore.h110
-rw-r--r--WebCore/platform/graphics/TiledBackingStoreClient.h40
-rw-r--r--WebCore/platform/graphics/cairo/FontCacheCairo.cpp (renamed from WebCore/platform/graphics/gtk/FontCacheGtk.cpp)0
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp7
-rw-r--r--WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp (renamed from WebCore/platform/graphics/gtk/FontCustomPlatformData.cpp)0
-rw-r--r--WebCore/platform/graphics/cairo/FontCustomPlatformData.h (renamed from WebCore/platform/graphics/gtk/FontCustomPlatformData.h)0
-rw-r--r--WebCore/platform/graphics/cairo/FontPlatformData.h (renamed from WebCore/platform/graphics/gtk/FontPlatformData.h)55
-rw-r--r--WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp (renamed from WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp)6
-rw-r--r--WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp (renamed from WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp)0
-rw-r--r--WebCore/platform/graphics/cairo/PathCairo.cpp5
-rw-r--r--WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp (renamed from WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp)7
-rw-r--r--WebCore/platform/graphics/cg/FontPlatformData.h (renamed from WebCore/platform/graphics/win/FontPlatformData.h)79
-rw-r--r--WebCore/platform/graphics/cg/GradientCG.cpp2
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h1
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp5
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp31
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.cpp7
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.h2
-rw-r--r--WebCore/platform/graphics/cg/PathCG.cpp4
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp13
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheLinux.cpp7
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/FontLinux.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp47
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.h8
-rw-r--r--WebCore/platform/graphics/chromium/FontRenderStyle.h56
-rw-r--r--WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp28
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp561
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.h149
-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.cpp7
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.cpp251
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.h227
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.cpp138
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.h84
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp9
-rw-r--r--WebCore/platform/graphics/chromium/UniscribeHelper.cpp1
-rw-r--r--WebCore/platform/graphics/efl/FloatRectEfl.cpp41
-rw-r--r--WebCore/platform/graphics/efl/FontEfl.cpp66
-rw-r--r--WebCore/platform/graphics/efl/IconEfl.cpp (renamed from WebCore/platform/graphics/win/FontDatabase.h)40
-rw-r--r--WebCore/platform/graphics/efl/ImageEfl.cpp68
-rw-r--r--WebCore/platform/graphics/efl/IntPointEfl.cpp42
-rw-r--r--WebCore/platform/graphics/efl/IntRectEfl.cpp41
-rw-r--r--WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp (renamed from WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp)0
-rw-r--r--WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h (renamed from WebCore/platform/graphics/gtk/DataSourceGStreamer.h)0
-rw-r--r--WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp35
-rw-r--r--WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h33
-rw-r--r--WebCore/platform/graphics/gstreamer/ImageGStreamer.h62
-rw-r--r--WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp72
-rw-r--r--WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (renamed from WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp)439
-rw-r--r--WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h (renamed from WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h)37
-rw-r--r--WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp (renamed from WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp)6
-rw-r--r--WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h (renamed from WebCore/platform/graphics/gtk/VideoSinkGStreamer.h)0
-rw-r--r--WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp (renamed from WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp)30
-rw-r--r--WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h (renamed from WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h)0
-rw-r--r--WebCore/platform/graphics/gtk/FontGtk.cpp2
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp4
-rw-r--r--WebCore/platform/graphics/gtk/IconGtk.cpp2
-rw-r--r--WebCore/platform/graphics/gtk/ImageGtk.cpp77
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp7
-rw-r--r--WebCore/platform/graphics/haiku/FontCacheHaiku.cpp12
-rw-r--r--WebCore/platform/graphics/haiku/FontHaiku.cpp2
-rw-r--r--WebCore/platform/graphics/haiku/GradientHaiku.cpp34
-rw-r--r--WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp2
-rw-r--r--WebCore/platform/graphics/haiku/ImageHaiku.cpp3
-rw-r--r--WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp6
-rw-r--r--WebCore/platform/graphics/haiku/StillImageHaiku.cpp78
-rw-r--r--WebCore/platform/graphics/haiku/StillImageHaiku.h58
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.h4
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.mm11
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextController.cpp22
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextController.h10
-rw-r--r--WebCore/platform/graphics/mac/FontComplexTextMac.cpp10
-rw-r--r--WebCore/platform/graphics/mac/FontMac.mm37
-rw-r--r--WebCore/platform/graphics/mac/FontPlatformData.h5
-rw-r--r--WebCore/platform/graphics/mac/FontPlatformDataMac.mm12
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp254
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.h1
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm35
-rw-r--r--WebCore/platform/graphics/mac/ImageMac.mm1
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h10
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm36
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerProxy.h4
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm22
-rw-r--r--WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp24
-rw-r--r--WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h1
-rw-r--r--WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp63
-rw-r--r--WebCore/platform/graphics/openvg/PainterOpenVG.cpp297
-rw-r--r--WebCore/platform/graphics/openvg/PainterOpenVG.h30
-rw-r--r--WebCore/platform/graphics/openvg/PathOpenVG.cpp502
-rw-r--r--WebCore/platform/graphics/openvg/PlatformPathOpenVG.h53
-rw-r--r--WebCore/platform/graphics/openvg/SharedResourceOpenVG.cpp45
-rw-r--r--WebCore/platform/graphics/openvg/SharedResourceOpenVG.h33
-rw-r--r--WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp28
-rw-r--r--WebCore/platform/graphics/openvg/SurfaceOpenVG.h22
-rw-r--r--WebCore/platform/graphics/openvg/VGUtils.cpp43
-rw-r--r--WebCore/platform/graphics/openvg/VGUtils.h3
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformDataQt.cpp3
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp19
-rw-r--r--WebCore/platform/graphics/qt/GradientQt.cpp10
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp1651
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp41
-rw-r--r--WebCore/platform/graphics/qt/GraphicsLayerQt.cpp392
-rw-r--r--WebCore/platform/graphics/qt/GraphicsLayerQt.h3
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp75
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.h4
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp67
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h1
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp571
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h133
-rw-r--r--WebCore/platform/graphics/qt/PathQt.cpp4
-rw-r--r--WebCore/platform/graphics/qt/StillImageQt.cpp37
-rw-r--r--WebCore/platform/graphics/qt/TileQt.cpp178
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp12
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp3
-rw-r--r--WebCore/platform/graphics/transforms/AffineTransform.cpp18
-rw-r--r--WebCore/platform/graphics/transforms/AffineTransform.h10
-rw-r--r--WebCore/platform/graphics/win/FontCGWin.cpp9
-rw-r--r--WebCore/platform/graphics/win/FontCacheWin.cpp73
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformData.cpp45
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformData.h6
-rw-r--r--WebCore/platform/graphics/win/FontDatabase.cpp217
-rw-r--r--WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp28
-rw-r--r--WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp18
-rw-r--r--WebCore/platform/graphics/win/FontWin.cpp10
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.cpp137
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.h2
-rw-r--r--WebCore/platform/graphics/win/ImageCGWin.cpp5
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp113
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h5
-rwxr-xr-xWebCore/platform/graphics/win/RefCountedHFONT.h56
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp18
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataWin.cpp17
-rw-r--r--WebCore/platform/graphics/win/UniscribeController.cpp34
-rw-r--r--WebCore/platform/graphics/win/UniscribeController.h10
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.cpp256
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.h23
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp208
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayerRenderer.h23
-rw-r--r--WebCore/platform/graphics/wince/FontCustomPlatformData.cpp1
-rw-r--r--WebCore/platform/graphics/wince/FontPlatformData.cpp2
-rw-r--r--WebCore/platform/graphics/wince/FontWince.cpp2
-rw-r--r--WebCore/platform/graphics/wince/GraphicsContextWince.cpp1
-rw-r--r--WebCore/platform/graphics/wince/ImageBufferWince.cpp1
-rw-r--r--WebCore/platform/graphics/wince/PlatformPathWince.h5
-rw-r--r--WebCore/platform/graphics/wx/FontPlatformData.h11
-rw-r--r--WebCore/platform/graphics/wx/FontPlatformDataWx.cpp1
-rw-r--r--WebCore/platform/graphics/wx/FontWx.cpp2
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp51
-rw-r--r--WebCore/platform/graphics/wx/ImageBufferWx.cpp5
-rw-r--r--WebCore/platform/graphics/wx/ImageWx.cpp1
-rw-r--r--WebCore/platform/graphics/wx/PathWx.cpp23
-rw-r--r--WebCore/platform/graphics/wx/SimpleFontDataWx.cpp8
191 files changed, 9037 insertions, 1529 deletions
diff --git a/WebCore/platform/graphics/BitmapImage.cpp b/WebCore/platform/graphics/BitmapImage.cpp
index 0cd3907..e3db752 100644
--- a/WebCore/platform/graphics/BitmapImage.cpp
+++ b/WebCore/platform/graphics/BitmapImage.cpp
@@ -270,6 +270,11 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary)
if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)
return;
+ // If we aren't already animating, set now as the animation start time.
+ const double time = currentTime();
+ if (!m_desiredFrameStartTime)
+ m_desiredFrameStartTime = time;
+
// Don't advance the animation to an incomplete frame.
size_t nextFrame = (m_currentFrame + 1) % frameCount();
if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame))
@@ -286,19 +291,14 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary)
// in this calculation, we make the animation appear to run at its desired
// rate regardless of how fast it's being repainted.
const double currentDuration = frameDurationAtIndex(m_currentFrame);
- const double time = currentTime();
- if (m_desiredFrameStartTime == 0) {
+ m_desiredFrameStartTime += currentDuration;
+
+ // When an animated image is more than five minutes out of date, the
+ // user probably doesn't care about resyncing and we could burn a lot of
+ // time looping through frames below. Just reset the timings.
+ const double cAnimationResyncCutoff = 5 * 60;
+ if ((time - m_desiredFrameStartTime) > cAnimationResyncCutoff)
m_desiredFrameStartTime = time + currentDuration;
- } else {
- m_desiredFrameStartTime += currentDuration;
-
- // When an animated image is more than five minutes out of date, the
- // user probably doesn't care about resyncing and we could burn a lot of
- // time looping through frames below. Just reset the timings.
- const double cAnimationResyncCutoff = 5 * 60;
- if ((time - m_desiredFrameStartTime) > cAnimationResyncCutoff)
- m_desiredFrameStartTime = time + currentDuration;
- }
// The image may load more slowly than it's supposed to animate, so that by
// the time we reach the end of the first repetition, we're well behind.
@@ -311,7 +311,7 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary)
// switch tabs (and thus stop drawing the animation, which will pause it)
// during that initial loop, then switch back later.
if (nextFrame == 0 && m_repetitionsComplete == 0 && m_desiredFrameStartTime < time)
- m_desiredFrameStartTime = time;
+ m_desiredFrameStartTime = time;
if (!catchUpIfNecessary || time < m_desiredFrameStartTime) {
// Haven't yet reached time for next frame to start; delay until then.
diff --git a/WebCore/platform/graphics/Color.h b/WebCore/platform/graphics/Color.h
index c348166..b8d19e0 100644
--- a/WebCore/platform/graphics/Color.h
+++ b/WebCore/platform/graphics/Color.h
@@ -27,7 +27,6 @@
#define Color_h
#include <wtf/FastAllocBase.h>
-#include <wtf/Platform.h>
#if PLATFORM(CG)
typedef struct CGColor* CGColorRef;
diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h
index bf568d4..7443e97 100644
--- a/WebCore/platform/graphics/FloatPoint.h
+++ b/WebCore/platform/graphics/FloatPoint.h
@@ -30,7 +30,6 @@
#include "FloatSize.h"
#include "IntPoint.h"
#include <wtf/MathExtras.h>
-#include <wtf/Platform.h>
#if PLATFORM(CG)
typedef struct CGPoint CGPoint;
@@ -71,6 +70,9 @@ public:
FloatPoint(float x, float y) : m_x(x), m_y(y) { }
FloatPoint(const IntPoint&);
+
+ static FloatPoint zero() { return FloatPoint(); }
+
static FloatPoint narrowPrecision(double x, double y);
float x() const { return m_x; }
diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h
index b265121..4c3a382 100644
--- a/WebCore/platform/graphics/FloatRect.h
+++ b/WebCore/platform/graphics/FloatRect.h
@@ -29,6 +29,10 @@
#include "FloatPoint.h"
+#if PLATFORM(EFL)
+#include <Evas.h>
+#endif
+
#if PLATFORM(CG)
typedef struct CGRect CGRect;
#endif
@@ -145,6 +149,11 @@ public:
operator QRectF() const;
#endif
+#if PLATFORM(EFL)
+ explicit FloatRect(const Eina_Rectangle&);
+ operator Eina_Rectangle() const;
+#endif
+
#if PLATFORM(WX) && USE(WXGC)
FloatRect(const wxRect2DDouble&);
operator wxRect2DDouble() const;
diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h
index a3233d1..97ee00d 100644
--- a/WebCore/platform/graphics/FloatSize.h
+++ b/WebCore/platform/graphics/FloatSize.h
@@ -30,7 +30,6 @@
#include "IntSize.h"
#include <wtf/MathExtras.h>
-#include <wtf/Platform.h>
#if PLATFORM(CG)
typedef struct CGSize CGSize;
diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp
index 7d0e5a9..7bdefba 100644
--- a/WebCore/platform/graphics/Font.cpp
+++ b/WebCore/platform/graphics/Font.cpp
@@ -182,7 +182,7 @@ void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoi
return drawComplexText(context, run, point, from, to);
}
-float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
#if ENABLE(SVG_FONTS)
if (primaryFont()->isSVGFont())
@@ -198,7 +198,7 @@ float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallb
}
#endif
- return floatWidthForComplexText(run, fallbackFonts);
+ return floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
}
float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
@@ -267,12 +267,13 @@ FontSelector* Font::fontSelector() const
String Font::normalizeSpaces(const String& string)
{
+ const UChar* characters = string.characters();
unsigned length = string.length();
Vector<UChar, 256> buffer(length);
bool didReplacement = false;
for (unsigned i = 0; i < length; ++i) {
- UChar originalCharacter = string[i];
+ UChar originalCharacter = characters[i];
buffer[i] = normalizeSpaces(originalCharacter);
if (buffer[i] != originalCharacter)
didReplacement = true;
diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h
index 3c07be7..62525b0 100644
--- a/WebCore/platform/graphics/Font.h
+++ b/WebCore/platform/graphics/Font.h
@@ -56,6 +56,21 @@ struct GlyphData;
const unsigned defaultUnitsPerEm = 1000;
+struct GlyphOverflow {
+ GlyphOverflow()
+ : left(0)
+ , right(0)
+ , top(0)
+ , bottom(0)
+ {
+ }
+
+ int left;
+ int right;
+ int top;
+ int bottom;
+};
+
class Font {
public:
Font();
@@ -81,8 +96,8 @@ public:
void drawText(GraphicsContext*, const TextRun&, const FloatPoint&, int from = 0, int to = -1) const;
- int width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0) const { return lroundf(floatWidth(run, fallbackFonts)); }
- float floatWidth(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0) const;
+ int width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* glyphOverflow = 0) const { return lroundf(floatWidth(run, fallbackFonts, glyphOverflow)); }
+ float floatWidth(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* glyphOverflow = 0) const;
float floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const;
int offsetForPosition(const TextRun&, int position, bool includePartialGlyphs) const;
@@ -159,7 +174,7 @@ private:
#endif
void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
- float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0) const;
+ float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
int offsetForPositionForComplexText(const TextRun&, int position, bool includePartialGlyphs) const;
FloatRect selectionRectForComplexText(const TextRun&, const IntPoint&, int h, int from, int to) const;
diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp
index 428e85e..6e2a744 100644
--- a/WebCore/platform/graphics/FontFastPath.cpp
+++ b/WebCore/platform/graphics/FontFastPath.cpp
@@ -24,17 +24,17 @@
#include "Font.h"
#include "CharacterNames.h"
+#include "FloatRect.h"
#include "FontCache.h"
#include "FontFallbackList.h"
-#include "FloatRect.h"
#include "GlyphBuffer.h"
#include "GlyphPageTreeNode.h"
#include "IntPoint.h"
#include "SimpleFontData.h"
#include "WidthIterator.h"
-#include <wtf/unicode/Unicode.h>
#include <wtf/MathExtras.h>
+#include <wtf/unicode/Unicode.h>
using namespace WTF;
using namespace Unicode;
@@ -234,6 +234,13 @@ bool Font::canUseGlyphCache(const TextRun& run) const
if (c <= 0x194F)
return false;
+ // FIXME: we should not use complex text path for these characters.
+
+ if (c < 0x1E00) // U+1E00 through U+2000 characters with diacritics and stacked diacritics
+ continue;
+ if (c <= 0x2000)
+ return false;
+
if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
continue;
if (c <= 0x20FF)
diff --git a/WebCore/platform/graphics/GlyphWidthMap.cpp b/WebCore/platform/graphics/GlyphMetricsMap.cpp
index 43cab65..d3c3180 100644
--- a/WebCore/platform/graphics/GlyphWidthMap.cpp
+++ b/WebCore/platform/graphics/GlyphMetricsMap.cpp
@@ -27,14 +27,14 @@
*/
#include "config.h"
-#include "GlyphWidthMap.h"
+#include "GlyphMetricsMap.h"
namespace WebCore {
-GlyphWidthMap::GlyphWidthPage* GlyphWidthMap::locatePageSlowCase(unsigned pageNumber)
+GlyphMetricsMap::GlyphMetricsPage* GlyphMetricsMap::locatePageSlowCase(unsigned pageNumber)
{
- GlyphWidthPage* page;
- if (pageNumber == 0) {
+ GlyphMetricsPage* page;
+ if (!pageNumber) {
ASSERT(!m_filledPrimaryPage);
page = &m_primaryPage;
m_filledPrimaryPage = true;
@@ -43,14 +43,18 @@ GlyphWidthMap::GlyphWidthPage* GlyphWidthMap::locatePageSlowCase(unsigned pageNu
if ((page = m_pages->get(pageNumber)))
return page;
} else
- m_pages.set(new HashMap<int, GlyphWidthPage*>);
- page = new GlyphWidthPage;
+ m_pages.set(new HashMap<int, GlyphMetricsPage*>);
+ page = new GlyphMetricsPage;
m_pages->set(pageNumber, page);
}
- // Fill in the whole page with the unknown glyph width value.
- for (unsigned i = 0; i < GlyphWidthPage::size; i++)
- page->setWidthForIndex(i, cGlyphWidthUnknown);
+ GlyphMetrics unknownMetrics;
+ unknownMetrics.horizontalAdvance = cGlyphSizeUnknown;
+ unknownMetrics.boundingBox.setWidth(cGlyphSizeUnknown);
+ unknownMetrics.boundingBox.setHeight(cGlyphSizeUnknown);
+ // Fill in the whole page with the unknown glyph information.
+ for (unsigned i = 0; i < GlyphMetricsPage::size; i++)
+ page->setMetricsForIndex(i, unknownMetrics);
return page;
}
diff --git a/WebCore/platform/graphics/GlyphWidthMap.h b/WebCore/platform/graphics/GlyphMetricsMap.h
index 66dea1f..49854be 100644
--- a/WebCore/platform/graphics/GlyphWidthMap.h
+++ b/WebCore/platform/graphics/GlyphMetricsMap.h
@@ -26,9 +26,10 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef GlyphWidthMap_h
-#define GlyphWidthMap_h
+#ifndef GlyphMetricsMap_h
+#define GlyphMetricsMap_h
+#include "FloatRect.h"
#include <wtf/HashMap.h>
#include <wtf/OwnPtr.h>
#include <wtf/unicode/Unicode.h>
@@ -37,53 +38,67 @@ namespace WebCore {
typedef unsigned short Glyph;
-const float cGlyphWidthUnknown = -1;
+const float cGlyphSizeUnknown = -1;
-class GlyphWidthMap : public Noncopyable {
+struct GlyphMetrics {
+ float horizontalAdvance;
+ FloatRect boundingBox;
+};
+
+class GlyphMetricsMap : public Noncopyable {
public:
- GlyphWidthMap() : m_filledPrimaryPage(false) { }
- ~GlyphWidthMap() { if (m_pages) { deleteAllValues(*m_pages); } }
+ GlyphMetricsMap() : m_filledPrimaryPage(false) { }
+ ~GlyphMetricsMap()
+ {
+ if (m_pages)
+ deleteAllValues(*m_pages);
+ }
+
+ GlyphMetrics metricsForGlyph(Glyph glyph)
+ {
+ return locatePage(glyph / GlyphMetricsPage::size)->metricsForGlyph(glyph);
+ }
float widthForGlyph(Glyph glyph)
{
- return locatePage(glyph / GlyphWidthPage::size)->widthForGlyph(glyph);
+ return locatePage(glyph / GlyphMetricsPage::size)->metricsForGlyph(glyph).horizontalAdvance;
}
- void setWidthForGlyph(Glyph glyph, float width)
+ void setMetricsForGlyph(Glyph glyph, const GlyphMetrics& metrics)
{
- locatePage(glyph / GlyphWidthPage::size)->setWidthForGlyph(glyph, width);
+ locatePage(glyph / GlyphMetricsPage::size)->setMetricsForGlyph(glyph, metrics);
}
private:
- struct GlyphWidthPage {
+ struct GlyphMetricsPage {
static const size_t size = 256; // Usually covers Latin-1 in a single page.
- float m_widths[size];
+ GlyphMetrics m_metrics[size];
- float widthForGlyph(Glyph glyph) const { return m_widths[glyph % size]; }
- void setWidthForGlyph(Glyph glyph, float width)
+ GlyphMetrics metricsForGlyph(Glyph glyph) const { return m_metrics[glyph % size]; }
+ void setMetricsForGlyph(Glyph glyph, const GlyphMetrics& metrics)
{
- setWidthForIndex(glyph % size, width);
+ setMetricsForIndex(glyph % size, metrics);
}
- void setWidthForIndex(unsigned index, float width)
+ void setMetricsForIndex(unsigned index, const GlyphMetrics& metrics)
{
- m_widths[index] = width;
+ m_metrics[index] = metrics;
}
};
- GlyphWidthPage* locatePage(unsigned pageNumber)
+ GlyphMetricsPage* locatePage(unsigned pageNumber)
{
if (!pageNumber && m_filledPrimaryPage)
return &m_primaryPage;
return locatePageSlowCase(pageNumber);
}
- GlyphWidthPage* locatePageSlowCase(unsigned pageNumber);
+ GlyphMetricsPage* locatePageSlowCase(unsigned pageNumber);
bool m_filledPrimaryPage;
- GlyphWidthPage m_primaryPage; // We optimize for the page that contains glyph indices 0-255.
- OwnPtr<HashMap<int, GlyphWidthPage*> > m_pages;
+ GlyphMetricsPage m_primaryPage; // We optimize for the page that contains glyph indices 0-255.
+ OwnPtr<HashMap<int, GlyphMetricsPage*> > m_pages;
};
-}
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
index 9f53f0b..59a5efb 100644
--- a/WebCore/platform/graphics/GlyphPageTreeNode.cpp
+++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
@@ -29,10 +29,12 @@
#include "config.h"
#include "GlyphPageTreeNode.h"
-#include "CString.h"
#include "CharacterNames.h"
+#include "PlatformString.h"
#include "SegmentedFontData.h"
#include "SimpleFontData.h"
+#include <stdio.h>
+#include <wtf/text/CString.h>
#include <wtf/unicode/Unicode.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h
index 0efd3bf..371cad7 100644
--- a/WebCore/platform/graphics/Gradient.h
+++ b/WebCore/platform/graphics/Gradient.h
@@ -63,7 +63,13 @@ typedef class PlatformGradientRec* PlatformGradient;
class SkShader;
typedef class SkShader* PlatformGradient;
typedef class SkShader* PlatformPattern;
+<<<<<<< HEAD
#endif
+=======
+#elif PLATFORM(HAIKU)
+class BGradient;
+typedef BGradient* PlatformGradient;
+>>>>>>> webkit.org at r58033
#else
typedef void* PlatformGradient;
#endif
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index 45b516a..caa0a7c 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -35,7 +35,7 @@
#include "Path.h"
#include "TextDirection.h"
#include <wtf/Noncopyable.h>
-#include <wtf/Platform.h>
+#include <wtf/PassOwnPtr.h>
#if PLATFORM(CG)
typedef struct CGContext PlatformGraphicsContext;
diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp
index 3eb9818..97465e2 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.cpp
+++ b/WebCore/platform/graphics/GraphicsContext3D.cpp
@@ -31,6 +31,7 @@
#include "GraphicsContext3D.h"
#include "Image.h"
+#include "ImageData.h"
namespace WebCore {
@@ -57,6 +58,28 @@ bool GraphicsContext3D::extractImageData(Image* image,
return true;
}
+bool GraphicsContext3D::extractImageData(ImageData* imageData,
+ bool flipY,
+ bool premultiplyAlpha,
+ Vector<uint8_t>& data)
+{
+ if (!imageData)
+ return false;
+ int width = imageData->width();
+ int height = imageData->height();
+ int dataBytes = width * height * 4;
+ data.resize(dataBytes);
+ uint8_t* dst = data.data();
+ uint8_t* src = imageData->data()->data()->data();
+ memcpy(dst, src, dataBytes);
+ processImageData(dst,
+ width,
+ height,
+ flipY,
+ premultiplyAlpha ? kAlphaDoPremultiply : kAlphaDoNothing);
+ return true;
+}
+
void GraphicsContext3D::processImageData(uint8_t* imageData,
unsigned width,
unsigned height,
diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h
index 0a41dc6..45f6f06 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/WebCore/platform/graphics/GraphicsContext3D.h
@@ -33,7 +33,7 @@
#include <wtf/PassOwnPtr.h>
// FIXME: Find a better way to avoid the name confliction for NO_ERROR.
-#if ((PLATFORM(CHROMIUM) && OS(WINDOWS)) || PLATFORM(WIN))
+#if ((PLATFORM(CHROMIUM) && OS(WINDOWS)) || PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)))
#undef NO_ERROR
#endif
@@ -44,6 +44,13 @@ typedef void* PlatformGraphicsContext3D;
const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0;
typedef GLuint Platform3DObject;
const Platform3DObject NullPlatform3DObject = 0;
+#elif PLATFORM(QT)
+#include <QtOpenGL/QtOpenGL>
+
+typedef void* PlatformGraphicsContext3D;
+const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0;
+typedef int Platform3DObject;
+const Platform3DObject NullPlatform3DObject = 0;
#else
typedef void* PlatformGraphicsContext3D;
const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0;
@@ -65,6 +72,8 @@ namespace WebCore {
class WebGLShader;
class WebGLTexture;
class Image;
+ class ImageData;
+ class HostWindow;
struct ActiveInfo {
String name;
@@ -73,7 +82,7 @@ namespace WebCore {
};
// FIXME: ideally this would be used on all platforms.
-#if PLATFORM(CHROMIUM)
+#if PLATFORM(CHROMIUM) || PLATFORM(QT)
class GraphicsContext3DInternal;
#endif
@@ -354,6 +363,7 @@ namespace WebCore {
DEPTH_COMPONENT16 = 0x81A5,
STENCIL_INDEX = 0x1901,
STENCIL_INDEX8 = 0x8D48,
+ DEPTH_STENCIL = 0x84F9,
RENDERBUFFER_WIDTH = 0x8D42,
RENDERBUFFER_HEIGHT = 0x8D43,
RENDERBUFFER_INTERNAL_FORMAT = 0x8D44,
@@ -370,6 +380,7 @@ namespace WebCore {
COLOR_ATTACHMENT0 = 0x8CE0,
DEPTH_ATTACHMENT = 0x8D00,
STENCIL_ATTACHMENT = 0x8D20,
+ DEPTH_STENCIL_ATTACHMENT = 0x821A,
NONE = 0,
FRAMEBUFFER_COMPLETE = 0x8CD5,
FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6,
@@ -400,7 +411,7 @@ namespace WebCore {
bool premultipliedAlpha;
};
- static PassOwnPtr<GraphicsContext3D> create(Attributes attrs);
+ static PassOwnPtr<GraphicsContext3D> create(Attributes attrs, HostWindow* hostWindow);
virtual ~GraphicsContext3D();
#if PLATFORM(MAC)
@@ -409,12 +420,20 @@ namespace WebCore {
#elif PLATFORM(CHROMIUM)
PlatformGraphicsContext3D platformGraphicsContext3D() const;
Platform3DObject platformTexture() const;
+#elif PLATFORM(QT)
+ PlatformGraphicsContext3D platformGraphicsContext3D();
+ Platform3DObject platformTexture() const;
#else
PlatformGraphicsContext3D platformGraphicsContext3D() const { return NullPlatformGraphicsContext3D; }
Platform3DObject platformTexture() const { return NullPlatform3DObject; }
#endif
void makeContextCurrent();
-
+
+#if PLATFORM(MAC)
+ // With multisampling on, blit from multisampleFBO to regular FBO.
+ void prepareTexture();
+#endif
+
// Helper to return the size in bytes of OpenGL data types
// like GL_FLOAT, GL_INT, etc.
int sizeInBytes(int type);
@@ -435,6 +454,14 @@ namespace WebCore {
unsigned int* format,
unsigned int* internalFormat);
+ // Extracts the contents of the given ImageData into the passed
+ // Vector, obeying the flipY and premultiplyAlpha flags.
+ // Returns true upon success.
+ bool extractImageData(ImageData*,
+ bool flipY,
+ bool premultiplyAlpha,
+ Vector<uint8_t>& data);
+
// Processes the given image data in preparation for uploading
// via texImage2D or texSubImage2D. The input data must be in
// 4-component format with the alpha channel last (i.e., RGBA
@@ -566,7 +593,7 @@ namespace WebCore {
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 readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data);
void releaseShaderCompiler();
void renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height);
@@ -659,7 +686,7 @@ namespace WebCore {
void synthesizeGLError(unsigned long error);
private:
- GraphicsContext3D(Attributes attrs);
+ GraphicsContext3D(Attributes attrs, HostWindow* hostWindow);
// Helpers for texture uploading.
void premultiplyAlpha(unsigned char* rgbaData, int numPixels);
@@ -689,6 +716,14 @@ namespace WebCore {
AlphaOp* neededAlphaOp,
unsigned int* format);
+#if PLATFORM(MAC)
+ // Take into account the user's requested context creation attributes,
+ // in particular stencil and antialias, and determine which could or
+ // could not be honored based on the capabilities of the OpenGL
+ // implementation.
+ void validateAttributes();
+#endif
+
int m_currentWidth, m_currentHeight;
#if PLATFORM(MAC)
@@ -698,13 +733,22 @@ namespace WebCore {
CGLContextObj m_contextObj;
GLuint m_texture;
GLuint m_fbo;
- GLuint m_depthBuffer;
+ GLuint m_depthStencilBuffer;
+
+ // For tracking which FBO is bound
+ GLuint m_boundFBO;
+
+ // For multisampling
+ GLuint m_multisampleFBO;
+ GLuint m_multisampleDepthStencilBuffer;
+ GLuint m_multisampleColorBuffer;
+
// Errors raised by synthesizeGLError().
ListHashSet<unsigned long> m_syntheticErrors;
#endif
// FIXME: ideally this would be used on all platforms.
-#if PLATFORM(CHROMIUM)
+#if PLATFORM(CHROMIUM) || PLATFORM(QT)
friend class GraphicsContext3DInternal;
OwnPtr<GraphicsContext3DInternal> m_internal;
#endif
diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp
index 2336d0b..b7567bf 100644
--- a/WebCore/platform/graphics/GraphicsLayer.cpp
+++ b/WebCore/platform/graphics/GraphicsLayer.cpp
@@ -32,6 +32,11 @@
#include "FloatPoint.h"
#include "RotateTransformOperation.h"
#include "TextStream.h"
+#include <wtf/text/CString.h>
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
namespace WebCore {
@@ -388,17 +393,23 @@ static void writeIndent(TextStream& ts, int indent)
ts << " ";
}
-void GraphicsLayer::dumpLayer(TextStream& ts, int indent) const
+void GraphicsLayer::dumpLayer(TextStream& ts, int indent, LayerTreeAsTextBehavior behavior) const
{
writeIndent(ts, indent);
- ts << "(" << "GraphicsLayer" << " " << static_cast<void*>(const_cast<GraphicsLayer*>(this));
- ts << " \"" << m_name << "\"\n";
- dumpProperties(ts, indent);
+ ts << "(" << "GraphicsLayer";
+
+ if (behavior & LayerTreeAsTextDebug) {
+ ts << " " << static_cast<void*>(const_cast<GraphicsLayer*>(this));
+ ts << " \"" << m_name << "\"";
+ }
+
+ ts << "\n";
+ dumpProperties(ts, indent, behavior);
writeIndent(ts, indent);
ts << ")\n";
}
-void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const
+void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeAsTextBehavior behavior) const
{
writeIndent(ts, indent + 1);
ts << "(position " << m_position.x() << " " << m_position.y() << ")\n";
@@ -416,21 +427,23 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const
ts << "(usingTiledLayer " << m_usingTiledLayer << ")\n";
writeIndent(ts, indent + 1);
- ts << "(m_preserves3D " << m_preserves3D << ")\n";
+ ts << "(preserves3D " << m_preserves3D << ")\n";
writeIndent(ts, indent + 1);
ts << "(drawsContent " << m_drawsContent << ")\n";
writeIndent(ts, indent + 1);
- ts << "(m_backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n";
+ ts << "(backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n";
- writeIndent(ts, indent + 1);
- ts << "(client ";
- if (m_client)
- ts << static_cast<void*>(m_client);
- else
- ts << "none";
- ts << ")\n";
+ if (behavior & LayerTreeAsTextDebug) {
+ writeIndent(ts, indent + 1);
+ ts << "(";
+ if (m_client)
+ ts << "client " << static_cast<void*>(m_client);
+ else
+ ts << "no client";
+ ts << ")\n";
+ }
writeIndent(ts, indent + 1);
ts << "(backgroundColor ";
@@ -466,13 +479,19 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const
if (m_replicaLayer) {
writeIndent(ts, indent + 1);
- ts << "(replica layer " << m_replicaLayer << ")\n";
- m_replicaLayer->dumpLayer(ts, indent+2);
+ ts << "(replica layer";
+ if (behavior & LayerTreeAsTextDebug)
+ ts << " " << m_replicaLayer;
+ ts << ")\n";
+ m_replicaLayer->dumpLayer(ts, indent + 2, behavior);
}
if (m_replicatedLayer) {
writeIndent(ts, indent + 1);
- ts << "(replicated layer " << m_replicatedLayer << ")\n";
+ ts << "(replicated layer";
+ if (behavior & LayerTreeAsTextDebug)
+ ts << " " << m_replicatedLayer;;
+ ts << ")\n";
}
if (m_children.size()) {
@@ -481,12 +500,31 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const
unsigned i;
for (i = 0; i < m_children.size(); i++)
- m_children[i]->dumpLayer(ts, indent+2);
+ m_children[i]->dumpLayer(ts, indent + 2, behavior);
writeIndent(ts, indent + 1);
ts << ")\n";
}
}
+String GraphicsLayer::layerTreeAsText(LayerTreeAsTextBehavior behavior) const
+{
+ TextStream ts;
+
+ dumpLayer(ts, 0, behavior);
+ return ts.release();
+}
+
} // namespace WebCore
+#ifndef NDEBUG
+void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer)
+{
+ if (!layer)
+ return;
+
+ WebCore::String output = layer->layerTreeAsText(LayerTreeAsTextDebug);
+ fprintf(stderr, "%s\n", output.utf8().data());
+}
+#endif
+
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h
index a097620..340b911 100644
--- a/WebCore/platform/graphics/GraphicsLayer.h
+++ b/WebCore/platform/graphics/GraphicsLayer.h
@@ -60,14 +60,28 @@ typedef WKCACFLayer PlatformLayer;
typedef void* NativeLayer;
}
#elif PLATFORM(QT)
+QT_BEGIN_NAMESPACE
class QGraphicsItem;
+QT_END_NAMESPACE
typedef QGraphicsItem PlatformLayer;
typedef QGraphicsItem* NativeLayer;
+#elif PLATFORM(CHROMIUM)
+namespace WebCore {
+class LayerChromium;
+typedef LayerChromium PlatformLayer;
+typedef void* NativeLayer;
+}
#else
typedef void* PlatformLayer;
typedef void* NativeLayer;
#endif
+enum LayerTreeAsTextBehaviorFlags {
+ LayerTreeAsTextBehaviorNormal = 0,
+ LayerTreeAsTextDebug = 1 << 0, // Dump extra debugging info like layer addresses.
+};
+typedef unsigned LayerTreeAsTextBehavior;
+
namespace WebCore {
class FloatPoint3D;
@@ -298,7 +312,7 @@ public:
virtual PlatformLayer* platformLayer() const { return 0; }
- void dumpLayer(TextStream&, int indent = 0) const;
+ void dumpLayer(TextStream&, int indent = 0, LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const;
int repaintCount() const { return m_repaintCount; }
int incrementRepaintCount() { return ++m_repaintCount; }
@@ -333,6 +347,10 @@ public:
// Some compositing systems may do internal batching to synchronize compositing updates
// with updates drawn into the window. This is a signal to flush any internal batched state.
virtual void syncCompositingState() { }
+
+ // Return a string with a human readable form of the layer tree, If debug is true
+ // pointers for the layers and timing data will be included in the returned string.
+ String layerTreeAsText(LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const;
protected:
@@ -349,7 +367,7 @@ protected:
GraphicsLayer(GraphicsLayerClient*);
- void dumpProperties(TextStream&, int indent) const;
+ void dumpProperties(TextStream&, int indent, LayerTreeAsTextBehavior) const;
GraphicsLayerClient* m_client;
String m_name;
@@ -398,6 +416,11 @@ protected:
} // namespace WebCore
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer);
+#endif
+
#endif // USE(ACCELERATED_COMPOSITING)
#endif // GraphicsLayer_h
diff --git a/WebCore/platform/graphics/Icon.h b/WebCore/platform/graphics/Icon.h
index e9f2dc7..59c732f 100644
--- a/WebCore/platform/graphics/Icon.h
+++ b/WebCore/platform/graphics/Icon.h
@@ -39,6 +39,8 @@ typedef struct HICON__* HICON;
#include <QIcon>
#elif PLATFORM(GTK)
typedef struct _GdkPixbuf GdkPixbuf;
+#elif PLATFORM(EFL)
+#include <Evas.h>
#elif PLATFORM(CHROMIUM)
#include "PlatformIcon.h"
#endif
@@ -51,8 +53,6 @@ class String;
class Icon : public RefCounted<Icon> {
public:
- // Deprecated. This function will be removed.
- // FIXME: Remove it when all implementations are moved to ChromeClient::iconForFiles().
static PassRefPtr<Icon> createIconForFiles(const Vector<String>& filenames);
~Icon();
@@ -76,6 +76,9 @@ private:
#elif PLATFORM(GTK)
Icon();
GdkPixbuf* m_icon;
+#elif PLATFORM(EFL)
+ Icon();
+ Evas_Object* m_icon;
#elif PLATFORM(CHROMIUM)
Icon(const PlatformIcon&);
PlatformIcon m_icon;
diff --git a/WebCore/platform/graphics/Image.cpp b/WebCore/platform/graphics/Image.cpp
index 8263faa..6f2311c 100644
--- a/WebCore/platform/graphics/Image.cpp
+++ b/WebCore/platform/graphics/Image.cpp
@@ -32,9 +32,9 @@
#include "GraphicsContext.h"
#include "IntRect.h"
#include "MIMETypeRegistry.h"
-#include <wtf/StdLibExtras.h>
-
+#include "SharedBuffer.h"
#include <math.h>
+#include <wtf/StdLibExtras.h>
#if PLATFORM(CG)
#include <CoreFoundation/CoreFoundation.h>
@@ -53,6 +53,7 @@ Image::~Image()
Image* Image::nullImage()
{
+ ASSERT(isMainThread());
DEFINE_STATIC_LOCAL(RefPtr<Image>, nullImage, (BitmapImage::create()));;
return nullImage.get();
}
diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h
index b786106..212175c 100644
--- a/WebCore/platform/graphics/Image.h
+++ b/WebCore/platform/graphics/Image.h
@@ -32,8 +32,9 @@
#include "GraphicsTypes.h"
#include "ImageSource.h"
#include "IntRect.h"
-#include "SharedBuffer.h"
+#include "PlatformString.h"
#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#if PLATFORM(MAC)
@@ -73,7 +74,6 @@ class FloatRect;
class FloatSize;
class GraphicsContext;
class SharedBuffer;
-class String;
class AffineTransform;
// This class gets notified when an image creates or destroys decoded frames and when it advances animation frames.
diff --git a/WebCore/platform/graphics/IntPoint.h b/WebCore/platform/graphics/IntPoint.h
index 5137485..d4ea2f2 100644
--- a/WebCore/platform/graphics/IntPoint.h
+++ b/WebCore/platform/graphics/IntPoint.h
@@ -27,7 +27,6 @@
#define IntPoint_h
#include "IntSize.h"
-#include <wtf/Platform.h>
#if PLATFORM(QT)
#include <QDataStream>
@@ -57,6 +56,8 @@ QT_END_NAMESPACE
typedef struct _GdkPoint GdkPoint;
#elif PLATFORM(HAIKU)
class BPoint;
+#elif PLATFORM(EFL)
+typedef struct _Evas_Point Evas_Point;
#endif
#if PLATFORM(WX)
@@ -80,6 +81,8 @@ public:
IntPoint(int x, int y) : m_x(x), m_y(y) { }
explicit IntPoint(const IntSize& size) : m_x(size.width()), m_y(size.height()) { }
+ static IntPoint zero() { return IntPoint(); }
+
int x() const { return m_x; }
int y() const { return m_y; }
@@ -103,7 +106,7 @@ public:
void clampNegativeToZero()
{
- *this = expandedTo(IntPoint());
+ *this = expandedTo(zero());
}
#if PLATFORM(CG)
@@ -130,6 +133,9 @@ public:
#elif PLATFORM(HAIKU)
explicit IntPoint(const BPoint&);
operator BPoint() const;
+#elif PLATFORM(EFL)
+ explicit IntPoint(const Evas_Point&);
+ operator Evas_Point() const;
#endif
#if PLATFORM(WX)
@@ -189,6 +195,11 @@ inline bool operator!=(const IntPoint& a, const IntPoint& b)
return a.x() != b.x() || a.y() != b.y();
}
+inline IntPoint toPoint(const IntSize& size)
+{
+ return IntPoint(size.width(), size.height());
+}
+
#if PLATFORM(QT)
inline QDataStream& operator<<(QDataStream& stream, const IntPoint& point)
{
diff --git a/WebCore/platform/graphics/IntPointHash.h b/WebCore/platform/graphics/IntPointHash.h
new file mode 100644
index 0000000..bf25b14
--- /dev/null
+++ b/WebCore/platform/graphics/IntPointHash.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef IntPointHash_h
+#define IntPointHash_h
+
+#include "IntPoint.h"
+#include <wtf/HashFunctions.h>
+#include <wtf/HashTraits.h>
+
+namespace WTF {
+
+// The empty value is (0, INT_MIN), the deleted value is (INT_MIN, 0)
+struct IntPointHash {
+ static unsigned hash(const WebCore::IntPoint& p) { return WTF::intHash(static_cast<uint64_t>(p.x()) << 32 | p.y()); }
+ static bool equal(const WebCore::IntPoint& a, const WebCore::IntPoint& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+template<> struct HashTraits<WebCore::IntPoint> : GenericHashTraits<WebCore::IntPoint> {
+ static const bool needsDestruction = false;
+ static WebCore::IntPoint emptyValue() { return WebCore::IntPoint(0, std::numeric_limits<int>::min()); }
+
+ static void constructDeletedValue(WebCore::IntPoint& slot) { slot = WebCore::IntPoint(std::numeric_limits<int>::min(), 0); }
+ static bool isDeletedValue(const WebCore::IntPoint& slot) { return slot == WebCore::IntPoint(std::numeric_limits<int>::min(), 0); }
+};
+template<> struct DefaultHash<WebCore::IntPoint> {
+ typedef IntPointHash Hash;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h
index e3633df..5c5eae1 100644
--- a/WebCore/platform/graphics/IntRect.h
+++ b/WebCore/platform/graphics/IntRect.h
@@ -27,7 +27,6 @@
#define IntRect_h
#include "IntPoint.h"
-#include <wtf/Platform.h>
#include <wtf/Vector.h>
#if PLATFORM(CG)
@@ -52,6 +51,8 @@ QT_END_NAMESPACE
typedef struct _GdkRectangle GdkRectangle;
#elif PLATFORM(HAIKU)
class BRect;
+#elif PLATFORM(EFL)
+#include <Evas.h>
#endif
#if PLATFORM(WX)
@@ -105,6 +106,10 @@ public:
int right() const { return x() + width(); }
int bottom() const { return y() + height(); }
+ // NOTE: The result is rounded to integer values, and thus may be not the exact
+ // center point.
+ IntPoint center() const { return IntPoint(x() + width() / 2, y() + height() / 2); }
+
void move(const IntSize& s) { m_location += s; }
void move(int dx, int dy) { m_location.move(dx, dy); }
@@ -150,6 +155,9 @@ public:
#elif PLATFORM(HAIKU)
explicit IntRect(const BRect&);
operator BRect() const;
+#elif PLATFORM(EFL)
+ explicit IntRect(const Eina_Rectangle&);
+ operator Eina_Rectangle() const;
#endif
#if PLATFORM(CG)
diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h
index 6938afd..b60338c 100644
--- a/WebCore/platform/graphics/IntSize.h
+++ b/WebCore/platform/graphics/IntSize.h
@@ -26,8 +26,6 @@
#ifndef IntSize_h
#define IntSize_h
-#include <wtf/Platform.h>
-
#if PLATFORM(CG)
typedef struct CGSize CGSize;
#endif
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index 9a7f7b3..813b29c 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -37,6 +37,10 @@
#include "Document.h"
#include "TimeRanges.h"
+#if PLATFORM(QT)
+#include <QtGlobal>
+#endif
+
#if PLATFORM(MAC)
#include "MediaPlayerPrivateQTKit.h"
#elif OS(WINCE) && !PLATFORM(QT)
@@ -46,7 +50,11 @@
#elif PLATFORM(GTK)
#include "MediaPlayerPrivateGStreamer.h"
#elif PLATFORM(QT)
+#if QT_VERSION < 0x040700
#include "MediaPlayerPrivatePhonon.h"
+#else
+#include "MediaPlayerPrivateQt.h"
+#endif
#elif PLATFORM(CHROMIUM)
#include "MediaPlayerPrivateChromium.h"
#elif PLATFORM(ANDROID)
@@ -153,7 +161,14 @@ static Vector<MediaPlayerFactory*>& installedMediaEngines()
if (!enginesQueried) {
enginesQueried = true;
+#if USE(GSTREAMER)
+ MediaPlayerPrivateGStreamer::registerMediaEngine(addMediaEngine);
+#else
+ // FIXME: currently all the MediaEngines are named
+ // MediaPlayerPrivate. This code will need an update when bug
+ // 36663 is adressed.
MediaPlayerPrivate::registerMediaEngine(addMediaEngine);
+#endif
// register additional engines here
}
@@ -198,15 +213,19 @@ MediaPlayer::MediaPlayer(MediaPlayerClient* client)
, m_private(createNullMediaPlayer(this))
, m_currentMediaEngine(0)
, m_frameView(0)
+ , m_preload(Auto)
, m_visible(false)
, m_rate(1.0f)
, m_volume(1.0f)
, m_muted(false)
, m_preservesPitch(true)
+<<<<<<< HEAD
, m_autobuffer(false)
#if PLATFORM(ANDROID)
, m_mediaElementType(Video)
#endif
+=======
+>>>>>>> webkit.org at r58033
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
, m_playerProxy(0)
#endif
@@ -257,7 +276,7 @@ void MediaPlayer::load(const String& url, const ContentType& contentType)
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
m_private->setMediaPlayerProxy(m_playerProxy);
#endif
- m_private->setAutobuffer(autobuffer());
+ m_private->setPreload(m_preload);
m_private->setPreservesPitch(preservesPitch());
}
@@ -395,7 +414,9 @@ float MediaPlayer::volume() const
void MediaPlayer::setVolume(float volume)
{
m_volume = volume;
- m_private->setVolume(volume);
+
+ if (m_private->supportsMuting() || !m_muted)
+ m_private->setVolume(volume);
}
bool MediaPlayer::muted() const
@@ -403,15 +424,14 @@ bool MediaPlayer::muted() const
return m_muted;
}
-bool MediaPlayer::supportsMuting() const
-{
- return m_private->supportsMuting();
-}
-
void MediaPlayer::setMuted(bool muted)
{
m_muted = muted;
- m_private->setMuted(muted);
+
+ if (m_private->supportsMuting())
+ m_private->setMuted(muted);
+ else
+ m_private->setVolume(muted ? 0 : m_volume);
}
bool MediaPlayer::hasClosedCaptions() const
@@ -478,17 +498,15 @@ void MediaPlayer::setVisible(bool b)
m_private->setVisible(b);
}
-bool MediaPlayer::autobuffer() const
+MediaPlayer::Preload MediaPlayer::preload() const
{
- return m_autobuffer;
+ return m_preload;
}
-void MediaPlayer::setAutobuffer(bool b)
+void MediaPlayer::setPreload(MediaPlayer::Preload preload)
{
- if (m_autobuffer != b) {
- m_autobuffer = b;
- m_private->setAutobuffer(b);
- }
+ m_preload = preload;
+ m_private->setPreload(preload);
}
void MediaPlayer::paint(GraphicsContext* p, const IntRect& r)
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
index f067cc9..24f4225 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -32,6 +32,7 @@
#include "MediaPlayerProxy.h"
#endif
+#include "Document.h"
#include "IntRect.h"
#include "StringHash.h"
#include <wtf/HashSet.h>
@@ -75,6 +76,9 @@ class MediaPlayerClient {
public:
virtual ~MediaPlayerClient() { }
+ // Get the document which the media player is owned by
+ virtual Document* mediaPlayerOwningDocument() { return 0; }
+
// the network state has changed
virtual void mediaPlayerNetworkStateChanged(MediaPlayer*) { }
@@ -189,15 +193,14 @@ public:
float volume() const;
void setVolume(float);
- bool supportsMuting() const;
bool muted() const;
void setMuted(bool);
bool hasClosedCaptions() const;
void setClosedCaptionsVisible(bool closedCaptionsVisible);
- bool autobuffer() const;
- void setAutobuffer(bool);
+ bool autoplay() const;
+ void setAutoplay(bool);
void paint(GraphicsContext*, const IntRect&);
void paintCurrentFrameInContext(GraphicsContext*, const IntRect&);
@@ -211,6 +214,10 @@ public:
enum MovieLoadType { Unknown, Download, StoredStream, LiveStream };
MovieLoadType movieLoadType() const;
+ enum Preload { None, MetaData, Auto };
+ Preload preload() const;
+ void setPreload(Preload);
+
void networkStateChanged();
void readyStateChanged();
void volumeChanged(float);
@@ -253,15 +260,19 @@ private:
void* m_currentMediaEngine;
FrameView* m_frameView;
IntSize m_size;
+ Preload m_preload;
bool m_visible;
float m_rate;
float m_volume;
bool m_muted;
bool m_preservesPitch;
+<<<<<<< HEAD
bool m_autobuffer;
#if PLATFORM(ANDROID)
MediaElementType m_mediaElementType;
#endif
+=======
+>>>>>>> webkit.org at r58033
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
WebMediaPlayerProxy* m_playerProxy; // not owned or used, passed to m_private
#endif
diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h
index 3bb8475..16ff543 100644
--- a/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -97,7 +97,7 @@ public:
virtual void paintCurrentFrameInContext(GraphicsContext* c, const IntRect& r) { paint(c, r); }
- virtual void setAutobuffer(bool) { };
+ virtual void setPreload(MediaPlayer::Preload) { };
virtual bool hasAvailableVideoFrame() const { return readyState() >= MediaPlayer::HaveCurrentData; }
diff --git a/WebCore/platform/graphics/Path.cpp b/WebCore/platform/graphics/Path.cpp
index e30703c..af94be7 100644
--- a/WebCore/platform/graphics/Path.cpp
+++ b/WebCore/platform/graphics/Path.cpp
@@ -39,6 +39,7 @@ static const float QUARTER = 0.552f; // approximation of control point positions
// to simulate a quarter of a circle.
namespace WebCore {
+#if !PLATFORM(OPENVG)
static void pathLengthApplierFunction(void* info, const PathElement* element)
{
PathTraversalState& traversalState = *static_cast<PathTraversalState*>(info);
@@ -107,6 +108,7 @@ float Path::normalAngleAtLength(float length, bool& ok)
ok = traversalState.m_success;
return traversalState.m_normalAngle;
}
+#endif
Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& roundingRadii)
{
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
index 533ef8f..b69670f 100644
--- a/WebCore/platform/graphics/Path.h
+++ b/WebCore/platform/graphics/Path.h
@@ -33,6 +33,11 @@
#if PLATFORM(CG)
typedef struct CGPath PlatformPath;
+#elif PLATFORM(OPENVG)
+namespace WebCore {
+class PlatformPathOpenVG;
+}
+typedef WebCore::PlatformPathOpenVG PlatformPath;
#elif PLATFORM(QT)
#include <qpainterpath.h>
typedef QPainterPath PlatformPath;
diff --git a/WebCore/platform/graphics/Pattern.h b/WebCore/platform/graphics/Pattern.h
index b0cf283..48e8d8b 100644
--- a/WebCore/platform/graphics/Pattern.h
+++ b/WebCore/platform/graphics/Pattern.h
@@ -87,6 +87,9 @@ public:
void setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation);
void setPlatformPatternSpaceTransform();
+ bool repeatX() const { return m_repeatX; }
+ bool repeatY() const { return m_repeatY; }
+
private:
Pattern(Image*, bool repeatX, bool repeatY);
diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp
index 2ec8abb..04b6ab1 100644
--- a/WebCore/platform/graphics/SimpleFontData.cpp
+++ b/WebCore/platform/graphics/SimpleFontData.cpp
@@ -157,9 +157,11 @@ void SimpleFontData::platformGlyphInit()
// are mapped to the ZERO WIDTH SPACE glyph.
Glyph zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph;
if (zeroWidthSpaceGlyph) {
- if (zeroWidthSpaceGlyph != m_spaceGlyph)
- m_glyphToWidthMap.setWidthForGlyph(zeroWidthSpaceGlyph, 0);
- else
+ if (zeroWidthSpaceGlyph != m_spaceGlyph) {
+ GlyphMetrics metrics;
+ metrics.horizontalAdvance = 0;
+ m_glyphToMetricsMap.setMetricsForGlyph(zeroWidthSpaceGlyph, metrics);
+ } else
LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width not overridden.");
}
diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h
index 0366e3b..efdbba4 100644
--- a/WebCore/platform/graphics/SimpleFontData.h
+++ b/WebCore/platform/graphics/SimpleFontData.h
@@ -26,8 +26,8 @@
#include "FontData.h"
#include "FontPlatformData.h"
+#include "GlyphMetricsMap.h"
#include "GlyphPageTreeNode.h"
-#include "GlyphWidthMap.h"
#include "TypesettingFeatures.h"
#include <wtf/OwnPtr.h>
@@ -58,9 +58,9 @@ class FontDescription;
class FontPlatformData;
class SharedBuffer;
class SVGFontData;
-class WidthMap;
enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
+enum GlyphMetricsMode { GlyphBoundingBox, GlyphWidthOnly };
class SimpleFontData : public FontData {
public:
@@ -81,8 +81,9 @@ public:
float xHeight() const { return m_xHeight; }
unsigned unitsPerEm() const { return m_unitsPerEm; }
- float widthForGlyph(Glyph) const;
- float platformWidthForGlyph(Glyph) const;
+ float widthForGlyph(Glyph glyph) const { return metricsForGlyph(glyph, GlyphWidthOnly).horizontalAdvance; }
+ GlyphMetrics metricsForGlyph(Glyph, GlyphMetricsMode = GlyphBoundingBox) const;
+ GlyphMetrics platformMetricsForGlyph(Glyph, GlyphMetricsMode) const;
float spaceWidth() const { return m_spaceWidth; }
float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; }
@@ -167,7 +168,7 @@ private:
|| (OS(WINDOWS) && PLATFORM(WX))
void initGDIFont();
void platformCommonDestroy();
- float widthForGDIGlyph(Glyph glyph) const;
+ GlyphMetrics metricsForGDIGlyph(Glyph glyph) const;
#endif
int m_ascent;
@@ -181,7 +182,7 @@ private:
FontPlatformData m_platformData;
- mutable GlyphWidthMap m_glyphToWidthMap;
+ mutable GlyphMetricsMap m_glyphToMetricsMap;
bool m_treatAsFixedPitch;
@@ -237,16 +238,16 @@ private:
#if !PLATFORM(QT)
-ALWAYS_INLINE float SimpleFontData::widthForGlyph(Glyph glyph) const
+ALWAYS_INLINE GlyphMetrics SimpleFontData::metricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const
{
- float width = m_glyphToWidthMap.widthForGlyph(glyph);
- if (width != cGlyphWidthUnknown)
- return width;
-
- width = platformWidthForGlyph(glyph);
- m_glyphToWidthMap.setWidthForGlyph(glyph, width);
-
- return width;
+ GlyphMetrics metrics = m_glyphToMetricsMap.metricsForGlyph(glyph);
+ if ((metricsMode == GlyphWidthOnly && metrics.horizontalAdvance != cGlyphSizeUnknown) || (metricsMode == GlyphBoundingBox && metrics.boundingBox.width() != cGlyphSizeUnknown))
+ return metrics;
+
+ metrics = platformMetricsForGlyph(glyph, metricsMode);
+ m_glyphToMetricsMap.setMetricsForGlyph(glyph, metrics);
+
+ return metrics;
}
#endif
diff --git a/WebCore/platform/graphics/Tile.h b/WebCore/platform/graphics/Tile.h
new file mode 100644
index 0000000..c623ec9
--- /dev/null
+++ b/WebCore/platform/graphics/Tile.h
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef Tile_h
+#define Tile_h
+
+#if ENABLE(TILED_BACKING_STORE)
+
+#include "IntPoint.h"
+#include "IntPointHash.h"
+#include "IntRect.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+#if PLATFORM(QT)
+QT_BEGIN_NAMESPACE
+class QPixmap;
+class QRegion;
+QT_END_NAMESPACE
+#endif
+
+namespace WebCore {
+
+class GraphicsContext;
+class TiledBackingStore;
+
+class Tile : public RefCounted<Tile> {
+public:
+ typedef IntPoint Coordinate;
+
+ static PassRefPtr<Tile> create(TiledBackingStore* backingStore, const Coordinate& tileCoordinate) { return adoptRef(new Tile(backingStore, tileCoordinate)); }
+ ~Tile();
+
+ bool isDirty() const;
+ void invalidate(const IntRect&);
+ void updateBackBuffer();
+ void swapBackBufferToFront();
+ bool isReadyToPaint() const;
+ void paint(GraphicsContext*, const IntRect&);
+
+ const Tile::Coordinate& coordinate() const { return m_coordinate; }
+ const IntRect& rect() const { return m_rect; }
+
+ static void paintCheckerPattern(GraphicsContext*, const FloatRect&);
+
+private:
+ Tile(TiledBackingStore*, const Coordinate&);
+
+ TiledBackingStore* m_backingStore;
+ Coordinate m_coordinate;
+ IntRect m_rect;
+
+#if PLATFORM(QT)
+ QPixmap* m_buffer;
+ QPixmap* m_backBuffer;
+ QRegion* m_dirtyRegion;
+#endif
+};
+
+}
+#endif
+#endif
diff --git a/WebCore/platform/graphics/TiledBackingStore.cpp b/WebCore/platform/graphics/TiledBackingStore.cpp
new file mode 100644
index 0000000..6214f1b
--- /dev/null
+++ b/WebCore/platform/graphics/TiledBackingStore.cpp
@@ -0,0 +1,378 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "TiledBackingStore.h"
+
+#if ENABLE(TILED_BACKING_STORE)
+
+#include "GraphicsContext.h"
+#include "TiledBackingStoreClient.h"
+
+namespace WebCore {
+
+static const int defaultTileWidth = 512;
+static const int defaultTileHeight = 512;
+
+TiledBackingStore::TiledBackingStore(TiledBackingStoreClient* client)
+ : m_client(client)
+ , m_tileBufferUpdateTimer(new TileTimer(this, &TiledBackingStore::tileBufferUpdateTimerFired))
+ , m_tileCreationTimer(new TileTimer(this, &TiledBackingStore::tileCreationTimerFired))
+ , m_tileSize(defaultTileWidth, defaultTileHeight)
+ , m_contentsScale(1.f)
+ , m_pendingScale(0)
+ , m_contentsFrozen(false)
+{
+}
+
+TiledBackingStore::~TiledBackingStore()
+{
+ delete m_tileBufferUpdateTimer;
+ delete m_tileCreationTimer;
+}
+
+void TiledBackingStore::invalidate(const IntRect& contentsDirtyRect)
+{
+ IntRect dirtyRect(mapFromContents(contentsDirtyRect));
+
+ Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft());
+ Tile::Coordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight());
+
+ for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
+ for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
+ RefPtr<Tile> currentTile = tileAt(Tile::Coordinate(xCoordinate, yCoordinate));
+ if (!currentTile)
+ continue;
+ currentTile->invalidate(dirtyRect);
+ }
+ }
+
+ startTileBufferUpdateTimer();
+}
+
+void TiledBackingStore::updateTileBuffers()
+{
+ if (m_contentsFrozen)
+ return;
+
+ Vector<IntRect> paintedArea;
+ Vector<RefPtr<Tile> > dirtyTiles;
+ TileMap::iterator end = m_tiles.end();
+ for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) {
+ if (!it->second->isDirty())
+ continue;
+ dirtyTiles.append(it->second);
+ // FIXME: should not request system repaint for the full tile.
+ paintedArea.append(mapToContents(it->second->rect()));
+ }
+
+ if (dirtyTiles.isEmpty())
+ return;
+
+ m_client->tiledBackingStorePaintBegin();
+
+ // FIXME: In single threaded case, tile back buffers could be updated asynchronously
+ // one by one and then swapped to front in one go. This would minimize the time spent
+ // blocking on tile updates.
+ unsigned size = dirtyTiles.size();
+ for (unsigned n = 0; n < size; ++n)
+ dirtyTiles[n]->updateBackBuffer();
+
+ for (unsigned n = 0; n < size; ++n)
+ dirtyTiles[n]->swapBackBufferToFront();
+
+ m_client->tiledBackingStorePaintEnd(paintedArea);
+}
+
+void TiledBackingStore::paint(GraphicsContext* context, const IntRect& rect)
+{
+ context->save();
+
+ // Assumes the backing store is painted with the scale transform applied.
+ // Since tile content is already scaled, first revert the scaling from the painter.
+ context->scale(FloatSize(1.f / m_contentsScale, 1.f / m_contentsScale));
+
+ IntRect dirtyRect = mapFromContents(rect);
+
+ Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft());
+ Tile::Coordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight());
+
+ for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
+ for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
+ Tile::Coordinate currentCoordinate(xCoordinate, yCoordinate);
+ RefPtr<Tile> currentTile = tileAt(currentCoordinate);
+ if (currentTile && currentTile->isReadyToPaint())
+ currentTile->paint(context, dirtyRect);
+ else {
+ FloatRect tileRect = tileRectForCoordinate(currentCoordinate);
+ FloatRect target = intersection(tileRect, FloatRect(rect));
+ Tile::paintCheckerPattern(context, target);
+ }
+ }
+ }
+ context->restore();
+}
+
+void TiledBackingStore::viewportChanged(const IntRect& contentsViewport)
+{
+ IntRect viewport = mapFromContents(contentsViewport);
+ if (m_viewport == viewport)
+ return;
+
+ m_viewport = viewport;
+
+ startTileCreationTimer();
+}
+
+void TiledBackingStore::setContentsScale(float scale)
+{
+ if (m_pendingScale == m_contentsScale) {
+ m_pendingScale = 0;
+ return;
+ }
+ m_pendingScale = scale;
+ if (m_contentsFrozen)
+ return;
+ commitScaleChange();
+}
+
+void TiledBackingStore::commitScaleChange()
+{
+ m_contentsScale = m_pendingScale;
+ m_pendingScale = 0;
+ m_tiles.clear();
+ createTiles();
+}
+
+double TiledBackingStore::tileDistance(const IntRect& viewport, const Tile::Coordinate& tileCoordinate)
+{
+ if (viewport.intersects(tileRectForCoordinate(tileCoordinate)))
+ return 0;
+
+ IntPoint viewCenter = viewport.location() + IntSize(viewport.width() / 2, viewport.height() / 2);
+ Tile::Coordinate centerCoordinate = tileCoordinateForPoint(viewCenter);
+
+ // Manhattan distance, biased so that vertical distances are shorter.
+ const double horizontalBias = 1.3;
+ return abs(centerCoordinate.y() - tileCoordinate.y()) + horizontalBias * abs(centerCoordinate.x() - tileCoordinate.x());
+}
+
+void TiledBackingStore::createTiles()
+{
+ if (m_contentsFrozen)
+ return;
+
+ if (m_viewport.isEmpty())
+ return;
+
+ // Remove tiles that extend outside the current contents rect.
+ dropOverhangingTiles();
+
+ // FIXME: Make configurable/adapt to memory.
+ IntRect keepRect = m_viewport;
+ keepRect.inflateX(m_viewport.width());
+ keepRect.inflateY(3 * m_viewport.height());
+ keepRect.intersect(contentsRect());
+
+ dropTilesOutsideRect(keepRect);
+
+ IntRect coverRect = m_viewport;
+ coverRect.inflateX(m_viewport.width() / 2);
+ coverRect.inflateY(2 * m_viewport.height());
+ coverRect.intersect(contentsRect());
+
+ // Search for the tile position closest to the viewport center that does not yet contain a tile.
+ // Which position is considered the closest depends on the tileDistance function.
+ double shortestDistance = std::numeric_limits<double>::infinity();
+ Vector<Tile::Coordinate> tilesToCreate;
+ unsigned requiredTileCount = 0;
+ Tile::Coordinate topLeft = tileCoordinateForPoint(coverRect.topLeft());
+ Tile::Coordinate bottomRight = tileCoordinateForPoint(coverRect.bottomRight());
+ for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
+ for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
+ Tile::Coordinate currentCoordinate(xCoordinate, yCoordinate);
+ if (tileAt(currentCoordinate))
+ continue;
+ ++requiredTileCount;
+ // Distance is 0 for all currently visible tiles.
+ double distance = tileDistance(m_viewport, currentCoordinate);
+ if (distance > shortestDistance)
+ continue;
+ if (distance < shortestDistance) {
+ tilesToCreate.clear();
+ shortestDistance = distance;
+ }
+ tilesToCreate.append(currentCoordinate);
+ }
+ }
+
+ // Now construct the tile(s)
+ unsigned tilesToCreateCount = tilesToCreate.size();
+ for (unsigned n = 0; n < tilesToCreateCount; ++n) {
+ Tile::Coordinate coordinate = tilesToCreate[n];
+ setTile(coordinate, Tile::create(this, coordinate));
+ }
+ requiredTileCount -= tilesToCreateCount;
+
+ // Paint the content of the newly created tiles
+ if (tilesToCreateCount)
+ updateTileBuffers();
+
+ // Keep creating tiles until the whole coverRect is covered.
+ if (requiredTileCount)
+ m_tileCreationTimer->startOneShot(0);
+}
+
+void TiledBackingStore::dropOverhangingTiles()
+{
+ IntRect contentsRect = this->contentsRect();
+
+ Vector<Tile::Coordinate> tilesToRemove;
+ TileMap::iterator end = m_tiles.end();
+ for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) {
+ Tile::Coordinate tileCoordinate = it->second->coordinate();
+ IntRect tileRect = it->second->rect();
+ IntRect expectedTileRect = tileRectForCoordinate(tileCoordinate);
+ if (expectedTileRect != tileRect || !contentsRect.contains(tileRect))
+ tilesToRemove.append(tileCoordinate);
+ }
+ unsigned removeCount = tilesToRemove.size();
+ for (unsigned n = 0; n < removeCount; ++n)
+ removeTile(tilesToRemove[n]);
+}
+
+void TiledBackingStore::dropTilesOutsideRect(const IntRect& keepRect)
+{
+ FloatRect keepRectF = keepRect;
+
+ Vector<Tile::Coordinate> toRemove;
+ TileMap::iterator end = m_tiles.end();
+ for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) {
+ Tile::Coordinate coordinate = it->second->coordinate();
+ FloatRect tileRect = it->second->rect();
+ if (!tileRect.intersects(keepRectF))
+ toRemove.append(coordinate);
+ }
+ unsigned removeCount = toRemove.size();
+ for (unsigned n = 0; n < removeCount; ++n)
+ removeTile(toRemove[n]);
+}
+
+PassRefPtr<Tile> TiledBackingStore::tileAt(const Tile::Coordinate& coordinate) const
+{
+ return m_tiles.get(coordinate);
+}
+
+void TiledBackingStore::setTile(const Tile::Coordinate& coordinate, PassRefPtr<Tile> tile)
+{
+ m_tiles.set(coordinate, tile);
+}
+
+void TiledBackingStore::removeTile(const Tile::Coordinate& coordinate)
+{
+ m_tiles.remove(coordinate);
+}
+
+IntRect TiledBackingStore::mapToContents(const IntRect& rect) const
+{
+ return enclosingIntRect(FloatRect(rect.x() / m_contentsScale,
+ rect.y() / m_contentsScale,
+ rect.width() / m_contentsScale,
+ rect.height() / m_contentsScale));
+}
+
+IntRect TiledBackingStore::mapFromContents(const IntRect& rect) const
+{
+ return enclosingIntRect(FloatRect(rect.x() * m_contentsScale,
+ rect.y() * m_contentsScale,
+ rect.width() * m_contentsScale,
+ rect.height() * m_contentsScale));
+}
+
+IntRect TiledBackingStore::contentsRect() const
+{
+ return mapFromContents(m_client->tiledBackingStoreContentsRect());
+}
+
+IntRect TiledBackingStore::tileRectForCoordinate(const Tile::Coordinate& coordinate) const
+{
+ IntRect rect(coordinate.x() * m_tileSize.width(),
+ coordinate.y() * m_tileSize.height(),
+ m_tileSize.width(),
+ m_tileSize.height());
+
+ rect.intersect(contentsRect());
+ return rect;
+}
+
+Tile::Coordinate TiledBackingStore::tileCoordinateForPoint(const IntPoint& point) const
+{
+ int x = point.x() / m_tileSize.width();
+ int y = point.y() / m_tileSize.height();
+ return Tile::Coordinate(std::max(x, 0), std::max(y, 0));
+}
+
+
+void TiledBackingStore::startTileBufferUpdateTimer()
+{
+ if (m_tileBufferUpdateTimer->isActive() || m_contentsFrozen)
+ return;
+ m_tileBufferUpdateTimer->startOneShot(0);
+}
+
+void TiledBackingStore::tileBufferUpdateTimerFired(TileTimer*)
+{
+ updateTileBuffers();
+}
+
+void TiledBackingStore::startTileCreationTimer()
+{
+ if (m_tileCreationTimer->isActive() || m_contentsFrozen)
+ return;
+ m_tileCreationTimer->startOneShot(0);
+}
+
+void TiledBackingStore::tileCreationTimerFired(TileTimer*)
+{
+ createTiles();
+}
+
+void TiledBackingStore::setContentsFrozen(bool freeze)
+{
+ if (m_contentsFrozen == freeze)
+ return;
+
+ m_contentsFrozen = freeze;
+
+ // Restart the timers. There might be pending invalidations that
+ // were not painted or created because tiles are not created or
+ // painted when in frozen state.
+ if (m_contentsFrozen)
+ return;
+ if (m_pendingScale)
+ commitScaleChange();
+ else {
+ startTileCreationTimer();
+ startTileBufferUpdateTimer();
+ }
+}
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/TiledBackingStore.h b/WebCore/platform/graphics/TiledBackingStore.h
new file mode 100644
index 0000000..8ed4336
--- /dev/null
+++ b/WebCore/platform/graphics/TiledBackingStore.h
@@ -0,0 +1,110 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TiledBackingStore_h
+#define TiledBackingStore_h
+
+#if ENABLE(TILED_BACKING_STORE)
+
+#include "FloatSize.h"
+#include "IntPoint.h"
+#include "IntRect.h"
+#include "Tile.h"
+#include "Timer.h"
+#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class GraphicsContext;
+class TiledBackingStoreClient;
+
+class TiledBackingStore : public Noncopyable {
+public:
+ TiledBackingStore(TiledBackingStoreClient*);
+ ~TiledBackingStore();
+
+ void viewportChanged(const IntRect& viewportRect);
+
+ float contentsScale() { return m_contentsScale; }
+ void setContentsScale(float);
+
+ bool contentsFrozen() const { return m_contentsFrozen; }
+ void setContentsFrozen(bool);
+
+ void invalidate(const IntRect& dirtyRect);
+ void paint(GraphicsContext*, const IntRect&);
+
+private:
+ void startTileBufferUpdateTimer();
+ void startTileCreationTimer();
+
+ typedef Timer<TiledBackingStore> TileTimer;
+
+ void tileBufferUpdateTimerFired(TileTimer*);
+ void tileCreationTimerFired(TileTimer*);
+
+ void updateTileBuffers();
+ void createTiles();
+
+ void commitScaleChange();
+
+ void dropOverhangingTiles();
+ void dropTilesOutsideRect(const IntRect&);
+
+ PassRefPtr<Tile> tileAt(const Tile::Coordinate&) const;
+ void setTile(const Tile::Coordinate& coordinate, PassRefPtr<Tile> tile);
+ void removeTile(const Tile::Coordinate& coordinate);
+
+ IntRect mapToContents(const IntRect&) const;
+ IntRect mapFromContents(const IntRect&) const;
+
+ IntRect contentsRect() const;
+
+ IntRect tileRectForCoordinate(const Tile::Coordinate&) const;
+ Tile::Coordinate tileCoordinateForPoint(const IntPoint&) const;
+ double tileDistance(const IntRect& viewport, const Tile::Coordinate&);
+
+ void paintCheckerPattern(GraphicsContext*, const IntRect&, const Tile::Coordinate&);
+
+private:
+ TiledBackingStoreClient* m_client;
+
+ typedef HashMap<Tile::Coordinate, RefPtr<Tile> > TileMap;
+ TileMap m_tiles;
+
+ TileTimer* m_tileBufferUpdateTimer;
+ TileTimer* m_tileCreationTimer;
+
+ IntSize m_tileSize;
+
+ IntRect m_viewport;
+ float m_contentsScale;
+ float m_pendingScale;
+
+ bool m_contentsFrozen;
+
+ friend class Tile;
+};
+
+}
+
+#endif
+#endif
diff --git a/WebCore/platform/graphics/TiledBackingStoreClient.h b/WebCore/platform/graphics/TiledBackingStoreClient.h
new file mode 100644
index 0000000..4adbbab
--- /dev/null
+++ b/WebCore/platform/graphics/TiledBackingStoreClient.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TiledBackingStoreClient_h
+#define TiledBackingStoreClient_h
+
+namespace WebCore {
+
+#if ENABLE(TILED_BACKING_STORE)
+class TiledBackingStoreClient {
+public:
+ virtual void tiledBackingStorePaintBegin() = 0;
+ virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&) = 0;
+ virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea) = 0;
+ virtual IntRect tiledBackingStoreContentsRect() = 0;
+};
+
+#else
+class TiledBackingStoreClient {};
+#endif
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/gtk/FontCacheGtk.cpp b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp
index d2b2f39..d2b2f39 100644
--- a/WebCore/platform/graphics/gtk/FontCacheGtk.cpp
+++ b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp
index 169c74c..c2aae49 100644
--- a/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) 2010 Holger Hans Peter Freyther
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -157,7 +158,11 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
}
}
- if (context->textDrawingMode() & cTextStroke) {
+ // Prevent running into a long computation within cairo. If the stroke width is
+ // twice the size of the width of the text we will not ask cairo to stroke
+ // the text as even one single stroke would cover the full wdth of the text.
+ // See https://bugs.webkit.org/show_bug.cgi?id=33759.
+ if (context->textDrawingMode() & cTextStroke && context->strokeThickness() < 2 * offset) {
if (context->strokeGradient()) {
cairo_set_source(cr, context->strokeGradient()->platformGradient());
if (context->getAlpha() < 1.0f) {
diff --git a/WebCore/platform/graphics/gtk/FontCustomPlatformData.cpp b/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp
index bb2e064..bb2e064 100644
--- a/WebCore/platform/graphics/gtk/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp
diff --git a/WebCore/platform/graphics/gtk/FontCustomPlatformData.h b/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
index b36cc79..b36cc79 100644
--- a/WebCore/platform/graphics/gtk/FontCustomPlatformData.h
+++ b/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
diff --git a/WebCore/platform/graphics/gtk/FontPlatformData.h b/WebCore/platform/graphics/cairo/FontPlatformData.h
index d30b480..3c926fe 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformData.h
+++ b/WebCore/platform/graphics/cairo/FontPlatformData.h
@@ -2,7 +2,7 @@
* This file is part of the internal font implementation. It should not be included by anyone other than
* FontMac.cpp, FontWin.cpp and Font.cpp.
*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc.
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007 Holger Hans Peter Freyther
* Copyright (C) 2007 Pioneer Research Center USA, Inc.
@@ -28,18 +28,25 @@
#ifndef FontPlatformData_h
#define FontPlatformData_h
-#include "GlyphBuffer.h"
#include "FontDescription.h"
+#include "GlyphBuffer.h"
#include <cairo.h>
#if defined(USE_FREETYPE)
#include <cairo-ft.h>
#include <fontconfig/fcfreetype.h>
#elif defined(USE_PANGO)
#include <pango/pangocairo.h>
+#elif PLATFORM(WIN)
+#include <cairo-win32.h>
+#include "RefCountedHFONT.h"
+#include "StringImpl.h"
#else
#error "Must defined a font backend"
#endif
+#if PLATFORM(WIN)
+typedef struct HFONT__* HFONT;
+#endif
namespace WebCore {
class String;
@@ -53,9 +60,16 @@ public:
#elif defined(USE_PANGO)
: m_context(0)
, m_font(hashTableDeletedFontValue())
+#elif PLATFORM(WIN)
+ : m_fontFace(0)
+ , m_useGDI(false)
+ , m_font(WTF::HashTableDeletedValue)
#else
#error "Must defined a font backend"
#endif
+ , m_size(0)
+ , m_syntheticBold(false)
+ , m_syntheticOblique(false)
, m_scaledFont(0)
{ }
@@ -66,24 +80,41 @@ public:
#elif defined(USE_PANGO)
: m_context(0)
, m_font(0)
+#elif PLATFORM(WIN)
+ : m_fontFace(0)
+ , m_useGDI(false)
#else
#error "Must defined a font backend"
#endif
+ , m_size(0)
+ , m_syntheticBold(false)
+ , m_syntheticOblique(false)
, m_scaledFont(0)
{ }
+#if PLATFORM(WIN)
+ FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI);
+#else
FontPlatformData(const FontDescription&, const AtomicString& family);
+#endif
+ FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic);
FontPlatformData(float size, bool bold, bool italic);
- FontPlatformData(cairo_font_face_t* fontFace, int size, bool bold, bool italic);
FontPlatformData(const FontPlatformData&);
~FontPlatformData();
+#if !PLATFORM(WIN)
static bool init();
+#else
+ HFONT hfont() const { return m_font->hfont(); }
+ bool useGDI() const { return m_useGDI; }
+ cairo_font_face_t* fontFace() const { return m_fontFace; }
+#endif
bool isFixedPitch();
float size() const { return m_size; }
+ void setSize(float size) { m_size = size; }
bool syntheticBold() const { return m_syntheticBold; }
bool syntheticOblique() const { return m_syntheticOblique; }
@@ -91,23 +122,30 @@ public:
unsigned hash() const
{
+#if PLATFORM(WIN)
+ return m_font->hash();
+#else
#if defined(USE_FREETYPE)
if (m_pattern)
return FcPatternHash(m_pattern);
#endif
uintptr_t hashCodes[1] = { reinterpret_cast<uintptr_t>(m_scaledFont) };
return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
+#endif
}
bool operator==(const FontPlatformData&) const;
FontPlatformData& operator=(const FontPlatformData&);
- bool isHashTableDeletedValue() const {
+ bool isHashTableDeletedValue() const
+ {
#if defined(USE_FREETYPE)
return m_pattern == hashTableDeletedFontValue();
#elif defined(USE_PANGO)
return m_font == hashTableDeletedFontValue();
+#elif PLATFORM(WIN)
+ return m_font.isHashTableDeletedValue();
#endif
- };
+ }
#ifndef NDEBUG
String description() const;
@@ -122,6 +160,13 @@ public:
PangoContext* m_context;
PangoFont* m_font;
+#elif PLATFORM(WIN)
+private:
+ void platformDataInit(HFONT, float size, HDC, WCHAR* faceName);
+
+ RefPtr<RefCountedHFONT> m_font;
+ cairo_font_face_t* m_fontFace;
+ bool m_useGDI;
#else
#error "Must defined a font backend"
#endif
diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp b/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp
index 0b1280e..974c195 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
+++ b/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp
@@ -25,14 +25,14 @@
#include "config.h"
#include "FontPlatformData.h"
-#include "CString.h"
#include "PlatformString.h"
#include "FontDescription.h"
+#include <wtf/text/CString.h>
#include <cairo-ft.h>
#include <cairo.h>
#include <fontconfig/fcfreetype.h>
-#include <gtk/gtk.h>
+#include <gdk/gdk.h>
namespace WebCore {
@@ -134,7 +134,7 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool italic)
{
}
-FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, int size, bool bold, bool italic)
+FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic)
: m_pattern(0)
, m_fallbacks(0)
, m_size(size)
diff --git a/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp
index 7c9ffe6..7c9ffe6 100644
--- a/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp
+++ b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp
diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp
index bc68b37..91cecd3 100644
--- a/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -89,7 +89,7 @@ bool Path::hasCurrentPoint() const
void Path::translate(const FloatSize& p)
{
cairo_t* cr = platformPath()->m_cr;
- cairo_translate(cr, p.width(), p.height());
+ cairo_translate(cr, -p.width(), -p.height());
}
void Path::moveTo(const FloatPoint& p)
@@ -267,9 +267,6 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
bool Path::contains(const FloatPoint& point, WindRule rule) const
{
- if (!boundingRect().contains(point))
- return false;
-
cairo_t* cr = platformPath()->m_cr;
cairo_fill_rule_t cur = cairo_get_fill_rule(cr);
cairo_set_fill_rule(cr, rule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp
index df25393..0be45f6 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
+++ b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp
@@ -114,7 +114,7 @@ void SimpleFontData::determinePitch()
m_treatAsFixedPitch = m_platformData.isFixedPitch();
}
-float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const
{
ASSERT(m_platformData.m_scaledFont);
@@ -125,7 +125,10 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
float w = (float)m_spaceWidth;
if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0)
w = (float)extents.x_advance;
- return w;
+
+ GlyphMetrics metrics;
+ metrics.horizontalAdvance = w;
+ return metrics;
}
}
diff --git a/WebCore/platform/graphics/win/FontPlatformData.h b/WebCore/platform/graphics/cg/FontPlatformData.h
index 5084469..da2b7e3 100644
--- a/WebCore/platform/graphics/win/FontPlatformData.h
+++ b/WebCore/platform/graphics/cg/FontPlatformData.h
@@ -2,7 +2,7 @@
* This file is part of the internal font implementation. It should not be included by anyone other than
* FontMac.cpp, FontWin.cpp and Font.cpp.
*
- * Copyright (C) 2006, 2007, 2008 Apple Inc.
+ * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,17 +21,14 @@
*
*/
-#ifndef FontPlatformData_H
-#define FontPlatformData_H
+#ifndef FontPlatformData_h
+#define FontPlatformData_h
+#include "RefCountedHFONT.h"
#include "StringImpl.h"
#include <wtf/PassRefPtr.h>
-#include <wtf/RetainPtr.h>
#include <wtf/RefCounted.h>
-
-#if PLATFORM(CAIRO)
-#include <cairo-win32.h>
-#endif
+#include <wtf/RetainPtr.h>
typedef struct HFONT__* HFONT;
typedef struct CGFont* CGFontRef;
@@ -44,14 +41,7 @@ class String;
class FontPlatformData {
public:
FontPlatformData()
-#if PLATFORM(CAIRO)
- : m_fontFace(0)
- , m_scaledFont(0)
- ,
-#else
- :
-#endif
- m_size(0)
+ : m_size(0)
, m_syntheticBold(false)
, m_syntheticOblique(false)
, m_useGDI(false)
@@ -61,26 +51,14 @@ public:
FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI);
FontPlatformData(float size, bool bold, bool oblique);
-#if PLATFORM(CG)
FontPlatformData(HFONT, CGFontRef, float size, bool bold, bool oblique, bool useGDI);
-#elif PLATFORM(CAIRO)
- FontPlatformData(cairo_font_face_t*, float size, bool bold, bool oblique);
- FontPlatformData(const FontPlatformData&);
-
- FontPlatformData& operator=(const FontPlatformData&);
-#endif
~FontPlatformData();
FontPlatformData(WTF::HashTableDeletedValueType) : m_font(WTF::HashTableDeletedValue) { }
bool isHashTableDeletedValue() const { return m_font.isHashTableDeletedValue(); }
HFONT hfont() const { return m_font->hfont(); }
-#if PLATFORM(CG)
CGFontRef cgFont() const { return m_cgFont.get(); }
-#elif PLATFORM(CAIRO)
- cairo_font_face_t* fontFace() const { return m_fontFace; }
- cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
-#endif
float size() const { return m_size; }
void setSize(float size) { m_size = size; }
@@ -95,16 +73,12 @@ public:
bool operator==(const FontPlatformData& other) const
{
- return m_font == other.m_font &&
-#if PLATFORM(CG)
- m_cgFont == other.m_cgFont &&
-#elif PLATFORM(CAIRO)
- m_fontFace == other.m_fontFace &&
- m_scaledFont == other.m_scaledFont &&
-#endif
- m_size == other.m_size &&
- m_syntheticBold == other.m_syntheticBold && m_syntheticOblique == other.m_syntheticOblique &&
- m_useGDI == other.m_useGDI;
+ return m_font == other.m_font
+ && m_cgFont == other.m_cgFont
+ && m_size == other.m_size
+ && m_syntheticBold == other.m_syntheticBold
+ && m_syntheticOblique == other.m_syntheticOblique
+ && m_useGDI == other.m_useGDI;
}
#ifndef NDEBUG
@@ -112,37 +86,10 @@ public:
#endif
private:
- class RefCountedHFONT : public RefCounted<RefCountedHFONT> {
- public:
- static PassRefPtr<RefCountedHFONT> create(HFONT hfont) { return adoptRef(new RefCountedHFONT(hfont)); }
- static PassRefPtr<RefCountedHFONT> createDeleted() { return adoptRef(new RefCountedHFONT(reinterpret_cast<HFONT>(-1))); }
-
- ~RefCountedHFONT() { if (m_hfont != reinterpret_cast<HFONT>(-1)) DeleteObject(m_hfont); }
-
- HFONT hfont() const { return m_hfont; }
- unsigned hash() const
- {
- return StringImpl::computeHash(reinterpret_cast<const UChar*>(&m_hfont), sizeof(HFONT) / sizeof(UChar));
- }
-
- private:
- RefCountedHFONT(HFONT hfont)
- : m_hfont(hfont)
- {
- }
-
- HFONT m_hfont;
- };
-
- void platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName);
+ void platformDataInit(HFONT, float size, HDC, WCHAR* faceName);
RefPtr<RefCountedHFONT> m_font;
-#if PLATFORM(CG)
RetainPtr<CGFontRef> m_cgFont;
-#elif PLATFORM(CAIRO)
- cairo_font_face_t* m_fontFace;
- cairo_scaled_font_t* m_scaledFont;
-#endif
float m_size;
bool m_syntheticBold;
diff --git a/WebCore/platform/graphics/cg/GradientCG.cpp b/WebCore/platform/graphics/cg/GradientCG.cpp
index 9c91700..4aaaeaf 100644
--- a/WebCore/platform/graphics/cg/GradientCG.cpp
+++ b/WebCore/platform/graphics/cg/GradientCG.cpp
@@ -29,8 +29,8 @@
#include "CSSParser.h"
#include "GraphicsContext.h"
-
#include <ApplicationServices/ApplicationServices.h>
+#include <wtf/RetainPtr.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
index b1efba1..aac4f45 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
+++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -23,6 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <wtf/RetainPtr.h>
#include <CoreGraphics/CGContext.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 0dc7a53..c82ebdc 100644
--- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -29,15 +29,16 @@
#include "Base64.h"
#include "BitmapImage.h"
-#include "CString.h"
#include "GraphicsContext.h"
#include "ImageData.h"
#include "MIMETypeRegistry.h"
#include "PlatformString.h"
#include <ApplicationServices/ApplicationServices.h>
#include <wtf/Assertions.h>
+#include <wtf/text/CString.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/RetainPtr.h>
+#include <wtf/Threading.h>
#include <math.h>
using namespace std;
@@ -254,6 +255,8 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
RetainPtr<CFStringRef> mimeTypeCFString(AdoptCF, mimeType.createCFString());
return RetainPtr<CFStringRef>(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeTypeCFString.get(), 0));
#else
+ ASSERT(isMainThread()); // It is unclear if CFSTR is threadsafe.
+
// FIXME: Add Windows support for all the supported UTIs when a way to convert from MIMEType to UTI reliably is found.
// For now, only support PNG, JPEG, and GIF. See <rdar://problem/6095286>.
static const CFStringRef kUTTypePNG = CFSTR("public.png");
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index 2b2c6b0..b4e1ca9 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -74,7 +74,7 @@ ImageSource::~ImageSource()
void ImageSource::clear(bool destroyAllFrames, size_t, SharedBuffer* data, bool allDataReceived)
{
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
// Recent versions of ImageIO discard previously decoded image frames if the client
// application no longer holds references to them, so there's no need to throw away
// the decoder unless we're explicitly asked to destroy all of the frames.
@@ -119,14 +119,22 @@ bool ImageSource::initialized() const
void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
{
- if (!m_decoder)
- m_decoder = CGImageSourceCreateIncremental(NULL);
#if PLATFORM(MAC)
+ if (!m_decoder)
+ m_decoder = CGImageSourceCreateIncremental(0);
// 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.
RetainPtr<CFDataRef> cfData(AdoptCF, data->createCFData());
CGImageSourceUpdateData(m_decoder, cfData.get(), allDataReceived);
#else
+ if (!m_decoder) {
+ m_decoder = CGImageSourceCreateIncremental(0);
+ } else if (allDataReceived) {
+ // 10.6 bug workaround: image sources with final=false fail to draw into PDF contexts, so re-create image source
+ // when data is complete. <rdar://problem/7874035> (<http://openradar.appspot.com/7874035>)
+ CFRelease(m_decoder);
+ m_decoder = CGImageSourceCreateIncremental(0);
+ }
// Create a CGDataProvider to wrap the SharedBuffer.
data->ref();
// We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
@@ -234,7 +242,22 @@ CGImageRef ImageSource::createFrameAtIndex(size_t index)
bool ImageSource::frameIsCompleteAtIndex(size_t index)
{
- return CGImageSourceGetStatusAtIndex(m_decoder, index) == kCGImageStatusComplete;
+ ASSERT(frameCount());
+
+ // CGImageSourceGetStatusAtIndex claims that all frames of a multi-frame image are incomplete
+ // when we've not yet received the complete data for an image that is using an incremental data
+ // source (<rdar://problem/7679174>). We work around this by special-casing all frames except the
+ // last in an image and treating them as complete if they are present and reported as being
+ // incomplete. We do this on the assumption that loading new data can only modify the existing last
+ // frame or append new frames. The last frame is only treated as being complete if the image source
+ // reports it as such. This ensures that it is truly the last frame of the image rather than just
+ // the last that we currently have data for.
+
+ CGImageSourceStatus frameStatus = CGImageSourceGetStatusAtIndex(m_decoder, index);
+ if (index < frameCount() - 1)
+ return frameStatus >= kCGImageStatusIncomplete;
+
+ return frameStatus == kCGImageStatusComplete;
}
float ImageSource::frameDurationAtIndex(size_t index)
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
index 67333ae..8bf04f1 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
@@ -31,7 +31,9 @@
#include "GraphicsContext.h"
#include "ImageObserver.h"
+#include "SharedBuffer.h"
#include <wtf/MathExtras.h>
+#include <wtf/RetainPtr.h>
#if !PLATFORM(MAC)
#include "ImageSourceCG.h"
@@ -54,6 +56,11 @@ PDFDocumentImage::~PDFDocumentImage()
CGPDFDocumentRelease(m_document);
}
+String PDFDocumentImage::filenameExtension() const
+{
+ return "pdf";
+}
+
IntSize PDFDocumentImage::size() const
{
const float sina = sinf(-m_rotation);
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.h b/WebCore/platform/graphics/cg/PDFDocumentImage.h
index 12ab46c..790d620 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.h
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.h
@@ -46,6 +46,8 @@ namespace WebCore {
private:
virtual ~PDFDocumentImage();
+ virtual String filenameExtension() const;
+
virtual bool hasSingleSecurityOrigin() const { return true; }
virtual bool dataChanged(bool allDataReceived);
diff --git a/WebCore/platform/graphics/cg/PathCG.cpp b/WebCore/platform/graphics/cg/PathCG.cpp
index 81454b3..eb196d9 100644
--- a/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/WebCore/platform/graphics/cg/PathCG.cpp
@@ -30,14 +30,14 @@
#if PLATFORM(CG)
#include "AffineTransform.h"
-#include <ApplicationServices/ApplicationServices.h>
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "IntRect.h"
#include "PlatformString.h"
#include "StrokeStyleApplier.h"
-
+#include <ApplicationServices/ApplicationServices.h>
#include <wtf/MathExtras.h>
+#include <wtf/RetainPtr.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
index 8dac612..6f46f7e 100644
--- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -140,6 +140,9 @@ static bool LookupAltName(const String& name, String& altName)
// 宋体, SimSun
{L"\x5B8B\x4F53", {L"SimSun", simplifiedChineseCodepage}},
{L"simsun", {L"\x5B8B\x4F53", simplifiedChineseCodepage}},
+ // 宋体-ExtB, SimSun-ExtB
+ {L"\x5B8B\x4F53-ExtB", {L"SimSun-ExtB", simplifiedChineseCodepage}},
+ {L"simsun-extb", {L"\x5B8B\x4F53-extb", simplifiedChineseCodepage}},
// 黑体, SimHei
{L"\x9ED1\x4F53", {L"SimHei", simplifiedChineseCodepage}},
{L"simhei", {L"\x9ED1\x4F53", simplifiedChineseCodepage}},
@@ -164,9 +167,15 @@ static bool LookupAltName(const String& name, String& altName)
// 新細明體, PMingLiu
{L"\x65B0\x7D30\x660E\x9AD4", {L"PMingLiu", traditionalChineseCodepage}},
{L"pmingliu", {L"\x65B0\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
+ // 新細明體-ExtB, PMingLiu-ExtB
+ {L"\x65B0\x7D30\x660E\x9AD4-ExtB", {L"PMingLiu-ExtB", traditionalChineseCodepage}},
+ {L"pmingliu-extb", {L"\x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}},
// 細明體, MingLiu
{L"\x7D30\x660E\x9AD4", {L"MingLiu", traditionalChineseCodepage}},
{L"mingliu", {L"\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
+ // 細明體-ExtB, MingLiu-ExtB
+ {L"\x7D30\x660E\x9AD4-ExtB", {L"MingLiu-ExtB", traditionalChineseCodepage}},
+ {L"mingliu-extb", {L"x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}},
// 微軟正黑體, Microsoft JhengHei
{L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", {L"Microsoft JhengHei", traditionalChineseCodepage}},
{L"microsoft jhengHei", {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", traditionalChineseCodepage}},
@@ -363,8 +372,10 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons
L"lucida sans unicode",
L"microsoft sans serif",
L"palatino linotype",
- // Four fonts below (and code2000 at the end) are not from MS, but
+ // Six fonts below (and code2000 at the end) are not from MS, but
// once installed, cover a very wide range of characters.
+ L"dejavu serif",
+ L"dejavu sasns",
L"freeserif",
L"freesans",
L"gentium",
diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
index 03d23c7..ececd13 100644
--- a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
@@ -33,7 +33,6 @@
#include "AtomicString.h"
#include "ChromiumBridge.h"
-#include "CString.h"
#include "Font.h"
#include "FontDescription.h"
#include "FontPlatformData.h"
@@ -47,6 +46,7 @@
#include <unicode/utf16.h>
#include <wtf/Assertions.h>
+#include <wtf/text/CString.h>
namespace WebCore {
@@ -107,7 +107,9 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
const char* name = 0;
CString s;
- if (family.length() == 0) {
+ // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into
+ // the fallback name (like "monospace") that fontconfig understands.
+ if (!family.length() || family.startsWith("-webkit-")) {
static const struct {
FontDescription::GenericFamilyType mType;
const char* mName;
@@ -145,6 +147,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
FontPlatformData* result =
new FontPlatformData(tf,
+ name,
fontDescription.computedSize(),
(style & SkTypeface::kBold) && !tf->isBold(),
(style & SkTypeface::kItalic) && !tf->isItalic());
diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 9f8f354..9538a8d 100644
--- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -503,7 +503,7 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
context->canvas()->endPlatformPaint();
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
{
UniscribeHelperTextRun state(run, *this);
return static_cast<float>(state.width());
diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
index 6432e17..74f1e26 100644
--- a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
@@ -101,7 +101,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
return FontPlatformData(hfont, size);
#elif OS(LINUX)
ASSERT(m_fontReference);
- return FontPlatformData(m_fontReference, size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic());
+ return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic());
#else
notImplemented();
return FontPlatformData();
diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp
index e76eca8..fa549cd 100644
--- a/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -521,7 +521,7 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
}
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
{
TextRunWalker walker(run, 0, this);
return walker.widthOfFullRun();
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
index bf4697f..2475e65 100644
--- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "FontPlatformData.h"
+#include "ChromiumBridge.h"
#include "HarfbuzzSkia.h"
#include "NotImplemented.h"
#include "PlatformString.h"
@@ -66,31 +67,37 @@ FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace()
FontPlatformData::FontPlatformData(const FontPlatformData& src)
: m_typeface(src.m_typeface)
+ , m_family(src.m_family)
, m_textSize(src.m_textSize)
, m_fakeBold(src.m_fakeBold)
, m_fakeItalic(src.m_fakeItalic)
+ , m_style(src.m_style)
, m_harfbuzzFace(src.m_harfbuzzFace)
{
m_typeface->safeRef();
}
-FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic)
+FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic)
: m_typeface(tf)
+ , m_family(family)
, m_textSize(textSize)
, m_fakeBold(fakeBold)
, m_fakeItalic(fakeItalic)
{
m_typeface->safeRef();
+ querySystemForRenderStyle();
}
FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
: m_typeface(src.m_typeface)
+ , m_family(src.m_family)
, m_textSize(textSize)
, m_fakeBold(src.m_fakeBold)
, m_fakeItalic(src.m_fakeItalic)
, m_harfbuzzFace(src.m_harfbuzzFace)
{
m_typeface->safeRef();
+ querySystemForRenderStyle();
}
FontPlatformData::~FontPlatformData()
@@ -102,10 +109,12 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
{
SkRefCnt_SafeAssign(m_typeface, src.m_typeface);
+ m_family = src.m_family;
m_textSize = src.m_textSize;
m_fakeBold = src.m_fakeBold;
m_fakeItalic = src.m_fakeItalic;
m_harfbuzzFace = src.m_harfbuzzFace;
+ m_style = src.m_style;
return *this;
}
@@ -121,13 +130,26 @@ void FontPlatformData::setupPaint(SkPaint* paint) const
{
const float ts = m_textSize > 0 ? m_textSize : 12;
- paint->setAntiAlias(isSkiaAntiAlias);
- paint->setHinting(skiaHinting);
- paint->setLCDRenderText(isSkiaSubpixelGlyphs);
+ paint->setAntiAlias(m_style.useAntiAlias == FontRenderStyle::NoPreference ? isSkiaAntiAlias : m_style.useAntiAlias);
+ switch (m_style.useHinting) {
+ case FontRenderStyle::NoPreference:
+ paint->setHinting(skiaHinting);
+ break;
+ case 0:
+ paint->setHinting(SkPaint::kNo_Hinting);
+ break;
+ default:
+ paint->setHinting(static_cast<SkPaint::Hinting>(m_style.hintStyle));
+ break;
+ }
+
paint->setTextSize(SkFloatToScalar(ts));
paint->setTypeface(m_typeface);
paint->setFakeBoldText(m_fakeBold);
paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0);
+
+ if (m_style.useAntiAlias == 1 || m_style.useAntiAlias == FontRenderStyle::NoPreference && isSkiaAntiAlias)
+ paint->setLCDRenderText(m_style.useSubpixel == FontRenderStyle::NoPreference ? isSkiaSubpixelGlyphs : m_style.useSubpixel);
}
SkFontID FontPlatformData::uniqueID() const
@@ -184,4 +206,21 @@ HB_FaceRec_* FontPlatformData::harfbuzzFace() const
return m_harfbuzzFace->face();
}
+void FontPlatformData::querySystemForRenderStyle()
+{
+ if (!m_family.length()) {
+ // We don't have a family for this. Probably because it's a webfont. We
+ // set all the values to 'no preference' and take the defaults passed
+ // in from XSETTINGS.
+ m_style.useBitmaps = FontRenderStyle::NoPreference;
+ m_style.useAutoHint = FontRenderStyle::NoPreference;
+ m_style.useHinting = FontRenderStyle::NoPreference;
+ m_style.useAntiAlias = FontRenderStyle::NoPreference;
+ m_style.useSubpixel = FontRenderStyle::NoPreference;
+ return;
+ }
+
+ ChromiumBridge::getRenderStyleForStrike(m_family.data(), (((int)m_textSize) << 2) | (m_typeface->style() & 3), &m_style);
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
index 29ce8e7..e2abe2e 100644
--- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -31,8 +31,10 @@
#ifndef FontPlatformDataLinux_h
#define FontPlatformDataLinux_h
+#include "FontRenderStyle.h"
#include "StringImpl.h"
#include <wtf/RefPtr.h>
+#include <wtf/text/CString.h>
#include <SkPaint.h>
class SkTypeface;
@@ -79,7 +81,7 @@ public:
{ }
FontPlatformData(const FontPlatformData&);
- FontPlatformData(SkTypeface*, float textSize, bool fakeBold, bool fakeItalic);
+ FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic);
FontPlatformData(const FontPlatformData& src, float textSize);
~FontPlatformData();
@@ -140,11 +142,15 @@ private:
HB_FaceRec_* m_harfbuzzFace;
};
+ void querySystemForRenderStyle();
+
// FIXME: Could SkAutoUnref be used here?
SkTypeface* m_typeface;
+ CString m_family;
float m_textSize;
bool m_fakeBold;
bool m_fakeItalic;
+ FontRenderStyle m_style;
mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace;
SkTypeface* hashTableDeletedFontValue() const { return reinterpret_cast<SkTypeface*>(-1); }
diff --git a/WebCore/platform/graphics/chromium/FontRenderStyle.h b/WebCore/platform/graphics/chromium/FontRenderStyle.h
new file mode 100644
index 0000000..1a3c736
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/FontRenderStyle.h
@@ -0,0 +1,56 @@
+/* Copyright (c) 2010, 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 FontRenderStyle_h
+#define FontRenderStyle_h
+
+namespace WebCore {
+
+// FontRenderStyle describes the user's preferences for rendering a font at a
+// given size.
+struct FontRenderStyle {
+ enum {
+ NoPreference = 2,
+ };
+
+ // Each of the use* members below can take one of three values:
+ // 0: off
+ // 1: on
+ // NoPreference: no preference expressed
+ char useBitmaps; // use embedded bitmap strike if possible
+ char useAutoHint; // use 'auto' hinting (FreeType specific)
+ char useHinting; // hint glyphs to the pixel grid
+ char hintStyle; // level of hinting, 0..3
+ char useAntiAlias; // antialias glyph shapes
+ char useSubpixel; // use subpixel antialias
+};
+
+}
+
+#endif // FontRenderStyle_h
diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
index 4e2a226..8dba49e 100644
--- a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
@@ -60,6 +60,7 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap)
{USCRIPT_GREEK, L"times new roman"},
{USCRIPT_CYRILLIC, L"times new roman"},
{USCRIPT_SIMPLIFIED_HAN, L"simsun"},
+ {USCRIPT_TRADITIONAL_HAN, L"pmingliu"},
{USCRIPT_HIRAGANA, L"ms pgothic"},
{USCRIPT_KATAKANA, L"ms pgothic"},
{USCRIPT_KATAKANA_OR_HIRAGANA, L"ms pgothic"},
@@ -106,14 +107,10 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap)
localeFamily = scriptFontMap[USCRIPT_HIRAGANA];
else if (locale == icu::Locale::getKorean())
localeFamily = scriptFontMap[USCRIPT_HANGUL];
+ else if (locale == icu::Locale::getTraditionalChinese())
+ localeFamily = scriptFontMap[USCRIPT_TRADITIONAL_HAN];
else {
- // Use Simplified Chinese font for all other locales including
- // Traditional Chinese because Simsun (SC font) has a wider
- // coverage (covering both SC and TC) than PMingLiu (TC font).
- // Note that |fontMap| does not have a separate entry for
- // USCRIPT_TRADITIONAL_HAN for that reason.
- // This also speeds up the TC version of Chrome when rendering SC
- // pages.
+ // For other locales, use the simplified Chinese font for Han.
localeFamily = scriptFontMap[USCRIPT_SIMPLIFIED_HAN];
}
if (localeFamily)
@@ -270,16 +267,27 @@ const UChar* getFallbackFamily(const UChar* characters,
if (script == USCRIPT_COMMON)
script = getScriptBasedOnUnicodeBlock(ucs4);
- // Another lame work-around to cover non-BMP characters.
const UChar* family = getFontFamilyForScript(script, generic);
- if (!family) {
+ // Another lame work-around to cover non-BMP characters.
+ // If the font family for script is not found or the character is
+ // not in BMP (> U+FFFF), we resort to the hard-coded list of
+ // fallback fonts for now.
+ if (!family || ucs4 > 0xFFFF) {
int plane = ucs4 >> 16;
switch (plane) {
case 1:
family = L"code2001";
break;
case 2:
- family = L"simsun-extb";
+ // Use a Traditional Chinese ExtB font if in Traditional Chinese locale.
+ // Otherwise, use a Simplified Chinese ExtB font. Windows Japanese
+ // fonts do support a small subset of ExtB (that are included in JIS X 0213),
+ // but its coverage is rather sparse.
+ // Eventually, this should be controlled by lang/xml:lang.
+ if (icu::Locale::getDefault() == icu::Locale::getTraditionalChinese())
+ family = L"pmingliu-extb";
+ else
+ family = L"simsun-extb";
break;
default:
family = L"lucida sans unicode";
diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
new file mode 100644
index 0000000..1227a6a
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions 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.
+ */
+
+
+/** FIXME
+ * This file borrows code heavily from platform/graphics/win/GraphicsLayerCACF.cpp
+ * (and hence it includes both copyrights)
+ * Ideally the common code (mostly the code that keeps track of the layer hierarchy)
+ * should be kept separate and shared between platforms. It would be a well worthwhile
+ * effort once the Windows implementation (binaries and headers) of CoreAnimation is
+ * checked in to the WebKit repository. Until then only Apple can make this happen.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsLayerChromium.h"
+
+#include "FloatConversion.h"
+#include "FloatRect.h"
+#include "Image.h"
+#include "LayerChromium.h"
+#include "PlatformString.h"
+#include "SystemTime.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/StringExtras.h>
+#include <wtf/text/CString.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static void setLayerBorderColor(LayerChromium& layer, const Color& color)
+{
+ layer.setBorderColor(color);
+}
+
+static void clearBorderColor(LayerChromium& layer)
+{
+ layer.setBorderColor(0);
+}
+
+static void setLayerBackgroundColor(LayerChromium& layer, const Color& color)
+{
+ layer.setBackgroundColor(color);
+}
+
+static void clearLayerBackgroundColor(LayerChromium& layer)
+{
+ layer.setBackgroundColor(0);
+}
+
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
+{
+ return CompositingCoordinatesBottomUp;
+}
+
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerChromium(client);
+}
+
+GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
+ : GraphicsLayer(client)
+ , m_contentsLayerPurpose(NoContentsLayer)
+ , m_contentsLayerHasBackgroundColor(false)
+{
+ m_layer = LayerChromium::create(LayerChromium::Layer, this);
+
+ updateDebugIndicators();
+}
+
+GraphicsLayerChromium::~GraphicsLayerChromium()
+{
+ // Clean up the Skia layer.
+ if (m_layer)
+ m_layer->removeFromSuperlayer();
+
+ if (m_transformLayer)
+ m_transformLayer->removeFromSuperlayer();
+}
+
+void GraphicsLayerChromium::setName(const String& inName)
+{
+ String name = String::format("GraphicsLayerChromium(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
+ GraphicsLayer::setName(name);
+}
+
+NativeLayer GraphicsLayerChromium::nativeLayer() const
+{
+ return m_layer.get();
+}
+
+bool GraphicsLayerChromium::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 GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
+{
+ GraphicsLayer::addChild(childLayer);
+ updateSublayerList();
+}
+
+void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index)
+{
+ GraphicsLayer::addChildAtIndex(childLayer, index);
+ updateSublayerList();
+}
+
+void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildBelow(childLayer, sibling);
+ updateSublayerList();
+}
+
+void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
+{
+ GraphicsLayer::addChildAbove(childLayer, sibling);
+ updateSublayerList();
+}
+
+bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ if (GraphicsLayer::replaceChild(oldChild, newChild)) {
+ updateSublayerList();
+ return true;
+ }
+ return false;
+}
+
+void GraphicsLayerChromium::removeFromParent()
+{
+ GraphicsLayer::removeFromParent();
+ layerForSuperlayer()->removeFromSuperlayer();
+}
+
+void GraphicsLayerChromium::setPosition(const FloatPoint& point)
+{
+ GraphicsLayer::setPosition(point);
+ updateLayerPosition();
+}
+
+void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point)
+{
+ if (point == m_anchorPoint)
+ return;
+
+ GraphicsLayer::setAnchorPoint(point);
+ updateAnchorPoint();
+}
+
+void GraphicsLayerChromium::setSize(const FloatSize& size)
+{
+ if (size == m_size)
+ return;
+
+ GraphicsLayer::setSize(size);
+ updateLayerSize();
+}
+
+void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform)
+{
+ if (transform == m_transform)
+ return;
+
+ GraphicsLayer::setTransform(transform);
+ updateTransform();
+}
+
+void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform)
+{
+ if (transform == m_childrenTransform)
+ return;
+
+ GraphicsLayer::setChildrenTransform(transform);
+ updateChildrenTransform();
+}
+
+void GraphicsLayerChromium::setPreserves3D(bool preserves3D)
+{
+ if (preserves3D == m_preserves3D)
+ return;
+
+ GraphicsLayer::setPreserves3D(preserves3D);
+ updateLayerPreserves3D();
+}
+
+void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds)
+{
+ if (masksToBounds == m_masksToBounds)
+ return;
+
+ GraphicsLayer::setMasksToBounds(masksToBounds);
+ updateMasksToBounds();
+}
+
+void GraphicsLayerChromium::setDrawsContent(bool drawsContent)
+{
+ if (drawsContent == m_drawsContent)
+ return;
+
+ GraphicsLayer::setDrawsContent(drawsContent);
+ updateLayerDrawsContent();
+}
+
+void GraphicsLayerChromium::setBackgroundColor(const Color& color)
+{
+ if (m_backgroundColorSet && m_backgroundColor == color)
+ return;
+
+ GraphicsLayer::setBackgroundColor(color);
+
+ m_contentsLayerHasBackgroundColor = true;
+ updateLayerBackgroundColor();
+}
+
+void GraphicsLayerChromium::clearBackgroundColor()
+{
+ if (!m_backgroundColorSet)
+ return;
+
+ GraphicsLayer::clearBackgroundColor();
+ clearLayerBackgroundColor(*m_contentsLayer);
+}
+
+void GraphicsLayerChromium::setContentsOpaque(bool opaque)
+{
+ if (m_contentsOpaque == opaque)
+ return;
+
+ GraphicsLayer::setContentsOpaque(opaque);
+ updateContentsOpaque();
+}
+
+void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
+{
+ if (m_backfaceVisibility == visible)
+ return;
+
+ GraphicsLayer::setBackfaceVisibility(visible);
+ updateBackfaceVisibility();
+}
+
+void GraphicsLayerChromium::setOpacity(float opacity)
+{
+ float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
+
+ if (m_opacity == clampedOpacity)
+ return;
+
+ GraphicsLayer::setOpacity(clampedOpacity);
+ primaryLayer()->setOpacity(opacity);
+}
+
+void GraphicsLayerChromium::setNeedsDisplay()
+{
+ if (drawsContent())
+ m_layer->setNeedsDisplay();
+}
+
+void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ if (drawsContent())
+ m_layer->setNeedsDisplay(rect);
+}
+
+void GraphicsLayerChromium::setContentsRect(const IntRect& rect)
+{
+ if (rect == m_contentsRect)
+ return;
+
+ GraphicsLayer::setContentsRect(rect);
+ updateContentsRect();
+}
+
+void GraphicsLayerChromium::setContentsToImage(Image* image)
+{
+ // FIXME: Implement
+}
+
+void GraphicsLayerChromium::setContentsToVideo(PlatformLayer* videoLayer)
+{
+ // FIXME: Implement
+}
+
+void GraphicsLayerChromium::setGeometryOrientation(CompositingCoordinatesOrientation orientation)
+{
+ if (orientation == m_geometryOrientation)
+ return;
+
+ GraphicsLayer::setGeometryOrientation(orientation);
+ updateGeometryOrientation();
+}
+
+PlatformLayer* GraphicsLayerChromium::hostLayerForSublayers() const
+{
+ return m_transformLayer ? m_transformLayer.get() : m_layer.get();
+}
+
+PlatformLayer* GraphicsLayerChromium::layerForSuperlayer() const
+{
+ return m_transformLayer ? m_transformLayer.get() : m_layer.get();
+}
+
+PlatformLayer* GraphicsLayerChromium::platformLayer() const
+{
+ return primaryLayer();
+}
+
+void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color)
+{
+ if (color.isValid())
+ setLayerBackgroundColor(*m_layer, color);
+ else
+ clearLayerBackgroundColor(*m_layer);
+}
+
+void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth)
+{
+ if (color.isValid()) {
+ setLayerBorderColor(*m_layer, color);
+ m_layer->setBorderWidth(borderWidth);
+ } else {
+ clearBorderColor(*m_layer);
+ m_layer->setBorderWidth(0);
+ }
+}
+
+void GraphicsLayerChromium::updateSublayerList()
+{
+ Vector<RefPtr<LayerChromium> > 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) {
+ GraphicsLayerChromium* curChild = static_cast<GraphicsLayerChromium*>(childLayers[i]);
+
+ LayerChromium* childLayer = curChild->layerForSuperlayer();
+ newSublayers.append(childLayer);
+ }
+
+ for (size_t 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 GraphicsLayerChromium::updateLayerPosition()
+{
+ // Position is offset on the layer by the layer anchor point.
+ FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(),
+ m_position.y() + m_anchorPoint.y() * m_size.height());
+
+ primaryLayer()->setPosition(layerPosition);
+}
+
+void GraphicsLayerChromium::updateLayerSize()
+{
+ IntSize layerSize(m_size.width(), m_size.height());
+ if (m_transformLayer) {
+ m_transformLayer->setBounds(layerSize);
+ // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
+ FloatPoint centerPoint(m_size.width() / 2, m_size.height() / 2);
+ m_layer->setPosition(centerPoint);
+ }
+
+ m_layer->setBounds(layerSize);
+
+ // 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 GraphicsLayerChromium::updateAnchorPoint()
+{
+ primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
+ primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
+ updateLayerPosition();
+}
+
+void GraphicsLayerChromium::updateTransform()
+{
+ primaryLayer()->setTransform(m_transform);
+}
+
+void GraphicsLayerChromium::updateChildrenTransform()
+{
+ primaryLayer()->setSublayerTransform(m_childrenTransform);
+}
+
+void GraphicsLayerChromium::updateMasksToBounds()
+{
+ m_layer->setMasksToBounds(m_masksToBounds);
+ updateDebugIndicators();
+}
+
+void GraphicsLayerChromium::updateContentsOpaque()
+{
+ m_layer->setOpaque(m_contentsOpaque);
+}
+
+void GraphicsLayerChromium::updateBackfaceVisibility()
+{
+ m_layer->setDoubleSided(m_backfaceVisibility);
+}
+
+void GraphicsLayerChromium::updateLayerPreserves3D()
+{
+ // FIXME: implement
+}
+
+void GraphicsLayerChromium::updateLayerDrawsContent()
+{
+ if (m_drawsContent)
+ m_layer->setNeedsDisplay();
+
+ updateDebugIndicators();
+}
+
+void GraphicsLayerChromium::updateLayerBackgroundColor()
+{
+ if (!m_contentsLayer)
+ return;
+
+ // We never create the contents layer just for background color yet.
+ if (m_backgroundColorSet)
+ setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor);
+ else
+ clearLayerBackgroundColor(*m_contentsLayer);
+}
+
+void GraphicsLayerChromium::updateContentsImage()
+{
+ // FIXME: Implement
+}
+
+void GraphicsLayerChromium::updateContentsVideo()
+{
+ // FIXME: Implement
+}
+
+void GraphicsLayerChromium::updateContentsRect()
+{
+ if (!m_contentsLayer)
+ return;
+
+ m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
+ m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
+}
+
+void GraphicsLayerChromium::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 GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer)
+{
+ if (contentsLayer == m_contentsLayer)
+ return;
+
+ if (m_contentsLayer) {
+ m_contentsLayer->removeFromSuperlayer();
+ m_contentsLayer = 0;
+ }
+
+ if (contentsLayer) {
+ m_contentsLayer = contentsLayer;
+
+ m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
+
+ // 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, Color(0, 0, 128, 180));
+ m_contentsLayer->setBorderWidth(1);
+ }
+ }
+ updateDebugIndicators();
+}
+
+// This function simply mimics the operation of GraphicsLayerCA
+void GraphicsLayerChromium::updateOpacityOnLayer()
+{
+ primaryLayer()->setOpacity(m_opacity);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
new file mode 100644
index 0000000..03a6d41
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2010 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 GraphicsLayerChromium_h
+#define GraphicsLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+
+namespace WebCore {
+
+class LayerChromium;
+
+class GraphicsLayerChromium : public GraphicsLayer {
+public:
+ GraphicsLayerChromium(GraphicsLayerClient*);
+ virtual ~GraphicsLayerChromium();
+
+ 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*, GraphicsLayer* sibling);
+ virtual void addChildBelow(GraphicsLayer*, 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 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);
+
+ 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();
+
+ LayerChromium* primaryLayer() const { return m_transformLayer.get() ? m_transformLayer.get() : m_layer.get(); }
+ LayerChromium* hostLayerForSublayers() const;
+ LayerChromium* layerForSuperlayer() 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(LayerChromium*);
+ LayerChromium* contentsLayer() const { return m_contentsLayer.get(); }
+
+ RefPtr<LayerChromium> m_layer;
+ RefPtr<LayerChromium> m_transformLayer;
+ RefPtr<LayerChromium> m_contentsLayer;
+
+ enum ContentsLayerPurpose {
+ NoContentsLayer = 0,
+ ContentsLayerForImage,
+ ContentsLayerForVideo
+ };
+
+ ContentsLayerPurpose m_contentsLayerPurpose;
+ bool m_contentsLayerHasBackgroundColor : 1;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
index 1386163..16f55e2 100644
--- a/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
+++ b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
@@ -46,12 +46,6 @@ Icon::~Icon()
{
}
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
-{
- notImplemented();
- return 0;
-}
-
void Icon::paint(GraphicsContext*, const IntRect&)
{
notImplemented();
diff --git a/WebCore/platform/graphics/chromium/IconChromiumMac.cpp b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
index 23ca698..a24afb2 100644
--- a/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
+++ b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
@@ -39,11 +39,6 @@
namespace WebCore {
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
-{
- return 0;
-}
-
Icon::~Icon()
{
}
diff --git a/WebCore/platform/graphics/chromium/IconChromiumWin.cpp b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
index b0145f8..e958d4a 100644
--- a/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
@@ -52,13 +52,6 @@ Icon::~Icon()
DestroyIcon(m_icon);
}
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
-{
- // FIXME: We can't access icons directly from renderer processes.
- // http://code.google.com/p/chromium/issues/detail?id=4092
- return 0;
-}
-
void Icon::paint(GraphicsContext* context, const IntRect& rect)
{
if (context->paintingDisabled())
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp
new file mode 100644
index 0000000..4540ac1
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2010 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 USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+
+#include "PlatformContextSkia.h"
+#include "RenderLayerBacking.h"
+#include "skia/ext/platform_canvas.h"
+
+namespace WebCore {
+
+using namespace std;
+
+PassRefPtr<LayerChromium> LayerChromium::create(LayerType type, GraphicsLayerChromium* owner)
+{
+ return adoptRef(new LayerChromium(type, owner));
+}
+
+LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner)
+ : m_needsDisplayOnBoundsChange(false)
+ , m_owner(owner)
+ , m_layerType(type)
+ , m_superlayer(0)
+ , m_borderWidth(0)
+ , m_borderColor(0, 0, 0, 0)
+ , m_backgroundColor(0, 0, 0, 0)
+ , m_anchorPointZ(0)
+ , m_clearsContext(false)
+ , m_doubleSided(false)
+ , m_edgeAntialiasingMask(0)
+ , m_hidden(false)
+ , m_masksToBounds(false)
+ , m_contentsGravity(Bottom)
+ , m_opacity(1.0)
+ , m_opaque(true)
+ , m_zPosition(0.0)
+ , m_canvas(0)
+ , m_skiaContext(0)
+ , m_graphicsContext(0)
+ , m_geometryFlipped(false)
+{
+ updateGraphicsContext(m_backingStoreRect);
+}
+
+LayerChromium::~LayerChromium()
+{
+ // 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());
+}
+
+void LayerChromium::updateGraphicsContext(const IntSize& size)
+{
+#if PLATFORM(SKIA)
+ // Create new canvas and context. OwnPtr takes care of freeing up
+ // the old ones.
+ m_canvas = new skia::PlatformCanvas(size.width(), size.height(), false);
+ m_skiaContext = new PlatformContextSkia(m_canvas.get());
+
+ // This is needed to get text to show up correctly. Without it,
+ // GDI renders with zero alpha and the text becomes invisible.
+ // Unfortunately, setting this to true disables cleartype.
+ m_skiaContext->setDrawingToImageBuffer(true);
+
+ m_graphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_skiaContext.get()));
+#else
+#error "Need to implement for your platform."
+#endif
+ // The backing store allocated for a layer can be smaller than the layer's bounds.
+ // This is mostly true for the root layer whose backing store is sized based on the visible
+ // portion of the layer rather than the actual page size.
+ m_backingStoreRect = size;
+}
+
+void LayerChromium::updateContents()
+{
+ RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
+
+ if (backing && !backing->paintingGoesToWindow())
+ m_owner->paintGraphicsLayerContents(*m_graphicsContext, IntRect(0, 0, m_bounds.width(), m_bounds.height()));
+}
+
+void LayerChromium::drawDebugBorder()
+{
+ m_graphicsContext->setStrokeColor(m_borderColor, DeviceColorSpace);
+ m_graphicsContext->setStrokeThickness(m_borderWidth);
+ m_graphicsContext->drawLine(IntPoint(0, 0), IntPoint(m_bounds.width(), 0));
+ m_graphicsContext->drawLine(IntPoint(0, 0), IntPoint(0, m_bounds.height()));
+ m_graphicsContext->drawLine(IntPoint(m_bounds.width(), 0), IntPoint(m_bounds.width(), m_bounds.height()));
+ m_graphicsContext->drawLine(IntPoint(0, m_bounds.height()), IntPoint(m_bounds.width(), m_bounds.height()));
+}
+
+void LayerChromium::setNeedsCommit()
+{
+ // Call notifySyncRequired(), which in this implementation plumbs through to
+ // call setRootLayerNeedsDisplay() on the WebView, which will cause LayerRendererSkia
+ // to render a frame.
+ if (m_owner)
+ m_owner->notifySyncRequired();
+}
+
+void LayerChromium::addSublayer(PassRefPtr<LayerChromium> sublayer)
+{
+ insertSublayer(sublayer, numSublayers());
+}
+
+void LayerChromium::insertSublayer(PassRefPtr<LayerChromium> sublayer, size_t index)
+{
+ index = min(index, m_sublayers.size());
+ m_sublayers.insert(index, sublayer);
+ sublayer->setSuperlayer(this);
+ setNeedsCommit();
+}
+
+void LayerChromium::removeFromSuperlayer()
+{
+ LayerChromium* superlayer = this->superlayer();
+ if (!superlayer)
+ return;
+
+ superlayer->removeSublayer(this);
+}
+
+void LayerChromium::removeSublayer(LayerChromium* sublayer)
+{
+ int foundIndex = indexOfSublayer(sublayer);
+ if (foundIndex == -1)
+ return;
+
+ m_sublayers.remove(foundIndex);
+ sublayer->setSuperlayer(0);
+ setNeedsCommit();
+}
+
+int LayerChromium::indexOfSublayer(const LayerChromium* reference)
+{
+ for (size_t i = 0; i < m_sublayers.size(); i++) {
+ if (m_sublayers[i] == reference)
+ return i;
+ }
+ return -1;
+}
+
+void LayerChromium::setBackingStoreRect(const IntSize& rect)
+{
+ if (m_backingStoreRect == rect)
+ return;
+
+ updateGraphicsContext(rect);
+}
+
+void LayerChromium::setBounds(const IntSize& rect)
+{
+ if (rect == m_bounds)
+ return;
+
+ m_bounds = rect;
+
+ // Re-create the canvas and associated contexts.
+ updateGraphicsContext(m_bounds);
+
+ // Layer contents need to be redrawn as the backing surface
+ // was recreated above.
+ updateContents();
+
+ setNeedsCommit();
+}
+
+void LayerChromium::setFrame(const FloatRect& rect)
+{
+ if (rect == m_frame)
+ return;
+
+ m_frame = rect;
+ setNeedsCommit();
+}
+
+const LayerChromium* LayerChromium::rootLayer() const
+{
+ const LayerChromium* layer = this;
+ for (LayerChromium* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
+ return layer;
+}
+
+void LayerChromium::removeAllSublayers()
+{
+ m_sublayers.clear();
+ setNeedsCommit();
+}
+
+void LayerChromium::setSublayers(const Vector<RefPtr<LayerChromium> >& sublayers)
+{
+ m_sublayers = sublayers;
+}
+
+void LayerChromium::setSuperlayer(LayerChromium* superlayer)
+{
+ m_superlayer = superlayer;
+}
+
+LayerChromium* LayerChromium::superlayer() const
+{
+ return m_superlayer;
+}
+
+void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect)
+{
+ // Redraw the contents of the layer.
+ updateContents();
+
+ setNeedsCommit();
+}
+
+void LayerChromium::setNeedsDisplay()
+{
+ // FIXME: implement
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h
new file mode 100644
index 0000000..55b1288
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2010 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 LayerChromium_h
+#define LayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatPoint.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayerChromium.h"
+#include "PlatformString.h"
+#include "StringHash.h"
+#include "TransformationMatrix.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+
+namespace skia {
+class PlatformCanvas;
+}
+
+namespace WebCore {
+
+class LayerChromium : public RefCounted<LayerChromium> {
+public:
+ enum LayerType { Layer, TransformLayer };
+ enum FilterType { Linear, Nearest, Trilinear, Lanczos };
+ enum ContentsGravityType { Center, Top, Bottom, Left, Right, TopLeft, TopRight,
+ BottomLeft, BottomRight, Resize, ResizeAspect, ResizeAspectFill };
+
+ static PassRefPtr<LayerChromium> create(LayerType, GraphicsLayerChromium* owner = 0);
+
+ ~LayerChromium();
+
+ void display(PlatformGraphicsContext*);
+
+ void addSublayer(PassRefPtr<LayerChromium>);
+ void insertSublayer(PassRefPtr<LayerChromium>, size_t index);
+ void removeFromSuperlayer();
+
+ void setAnchorPoint(const FloatPoint& anchorPoint) { m_anchorPoint = anchorPoint; setNeedsCommit(); }
+ FloatPoint anchorPoint() const { return m_anchorPoint; }
+
+ void setAnchorPointZ(float anchorPointZ) { m_anchorPointZ = anchorPointZ; setNeedsCommit(); }
+ float anchorPointZ() const { return m_anchorPointZ; }
+
+ void setBackgroundColor(const Color& color) { m_backgroundColor = color; setNeedsCommit(); }
+ Color backgroundColor() const { return m_backgroundColor; }
+
+ void setBorderColor(const Color& color) { m_borderColor = color; setNeedsCommit(); }
+ Color borderColor() const { return m_borderColor; }
+
+ void setBorderWidth(float width) { m_borderWidth = width; setNeedsCommit(); }
+ float borderWidth() const { return m_borderWidth; }
+
+ void setBounds(const IntSize&);
+ IntSize bounds() const { return m_bounds; }
+
+ void setClearsContext(bool clears) { m_clearsContext = clears; setNeedsCommit(); }
+ bool clearsContext() const { return m_clearsContext; }
+
+ void setContentsGravity(ContentsGravityType gravityType) { m_contentsGravity = gravityType; setNeedsCommit(); }
+ ContentsGravityType contentsGravity() const { return m_contentsGravity; }
+
+ void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; setNeedsCommit(); }
+ bool doubleSided() const { return m_doubleSided; }
+
+ void setEdgeAntialiasingMask(uint32_t mask) { m_edgeAntialiasingMask = mask; setNeedsCommit(); }
+ uint32_t edgeAntialiasingMask() const { return m_edgeAntialiasingMask; }
+
+ void setFrame(const FloatRect&);
+ FloatRect frame() const { return m_frame; }
+
+ void setHidden(bool hidden) { m_hidden = hidden; setNeedsCommit(); }
+ bool isHidden() const { return m_hidden; }
+
+ void setMasksToBounds(bool masksToBounds) { m_masksToBounds = masksToBounds; }
+ bool masksToBounds() const { return m_masksToBounds; }
+
+ void setName(const String& name) { m_name = name; }
+ String name() const { return m_name; }
+
+ void setNeedsDisplay(const FloatRect& dirtyRect);
+ void setNeedsDisplay();
+
+ void setNeedsDisplayOnBoundsChange(bool needsDisplay) { m_needsDisplayOnBoundsChange = needsDisplay; }
+
+ void setOpacity(float opacity) { m_opacity = opacity; setNeedsCommit(); }
+ float opacity() const { return m_opacity; }
+
+ void setOpaque(bool opaque) { m_opaque = opaque; setNeedsCommit(); }
+ bool opaque() const { return m_opaque; }
+
+ void setPosition(const FloatPoint& position) { m_position = position; setNeedsCommit(); }
+
+ FloatPoint position() const { return m_position; }
+
+ void setZPosition(float zPosition) { m_zPosition = zPosition; setNeedsCommit(); }
+ float zPosition() const { return m_zPosition; }
+
+ const LayerChromium* rootLayer() const;
+
+ void removeAllSublayers();
+
+ void setSublayers(const Vector<RefPtr<LayerChromium> >&);
+
+ const Vector<RefPtr<LayerChromium> >& getSublayers() const { return m_sublayers; }
+
+ void setSublayerTransform(const TransformationMatrix& transform) { m_sublayerTransform = transform; setNeedsCommit(); }
+ const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; }
+
+ void setSuperlayer(LayerChromium* superlayer);
+ LayerChromium* superlayer() const;
+
+
+ void setTransform(const TransformationMatrix& transform) { m_transform = transform; setNeedsCommit(); }
+ const TransformationMatrix& transform() const { return m_transform; }
+
+ void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); }
+ bool geometryFlipped() const { return m_geometryFlipped; }
+
+ void updateContents();
+
+ skia::PlatformCanvas* platformCanvas() { return m_canvas.get(); }
+ GraphicsContext* graphicsContext() { return m_graphicsContext.get(); }
+
+ void setBackingStoreRect(const IntSize&);
+
+ void drawDebugBorder();
+
+private:
+ LayerChromium(LayerType, GraphicsLayerChromium* owner);
+
+ void setNeedsCommit();
+
+ void paintMe();
+
+ size_t numSublayers() const
+ {
+ return m_sublayers.size();
+ }
+
+ // Returns the index of the sublayer or -1 if not found.
+ int indexOfSublayer(const LayerChromium*);
+
+ // This should only be called from removeFromSuperlayer.
+ void removeSublayer(LayerChromium*);
+
+ // Re-create the canvas and graphics context. This method
+ // must be called every time the layer is resized.
+ void updateGraphicsContext(const IntSize&);
+
+ Vector<RefPtr<LayerChromium> > m_sublayers;
+ LayerChromium* m_superlayer;
+
+ GraphicsLayerChromium* m_owner;
+ OwnPtr<skia::PlatformCanvas> m_canvas;
+ OwnPtr<PlatformContextSkia> m_skiaContext;
+ OwnPtr<GraphicsContext> m_graphicsContext;
+
+ LayerType m_layerType;
+
+ IntSize m_bounds;
+ IntSize m_backingStoreRect;
+ FloatPoint m_position;
+ FloatPoint m_anchorPoint;
+ Color m_backgroundColor;
+ Color m_borderColor;
+
+ FloatRect m_frame;
+ TransformationMatrix m_transform;
+ TransformationMatrix m_sublayerTransform;
+
+ uint32_t m_edgeAntialiasingMask;
+ float m_opacity;
+ float m_zPosition;
+ float m_anchorPointZ;
+ float m_borderWidth;
+
+ bool m_clearsContext;
+ bool m_doubleSided;
+ bool m_hidden;
+ bool m_masksToBounds;
+ bool m_opaque;
+ bool m_geometryFlipped;
+ bool m_needsDisplayOnBoundsChange;
+
+ ContentsGravityType m_contentsGravity;
+ String m_name;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
new file mode 100644
index 0000000..722c80c
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2010 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 USE(ACCELERATED_COMPOSITING)
+#include "LayerRendererChromium.h"
+
+#include "LayerChromium.h"
+#include "PlatformContextSkia.h"
+#include "skia/ext/platform_canvas.h"
+
+namespace WebCore {
+
+PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create()
+{
+ return new LayerRendererChromium();
+}
+
+LayerRendererChromium::LayerRendererChromium()
+ : m_rootLayer(0)
+ , m_needsDisplay(false)
+{
+}
+
+LayerRendererChromium::~LayerRendererChromium()
+{
+}
+
+void LayerRendererChromium::updateLayerContents()
+{
+ if (m_rootLayer)
+ updateLayerContentsRecursive(m_rootLayer.get());
+}
+
+#if PLATFORM(SKIA)
+void LayerRendererChromium::drawLayersInCanvas(skia::PlatformCanvas* canvas, const IntRect& clipRect)
+{
+ if (!m_rootLayer)
+ return;
+
+ canvas->save();
+ canvas->clipRect(SkRect(clipRect));
+
+ // First composite the root layer into the canvas.
+ canvas->drawBitmap(m_rootLayer->platformCanvas()->getDevice()->accessBitmap(false), 0, 0, 0);
+
+ // Account for the scroll offset before compositing the remaining layers.
+ // Note that the root layer's painting takes into account the scroll offset already.
+ canvas->translate(-m_scrollFrame.fLeft, -m_scrollFrame.fTop);
+
+ float opacity = 1.0f;
+ const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers();
+ for (size_t i = 0; i < sublayers.size(); i++)
+ drawLayerInCanvasRecursive(canvas, sublayers[i].get(), opacity);
+
+ canvas->restore();
+
+ m_needsDisplay = false;
+}
+
+void LayerRendererChromium::drawLayerInCanvasRecursive(skia::PlatformCanvas* canvas, LayerChromium* layer, float opacity)
+{
+ // Guarantees that the canvas is restored to a known state on destruction.
+ SkAutoCanvasRestore autoRestoreCanvas(canvas, true);
+
+ FloatPoint position = layer->position();
+ FloatPoint anchorPoint = layer->anchorPoint();
+ SkMatrix transform = layer->transform().toAffineTransform();
+ IntSize bounds = layer->bounds();
+
+ canvas->translate(position.x(), position.y());
+
+ SkScalar tx = SkScalarMul(anchorPoint.x(), bounds.width());
+ SkScalar ty = SkScalarMul(anchorPoint.y(), bounds.height());
+ canvas->translate(tx, ty);
+ canvas->concat(transform);
+ canvas->translate(-tx, -ty);
+
+ // The position we get is for the center of the layer, but
+ // drawBitmap starts at the upper-left corner, and therefore
+ // we need to adjust our transform.
+ canvas->translate(-0.5f * bounds.width(), -0.5f * bounds.height());
+
+ layer->drawDebugBorder();
+
+ SkPaint opacityPaint;
+ opacity *= layer->opacity();
+ opacityPaint.setAlpha(opacity * 255);
+
+ canvas->drawBitmap(layer->platformCanvas()->getDevice()->accessBitmap(false), 0, 0, &opacityPaint);
+
+ const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
+ for (size_t i = 0; i < sublayers.size(); i++)
+ drawLayerInCanvasRecursive(canvas, sublayers[i].get(), opacity);
+}
+#endif // PLATFORM(SKIA)
+
+void LayerRendererChromium::updateLayerContentsRecursive(LayerChromium* layer)
+{
+ layer->updateContents();
+
+ const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
+ for (size_t i = 0; i < sublayers.size(); i++)
+ updateLayerContentsRecursive(sublayers[i].get());
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
new file mode 100644
index 0000000..7eb429f
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 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 LayerRendererChromium_h
+#define LayerRendererChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "IntRect.h"
+#include "LayerChromium.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace skia {
+class PlatformCanvas;
+}
+
+namespace WebCore {
+
+class LayerRendererChromium : public Noncopyable {
+public:
+ static PassOwnPtr<LayerRendererChromium> create();
+
+ LayerRendererChromium();
+ ~LayerRendererChromium();
+
+#if PLATFORM(SKIA)
+ void drawLayersInCanvas(skia::PlatformCanvas*, const IntRect& clipRect);
+#endif
+ void updateLayerContents();
+
+ void setRootLayer(PassRefPtr<LayerChromium> layer) { m_rootLayer = layer; }
+ LayerChromium* rootLayer() { return m_rootLayer.get(); }
+
+ void setNeedsDisplay() { m_needsDisplay = true; }
+
+ void setScrollFrame(SkIRect& scrollFrame) { m_scrollFrame = scrollFrame; }
+
+private:
+#if PLATFORM(SKIA)
+ void drawLayerInCanvasRecursive(skia::PlatformCanvas*, LayerChromium*, float opacity);
+#endif
+ void updateLayerContentsRecursive(LayerChromium*);
+
+ RefPtr<LayerChromium> m_rootLayer;
+
+ bool m_needsDisplay;
+ SkIRect m_scrollFrame;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
index 3d68ea8..72bbfb4 100644
--- a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
@@ -151,7 +151,7 @@ void SimpleFontData::determinePitch()
ReleaseDC(0, dc);
}
-float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const
{
HDC dc = GetDC(0);
HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
@@ -170,7 +170,9 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
SelectObject(dc, oldFont);
ReleaseDC(0, dc);
- return static_cast<float>(width);
+ GlyphMetrics metrics;
+ metrics.horizontalAdvance = static_cast<float>(width);
+ return metrics;
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
index 3bff83f..8c639aa 100644
--- a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -172,7 +172,7 @@ void SimpleFontData::determinePitch()
m_treatAsFixedPitch = platformData().isFixedPitch();
}
-float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode /* metricsMode */) const
{
SkASSERT(sizeof(glyph) == 2); // compile-time assert
@@ -183,7 +183,12 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
SkScalar width = paint.measureText(&glyph, 2);
- return SkScalarToFloat(width);
+ // Though WebKit supports non-integral advances, Skia only supports them
+ // for "subpixel" (distinct from LCD subpixel antialiasing) text, which
+ // we don't use.
+ GlyphMetrics metrics;
+ metrics.horizontalAdvance = round(SkScalarToFloat(width));
+ return metrics;
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
index 10fcdf6..dda84a9 100644
--- a/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
+++ b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
@@ -398,7 +398,6 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext,
&shaping.m_advance[fromGlyph],
justify,
&shaping.m_offsets[fromGlyph]);
- ASSERT(S_OK == hr);
textOutOk = (hr == S_OK);
} else {
SkPoint origin;
diff --git a/WebCore/platform/graphics/efl/FloatRectEfl.cpp b/WebCore/platform/graphics/efl/FloatRectEfl.cpp
new file mode 100644
index 0000000..12f8d03
--- /dev/null
+++ b/WebCore/platform/graphics/efl/FloatRectEfl.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
+ * Copyright (C) 2009-2010 ProFUSION embedded systems
+ * Copyright (C) 2009-2010 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "FloatRect.h"
+
+namespace WebCore {
+
+FloatRect::FloatRect(const Eina_Rectangle& r)
+ : m_location(FloatPoint(r.x, r.y))
+ , m_size(r.w, r.h)
+{
+}
+
+FloatRect::operator Eina_Rectangle() const // NOLINT
+{
+ Eina_Rectangle r = {(int) round(x()), (int) round(y()), (int) round(width()), (int) round(height())};
+ return r;
+}
+
+}
+
diff --git a/WebCore/platform/graphics/efl/FontEfl.cpp b/WebCore/platform/graphics/efl/FontEfl.cpp
new file mode 100644
index 0000000..2aeb397
--- /dev/null
+++ b/WebCore/platform/graphics/efl/FontEfl.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
+ * Copyright (C) 2009-2010 ProFUSION embedded systems
+ * Copyright (C) 2009-2010 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Font.h"
+
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "SimpleFontData.h"
+
+#include <cairo.h>
+
+namespace WebCore {
+
+void Font::drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const
+{
+ notImplemented();
+}
+
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
+float Font::floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
+{
+ notImplemented();
+ return 0.0f;
+}
+
+int Font::offsetForPositionForComplexText(const TextRun&, int, bool) const
+{
+ notImplemented();
+ return 0;
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun&, const IntPoint&, int, int, int) const
+{
+ notImplemented();
+ return FloatRect();
+}
+
+}
diff --git a/WebCore/platform/graphics/win/FontDatabase.h b/WebCore/platform/graphics/efl/IconEfl.cpp
index 4f76c9e..6b3de04 100644
--- a/WebCore/platform/graphics/win/FontDatabase.h
+++ b/WebCore/platform/graphics/efl/IconEfl.cpp
@@ -1,5 +1,9 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
+ * Copyright (C) 2009-2010 ProFUSION embedded systems
+ * Copyright (C) 2009-2010 Samsung Electronics
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,13 +30,37 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef FontDatabase_h
-#define FontDatabase_h
+#include "config.h"
+
+#include "Icon.h"
+
+#include "GraphicsContext.h"
+#include "MIMETypeRegistry.h"
+#include "NotImplemented.h"
+#include "PassRefPtr.h"
+#include "PlatformString.h"
namespace WebCore {
- void populateFontDatabase();
+Icon::Icon()
+ : m_icon(0)
+{
+ notImplemented();
+}
+
+Icon::~Icon()
+{
+}
+
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
+{
+ notImplemented();
+ return 0;
+}
-} // namespace WebCore
+void Icon::paint(GraphicsContext* context, const IntRect& rect)
+{
+ notImplemented();
+}
-#endif // !defined(FontDatabase_h)
+}
diff --git a/WebCore/platform/graphics/efl/ImageEfl.cpp b/WebCore/platform/graphics/efl/ImageEfl.cpp
new file mode 100644
index 0000000..112770f
--- /dev/null
+++ b/WebCore/platform/graphics/efl/ImageEfl.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008 Kenneth Rohde Christiansen. All rights reserved.
+ * Copyright (C) 2009-2010 ProFUSION embedded systems
+ * Copyright (C) 2009-2010 Samsung Electronics
+ *
+ * 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 "SharedBuffer.h"
+
+#include <cairo.h>
+
+namespace WebCore {
+
+void BitmapImage::initPlatformData()
+{
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+}
+
+static PassRefPtr<SharedBuffer> loadResourceSharedBufferFallback()
+{
+ return SharedBuffer::create(); // TODO: fallback image?
+}
+
+static PassRefPtr<SharedBuffer> loadResourceSharedBuffer(const char* name)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(String::format(DATA_DIR "/webkit-1.0/images/%s.png", name));
+ if (buffer)
+ return buffer.release();
+ return loadResourceSharedBufferFallback();
+}
+
+PassRefPtr<Image> Image::loadPlatformResource(const char* name)
+{
+ RefPtr<BitmapImage> img = BitmapImage::create();
+ RefPtr<SharedBuffer> buffer = loadResourceSharedBuffer(name);
+ img->setData(buffer.release(), true);
+ return img.release();
+}
+
+}
diff --git a/WebCore/platform/graphics/efl/IntPointEfl.cpp b/WebCore/platform/graphics/efl/IntPointEfl.cpp
new file mode 100644
index 0000000..76a25e1
--- /dev/null
+++ b/WebCore/platform/graphics/efl/IntPointEfl.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
+ * Copyright (C) 2009-2010 ProFUSION embedded systems
+ * Copyright (C) 2009-2010 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "IntPoint.h"
+
+#include <Evas.h>
+
+namespace WebCore {
+
+IntPoint::IntPoint(const Evas_Point& p)
+ : m_x(p.x)
+ , m_y(p.y)
+{
+}
+
+IntPoint::operator Evas_Point() const // NOLINT
+{
+ Evas_Point p = { x(), y() };
+ return p;
+}
+
+}
diff --git a/WebCore/platform/graphics/efl/IntRectEfl.cpp b/WebCore/platform/graphics/efl/IntRectEfl.cpp
new file mode 100644
index 0000000..5ff8626
--- /dev/null
+++ b/WebCore/platform/graphics/efl/IntRectEfl.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
+ * Copyright (C) 2009-2010 ProFUSION embedded systems
+ * Copyright (C) 2009-2010 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "IntRect.h"
+
+namespace WebCore {
+
+IntRect::IntRect(const Eina_Rectangle& r)
+ : m_location(IntPoint(r.x, r.y))
+ , m_size(r.w, r.h)
+{
+}
+
+IntRect::operator Eina_Rectangle() const // NOLINT
+{
+ Eina_Rectangle r = { x(), y(), width(), height() };
+ return r;
+}
+
+}
+
diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp
index 567da74..567da74 100644
--- a/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp
diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h
index 3e88f63..3e88f63 100644
--- a/WebCore/platform/graphics/gtk/DataSourceGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h
diff --git a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp
new file mode 100644
index 0000000..1d14b5a
--- /dev/null
+++ b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "config.h"
+#include "GOwnPtrGStreamer.h"
+
+#if ENABLE(VIDEO)
+#include <gst/gstelement.h>
+
+namespace WTF {
+
+template <> void freeOwnedGPtr<GstElement>(GstElement* ptr)
+{
+ if (ptr)
+ gst_object_unref(ptr);
+}
+#endif
+
+}
diff --git a/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h
new file mode 100644
index 0000000..6655f38
--- /dev/null
+++ b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef GOwnPtrGStreamer_h
+#define GOwnPtrGStreamer_h
+
+#include "GOwnPtr.h"
+
+typedef struct _GstElement GstElement;
+
+namespace WTF {
+
+template<> void freeOwnedGPtr<GstElement>(GstElement* ptr);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h
new file mode 100644
index 0000000..2e97b4d
--- /dev/null
+++ b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ImageGStreamer_h
+#define ImageGStreamer_h
+
+#if ENABLE(VIDEO)
+
+#include "BitmapImage.h"
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <wtf/PassRefPtr.h>
+
+#if PLATFORM(CAIRO)
+#include <cairo.h>
+#endif
+
+namespace WebCore {
+class IntSize;
+
+class ImageGStreamer : public RefCounted<ImageGStreamer> {
+ public:
+ static PassRefPtr<ImageGStreamer> createImage(GstBuffer*);
+ ~ImageGStreamer();
+
+ PassRefPtr<BitmapImage> image()
+ {
+ ASSERT(m_image);
+ return m_image.get();
+ }
+
+ private:
+ RefPtr<BitmapImage> m_image;
+
+#if PLATFORM(CAIRO)
+ ImageGStreamer(GstBuffer*&, IntSize, cairo_format_t&);
+ cairo_surface_t* m_surface;
+#endif
+
+ };
+}
+
+#endif
+
+#endif
diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp
new file mode 100644
index 0000000..6f975a4
--- /dev/null
+++ b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "GOwnPtr.h"
+#include "ImageGStreamer.h"
+
+using namespace std;
+
+using namespace WebCore;
+
+PassRefPtr<ImageGStreamer> ImageGStreamer::createImage(GstBuffer* buffer)
+{
+ int width = 0, height = 0;
+ GstCaps* caps = gst_buffer_get_caps(buffer);
+ GstVideoFormat format;
+ if (!gst_video_format_parse_caps(caps, &format, &width, &height)) {
+ gst_caps_unref(caps);
+ return 0;
+ }
+
+ gst_caps_unref(caps);
+
+ cairo_format_t cairoFormat;
+ if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA)
+ cairoFormat = CAIRO_FORMAT_ARGB32;
+ else
+ cairoFormat = CAIRO_FORMAT_RGB24;
+
+ return adoptRef(new ImageGStreamer(buffer, IntSize(width, height), cairoFormat));
+}
+
+ImageGStreamer::ImageGStreamer(GstBuffer*& buffer, IntSize size, cairo_format_t& cairoFormat)
+ : m_image(0)
+ , m_surface(0)
+{
+ m_surface = cairo_image_surface_create_for_data(GST_BUFFER_DATA(buffer), cairoFormat,
+ size.width(), size.height(),
+ cairo_format_stride_for_width(cairoFormat, size.width()));
+ ASSERT(cairo_surface_status(m_surface) == CAIRO_STATUS_SUCCESS);
+ m_image = BitmapImage::create(m_surface);
+}
+
+ImageGStreamer::~ImageGStreamer()
+{
+ if (m_image)
+ m_image.clear();
+
+ m_image = 0;
+
+ if (m_surface && cairo_surface_get_reference_count(m_surface))
+ cairo_surface_destroy(m_surface);
+
+ m_surface = 0;
+}
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index e1c9fd2..0afb971 100644
--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -28,13 +28,15 @@
#include "MediaPlayerPrivateGStreamer.h"
-#include "CString.h"
+#include "ColorSpace.h"
#include "DataSourceGStreamer.h"
#include "Document.h"
#include "Frame.h"
#include "FrameView.h"
-#include "GOwnPtrGtk.h"
+#include "GOwnPtrGStreamer.h"
#include "GraphicsContext.h"
+#include "GraphicsTypes.h"
+#include "ImageGStreamer.h"
#include "IntRect.h"
#include "KURL.h"
#include "MIMETypeRegistry.h"
@@ -46,14 +48,15 @@
#include "VideoSinkGStreamer.h"
#include "WebKitWebSourceGStreamer.h"
#include "Widget.h"
+#include <wtf/text/CString.h>
+#include <GOwnPtr.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/gtk/GOwnPtr.h>
// GstPlayFlags flags from playbin2. It is the policy of GStreamer to
// not publicly expose element-specific enums. That's why this
@@ -90,9 +93,10 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo
GOwnPtr<GError> err;
GOwnPtr<gchar> debug;
MediaPlayer::NetworkState error;
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
+ MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
bool issueError = true;
bool attemptNextLocation = false;
+ GstElement* pipeline = mp->pipeline();
if (message->structure) {
const gchar* messageTypeName = gst_structure_get_name(message->structure);
@@ -137,7 +141,10 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo
mp->didEnd();
break;
case GST_MESSAGE_STATE_CHANGED:
- mp->updateStates();
+ // Ignore state changes from internal elements. They are
+ // forwarded to playbin2 anyway.
+ if (GST_MESSAGE_SRC(message) == reinterpret_cast<GstObject*>(pipeline))
+ mp->updateStates();
break;
case GST_MESSAGE_BUFFERING:
mp->processBufferingStats(message);
@@ -156,7 +163,7 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo
void mediaPlayerPrivateSourceChangedCallback(GObject *object, GParamSpec *pspec, gpointer data)
{
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
+ MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
GOwnPtr<GstElement> element;
g_object_get(mp->m_playBin, "source", &element.outPtr(), NULL);
@@ -173,37 +180,17 @@ void mediaPlayerPrivateSourceChangedCallback(GObject *object, GParamSpec *pspec,
void mediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
{
// This is called when playbin receives the notify::volume signal.
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
+ MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
mp->volumeChanged();
}
-gboolean notifyVolumeIdleCallback(gpointer data)
-{
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
- mp->volumeChangedCallback();
- return FALSE;
-}
-
void mediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
{
// This is called when playbin receives the notify::mute signal.
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
+ MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
mp->muteChanged();
}
-gboolean notifyMuteIdleCallback(gpointer data)
-{
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
- mp->muteChangedCallback();
- return FALSE;
-}
-
-gboolean bufferingTimeoutCallback(gpointer data)
-{
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
- return mp->queryBufferingStats();
-}
-
static float playbackPosition(GstElement* playbin)
{
@@ -232,19 +219,19 @@ static float playbackPosition(GstElement* playbin)
}
-void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivate* playerPrivate)
+void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivateGStreamer* playerPrivate)
{
g_return_if_fail(GST_IS_BUFFER(buffer));
gst_buffer_replace(&playerPrivate->m_buffer, buffer);
playerPrivate->repaint();
}
-MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player)
+MediaPlayerPrivateInterface* MediaPlayerPrivateGStreamer::create(MediaPlayer* player)
{
- return new MediaPlayerPrivate(player);
+ return new MediaPlayerPrivateGStreamer(player);
}
-void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar)
+void MediaPlayerPrivateGStreamer::registerMediaEngine(MediaEngineRegistrar registrar)
{
if (isAvailable())
registrar(create, getSupportedTypes, supportsType);
@@ -272,7 +259,7 @@ static bool doGstInit()
return gstInitialized;
}
-bool MediaPlayerPrivate::isAvailable()
+bool MediaPlayerPrivateGStreamer::isAvailable()
{
if (!doGstInit())
return false;
@@ -285,7 +272,7 @@ bool MediaPlayerPrivate::isAvailable()
return false;
}
-MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
+MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player)
: m_player(player)
, m_playBin(0)
, m_videoSink(0)
@@ -296,7 +283,6 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_endTime(numeric_limits<float>::infinity())
, m_networkState(MediaPlayer::Empty)
, m_readyState(MediaPlayer::HaveNothing)
- , m_startedPlaying(false)
, m_isStreaming(false)
, m_size(IntSize())
, m_buffer(0)
@@ -305,36 +291,26 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_resetPipeline(false)
, m_paused(true)
, m_seeking(false)
+ , m_buffering(false)
, m_playbackRate(1)
, m_errorOccured(false)
- , m_volumeIdleId(0)
, m_mediaDuration(0)
- , m_muteIdleId(0)
, m_startedBuffering(false)
- , m_fillTimeoutId(0)
+ , m_fillTimer(this, &MediaPlayerPrivateGStreamer::fillTimerFired)
, m_maxTimeLoaded(0)
- , m_fillStatus(0)
+ , m_bufferingPercentage(0)
+ , m_preload(MediaPlayer::Auto)
+ , m_delayingLoad(false)
+ , m_mediaDurationKnown(true)
{
if (doGstInit())
createGSTPlayBin();
}
-MediaPlayerPrivate::~MediaPlayerPrivate()
+MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer()
{
- if (m_fillTimeoutId) {
- g_source_remove(m_fillTimeoutId);
- m_fillTimeoutId = 0;
- }
-
- if (m_volumeIdleId) {
- g_source_remove(m_volumeIdleId);
- m_volumeIdleId = 0;
- }
-
- if (m_muteIdleId) {
- g_source_remove(m_muteIdleId);
- m_muteIdleId = 0;
- }
+ if (m_fillTimer.isActive())
+ m_fillTimer.stop();
if (m_buffer)
gst_buffer_unref(m_buffer);
@@ -366,9 +342,28 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
}
}
-void MediaPlayerPrivate::load(const String& url)
+void MediaPlayerPrivateGStreamer::load(const String& url)
{
+ g_object_set(m_playBin, "uri", url.utf8().data(), NULL);
+
LOG_VERBOSE(Media, "Load %s", url.utf8().data());
+
+ if (m_preload == MediaPlayer::None) {
+ LOG_VERBOSE(Media, "Delaying load.");
+ m_delayingLoad = true;
+ return;
+ }
+
+ commitLoad();
+}
+
+void MediaPlayerPrivateGStreamer::commitLoad()
+{
+ // GStreamer needs to have the pipeline set to a paused state to
+ // start providing anything useful.
+ gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+
+ LOG_VERBOSE(Media, "Committing load.");
if (m_networkState != MediaPlayer::Loading) {
m_networkState = MediaPlayer::Loading;
m_player->networkStateChanged();
@@ -377,12 +372,9 @@ void MediaPlayerPrivate::load(const String& url)
m_readyState = MediaPlayer::HaveNothing;
m_player->readyStateChanged();
}
-
- g_object_set(m_playBin, "uri", url.utf8().data(), NULL);
- pause();
}
-bool MediaPlayerPrivate::changePipelineState(GstState newState)
+bool MediaPlayerPrivateGStreamer::changePipelineState(GstState newState)
{
ASSERT(newState == GST_STATE_PLAYING || newState == GST_STATE_PAUSED);
@@ -401,19 +393,27 @@ bool MediaPlayerPrivate::changePipelineState(GstState newState)
return true;
}
-void MediaPlayerPrivate::play()
+void MediaPlayerPrivateGStreamer::prepareToPlay()
+{
+ if (m_delayingLoad) {
+ m_delayingLoad = false;
+ commitLoad();
+ }
+}
+
+void MediaPlayerPrivateGStreamer::play()
{
if (changePipelineState(GST_STATE_PLAYING))
LOG_VERBOSE(Media, "Play");
}
-void MediaPlayerPrivate::pause()
+void MediaPlayerPrivateGStreamer::pause()
{
if (changePipelineState(GST_STATE_PAUSED))
LOG_VERBOSE(Media, "Pause");
}
-float MediaPlayerPrivate::duration() const
+float MediaPlayerPrivateGStreamer::duration() const
{
if (!m_playBin)
return 0.0;
@@ -421,6 +421,10 @@ float MediaPlayerPrivate::duration() const
if (m_errorOccured)
return 0.0;
+ // Media duration query failed already, don't attempt new useless queries.
+ if (!m_mediaDurationKnown)
+ return numeric_limits<float>::infinity();
+
if (m_mediaDuration)
return m_mediaDuration;
@@ -438,7 +442,7 @@ float MediaPlayerPrivate::duration() const
// FIXME: handle 3.14.9.5 properly
}
-float MediaPlayerPrivate::currentTime() const
+float MediaPlayerPrivateGStreamer::currentTime() const
{
if (!m_playBin)
return 0;
@@ -453,7 +457,7 @@ float MediaPlayerPrivate::currentTime() const
}
-void MediaPlayerPrivate::seek(float time)
+void MediaPlayerPrivateGStreamer::seek(float time)
{
// Avoid useless seeking.
if (time == playbackPosition(m_playBin))
@@ -479,33 +483,33 @@ void MediaPlayerPrivate::seek(float time)
}
}
-void MediaPlayerPrivate::startEndPointTimerIfNeeded()
+void MediaPlayerPrivateGStreamer::startEndPointTimerIfNeeded()
{
notImplemented();
}
-void MediaPlayerPrivate::cancelSeek()
+void MediaPlayerPrivateGStreamer::cancelSeek()
{
notImplemented();
}
-void MediaPlayerPrivate::endPointTimerFired(Timer<MediaPlayerPrivate>*)
+void MediaPlayerPrivateGStreamer::endPointTimerFired(Timer<MediaPlayerPrivateGStreamer>*)
{
notImplemented();
}
-bool MediaPlayerPrivate::paused() const
+bool MediaPlayerPrivateGStreamer::paused() const
{
return m_paused;
}
-bool MediaPlayerPrivate::seeking() const
+bool MediaPlayerPrivateGStreamer::seeking() const
{
return m_seeking;
}
// Returns the size of the video
-IntSize MediaPlayerPrivate::naturalSize() const
+IntSize MediaPlayerPrivateGStreamer::naturalSize() const
{
if (!hasVideo())
return IntSize();
@@ -567,7 +571,7 @@ IntSize MediaPlayerPrivate::naturalSize() const
return IntSize(width, height);
}
-bool MediaPlayerPrivate::hasVideo() const
+bool MediaPlayerPrivateGStreamer::hasVideo() const
{
gint currentVideo = -1;
if (m_playBin)
@@ -575,7 +579,7 @@ bool MediaPlayerPrivate::hasVideo() const
return currentVideo > -1;
}
-bool MediaPlayerPrivate::hasAudio() const
+bool MediaPlayerPrivateGStreamer::hasAudio() const
{
gint currentAudio = -1;
if (m_playBin)
@@ -583,7 +587,7 @@ bool MediaPlayerPrivate::hasAudio() const
return currentAudio > -1;
}
-void MediaPlayerPrivate::setVolume(float volume)
+void MediaPlayerPrivateGStreamer::setVolume(float volume)
{
if (!m_playBin)
return;
@@ -591,21 +595,20 @@ void MediaPlayerPrivate::setVolume(float volume)
g_object_set(m_playBin, "volume", static_cast<double>(volume), NULL);
}
-void MediaPlayerPrivate::volumeChangedCallback()
+void MediaPlayerPrivateGStreamer::volumeChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*)
{
double volume;
g_object_get(m_playBin, "volume", &volume, NULL);
m_player->volumeChanged(static_cast<float>(volume));
}
-void MediaPlayerPrivate::volumeChanged()
+void MediaPlayerPrivateGStreamer::volumeChanged()
{
- if (m_volumeIdleId)
- g_source_remove(m_volumeIdleId);
- m_volumeIdleId = g_idle_add((GSourceFunc) notifyVolumeIdleCallback, this);
+ Timer<MediaPlayerPrivateGStreamer> volumeChangedTimer(this, &MediaPlayerPrivateGStreamer::volumeChangedTimerFired);
+ volumeChangedTimer.startOneShot(0);
}
-void MediaPlayerPrivate::setRate(float rate)
+void MediaPlayerPrivateGStreamer::setRate(float rate)
{
// Avoid useless playback rate update.
if (m_playbackRate == rate)
@@ -658,17 +661,17 @@ void MediaPlayerPrivate::setRate(float rate)
g_object_set(m_playBin, "mute", mute, NULL);
}
-MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const
+MediaPlayer::NetworkState MediaPlayerPrivateGStreamer::networkState() const
{
return m_networkState;
}
-MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const
+MediaPlayer::ReadyState MediaPlayerPrivateGStreamer::readyState() const
{
return m_readyState;
}
-PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivateGStreamer::buffered() const
{
RefPtr<TimeRanges> timeRanges = TimeRanges::create();
float loaded = maxTimeLoaded();
@@ -677,44 +680,56 @@ PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
return timeRanges.release();
}
-void MediaPlayerPrivate::processBufferingStats(GstMessage* message)
+void MediaPlayerPrivateGStreamer::processBufferingStats(GstMessage* message)
{
- GstBufferingMode mode;
+ // This is the immediate buffering that needs to happen so we have
+ // enough to play right now.
+ m_buffering = true;
+ const GstStructure *structure = gst_message_get_structure(message);
+ gst_structure_get_int(structure, "buffer-percent", &m_bufferingPercentage);
+
+ LOG_VERBOSE(Media, "[Buffering] Buffering: %d%%.", m_bufferingPercentage);
+ GstBufferingMode mode;
gst_message_parse_buffering_stats(message, &mode, 0, 0, 0);
- if (mode != GST_BUFFERING_DOWNLOAD)
+ if (mode != GST_BUFFERING_DOWNLOAD) {
+ updateStates();
return;
+ }
+ // This is on-disk buffering, that allows us to download much more
+ // than needed for right now.
if (!m_startedBuffering) {
+ LOG_VERBOSE(Media, "[Buffering] Starting on-disk buffering.");
+
m_startedBuffering = true;
- if (m_fillTimeoutId > 0)
- g_source_remove(m_fillTimeoutId);
+ if (m_fillTimer.isActive())
+ m_fillTimer.stop();
- m_fillTimeoutId = g_timeout_add(200, (GSourceFunc) bufferingTimeoutCallback, this);
+ m_fillTimer.startRepeating(0.2);
}
}
-bool MediaPlayerPrivate::queryBufferingStats()
+void MediaPlayerPrivateGStreamer::fillTimerFired(Timer<MediaPlayerPrivateGStreamer>*)
{
GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT);
if (!gst_element_query(m_playBin, query)) {
gst_query_unref(query);
- return TRUE;
+ return;
}
gint64 start, stop;
+ gdouble fillStatus = 100.0;
gst_query_parse_buffering_range(query, 0, &start, &stop, 0);
gst_query_unref(query);
if (stop != -1)
- m_fillStatus = 100.0 * stop / GST_FORMAT_PERCENT_MAX;
- else
- m_fillStatus = 100.0;
+ fillStatus = 100.0 * stop / GST_FORMAT_PERCENT_MAX;
- LOG_VERBOSE(Media, "Download buffer filled up to %f%%", m_fillStatus);
+ LOG_VERBOSE(Media, "[Buffering] Download buffer filled up to %f%%", fillStatus);
if (!m_mediaDuration)
durationChanged();
@@ -722,25 +737,27 @@ bool MediaPlayerPrivate::queryBufferingStats()
// Update maxTimeLoaded only if the media duration is
// available. Otherwise we can't compute it.
if (m_mediaDuration) {
- m_maxTimeLoaded = static_cast<float>((m_fillStatus * m_mediaDuration) / 100.0);
- LOG_VERBOSE(Media, "Updated maxTimeLoaded: %f", m_maxTimeLoaded);
+ if (fillStatus == 100.0)
+ m_maxTimeLoaded = m_mediaDuration;
+ else
+ m_maxTimeLoaded = static_cast<float>((fillStatus * m_mediaDuration) / 100.0);
+ LOG_VERBOSE(Media, "[Buffering] Updated maxTimeLoaded: %f", m_maxTimeLoaded);
}
- if (m_fillStatus != 100.0) {
+ if (fillStatus != 100.0) {
updateStates();
- return TRUE;
+ return;
}
// Media is now fully loaded. It will play even if network
// connection is cut. Buffering is done, remove the fill source
// from the main loop.
- m_fillTimeoutId = 0;
+ m_fillTimer.stop();
m_startedBuffering = false;
updateStates();
- return FALSE;
}
-float MediaPlayerPrivate::maxTimeSeekable() const
+float MediaPlayerPrivateGStreamer::maxTimeSeekable() const
{
if (m_errorOccured)
return 0.0;
@@ -753,19 +770,19 @@ float MediaPlayerPrivate::maxTimeSeekable() const
return maxTimeLoaded();
}
-float MediaPlayerPrivate::maxTimeLoaded() const
+float MediaPlayerPrivateGStreamer::maxTimeLoaded() const
{
if (m_errorOccured)
return 0.0;
float loaded = m_maxTimeLoaded;
- if (!loaded && !m_fillTimeoutId)
+ if (!loaded && !m_fillTimer.isActive())
loaded = duration();
LOG_VERBOSE(Media, "maxTimeLoaded: %f", loaded);
return loaded;
}
-unsigned MediaPlayerPrivate::bytesLoaded() const
+unsigned MediaPlayerPrivateGStreamer::bytesLoaded() const
{
if (!m_playBin)
return 0;
@@ -778,7 +795,7 @@ unsigned MediaPlayerPrivate::bytesLoaded() const
return loaded;
}
-unsigned MediaPlayerPrivate::totalBytes() const
+unsigned MediaPlayerPrivateGStreamer::totalBytes() const
{
if (!m_source)
return 0;
@@ -794,7 +811,7 @@ unsigned MediaPlayerPrivate::totalBytes() const
return length;
}
-void MediaPlayerPrivate::cancelLoad()
+void MediaPlayerPrivateGStreamer::cancelLoad()
{
if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded)
return;
@@ -803,12 +820,8 @@ void MediaPlayerPrivate::cancelLoad()
gst_element_set_state(m_playBin, GST_STATE_NULL);
}
-void MediaPlayerPrivate::updateStates()
+void MediaPlayerPrivateGStreamer::updateStates()
{
- // There is no (known) way to get such level of information about
- // 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;
@@ -832,44 +845,66 @@ void MediaPlayerPrivate::updateStates()
m_resetPipeline = state <= GST_STATE_READY;
- if (state == GST_STATE_READY)
+ // Try to figure out ready and network states.
+ if (state == GST_STATE_READY) {
m_readyState = MediaPlayer::HaveNothing;
- else if (state == GST_STATE_PAUSED)
+ m_networkState = MediaPlayer::Empty;
+ } else if (maxTimeLoaded() == duration()) {
+ m_networkState = MediaPlayer::Loaded;
m_readyState = MediaPlayer::HaveEnoughData;
+ } else {
+ m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::HaveFutureData : MediaPlayer::HaveCurrentData;
+ m_networkState = MediaPlayer::Loading;
+ }
- if (state == GST_STATE_PLAYING) {
+ if (m_buffering && state != GST_STATE_READY) {
+ m_readyState = MediaPlayer::HaveCurrentData;
+ m_networkState = MediaPlayer::Loading;
+ }
+
+ // Now let's try to get the states in more detail using
+ // information from GStreamer, while we sync states where
+ // needed.
+ if (state == GST_STATE_PAUSED) {
+ if (m_buffering && m_bufferingPercentage == 100) {
+ m_buffering = false;
+ m_bufferingPercentage = 0;
+ m_readyState = MediaPlayer::HaveEnoughData;
+
+ LOG_VERBOSE(Media, "[Buffering] Complete.");
+
+ if (!m_paused) {
+ LOG_VERBOSE(Media, "[Buffering] Restarting playback.");
+ gst_element_set_state(m_playBin, GST_STATE_PLAYING);
+ }
+ } else if (!m_buffering && (currentTime() < duration())) {
+ m_paused = true;
+ }
+ } else if (state == GST_STATE_PLAYING) {
m_readyState = MediaPlayer::HaveEnoughData;
m_paused = false;
- m_startedPlaying = true;
+
if (!m_mediaDuration) {
float newDuration = duration();
- if (!isinf(newDuration))
+ m_mediaDurationKnown = !isinf(newDuration);
+ if (m_mediaDurationKnown)
m_mediaDuration = newDuration;
}
+
+ if (m_buffering) {
+ m_readyState = MediaPlayer::HaveCurrentData;
+ m_networkState = MediaPlayer::Loading;
+
+ LOG_VERBOSE(Media, "[Buffering] Pausing stream for buffering.");
+
+ gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ }
} else
m_paused = true;
// Is on-disk buffering in progress?
- if (m_fillTimeoutId) {
+ if (m_fillTimer.isActive())
m_networkState = MediaPlayer::Loading;
- // Buffering has just started, we should now have enough
- // data to restart playback if it was internally paused by
- // GStreamer.
- if (m_paused && !m_startedPlaying)
- gst_element_set_state(m_playBin, GST_STATE_PLAYING);
- }
-
- if (maxTimeLoaded() == duration()) {
- m_networkState = MediaPlayer::Loaded;
- if (state == GST_STATE_READY)
- m_readyState = MediaPlayer::HaveNothing;
- else if (state == GST_STATE_PAUSED)
- m_readyState = MediaPlayer::HaveEnoughData;
- } else
- if (state == GST_STATE_READY)
- m_readyState = MediaPlayer::HaveNothing;
- else if (m_paused)
- m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::HaveFutureData : MediaPlayer::HaveCurrentData;
if (m_changingRate) {
m_player->rateChanged();
@@ -917,20 +952,16 @@ void MediaPlayerPrivate::updateStates()
m_paused = true;
// Live pipelines go in PAUSED without prerolling.
m_isStreaming = true;
- } else if (state == GST_STATE_PLAYING) {
- m_startedPlaying = true;
+ } else if (state == GST_STATE_PLAYING)
m_paused = false;
- }
-
- if (m_paused && !m_startedPlaying)
- gst_element_set_state(m_playBin, GST_STATE_PLAYING);
if (m_seeking) {
shouldUpdateAfterSeek = true;
m_seeking = false;
- if (m_paused)
+ if (!m_paused)
gst_element_set_state(m_playBin, GST_STATE_PLAYING);
- }
+ } else if (!m_paused)
+ gst_element_set_state(m_playBin, GST_STATE_PLAYING);
m_networkState = MediaPlayer::Loading;
break;
@@ -957,7 +988,7 @@ void MediaPlayerPrivate::updateStates()
}
}
-void MediaPlayerPrivate::mediaLocationChanged(GstMessage* message)
+void MediaPlayerPrivateGStreamer::mediaLocationChanged(GstMessage* message)
{
if (m_mediaLocations)
gst_structure_free(m_mediaLocations);
@@ -970,13 +1001,13 @@ void MediaPlayerPrivate::mediaLocationChanged(GstMessage* message)
const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations");
if (locations)
- m_mediaLocationCurrentIndex = gst_value_list_get_size(locations) -1;
+ m_mediaLocationCurrentIndex = static_cast<int>(gst_value_list_get_size(locations)) -1;
loadNextLocation();
}
}
-bool MediaPlayerPrivate::loadNextLocation()
+bool MediaPlayerPrivateGStreamer::loadNextLocation()
{
if (!m_mediaLocations)
return false;
@@ -1056,23 +1087,23 @@ bool MediaPlayerPrivate::loadNextLocation()
}
-void MediaPlayerPrivate::loadStateChanged()
+void MediaPlayerPrivateGStreamer::loadStateChanged()
{
updateStates();
}
-void MediaPlayerPrivate::sizeChanged()
+void MediaPlayerPrivateGStreamer::sizeChanged()
{
notImplemented();
}
-void MediaPlayerPrivate::timeChanged()
+void MediaPlayerPrivateGStreamer::timeChanged()
{
updateStates();
m_player->timeChanged();
}
-void MediaPlayerPrivate::didEnd()
+void MediaPlayerPrivateGStreamer::didEnd()
{
// EOS was reached but in case of reverse playback the position is
// not always 0. So to not confuse the HTMLMediaElement we
@@ -1088,25 +1119,40 @@ void MediaPlayerPrivate::didEnd()
timeChanged();
}
-void MediaPlayerPrivate::durationChanged()
+void MediaPlayerPrivateGStreamer::durationChanged()
{
// Reset cached media duration
m_mediaDuration = 0;
// And re-cache it if possible.
+ GstState state;
+ gst_element_get_state(m_playBin, &state, 0, 0);
float newDuration = duration();
+
+ if (state <= GST_STATE_READY) {
+ // Don't set m_mediaDurationKnown yet if the pipeline is not
+ // paused. This allows duration() query to fail at least once
+ // before playback starts and duration becomes known.
+ if (!isinf(newDuration))
+ m_mediaDuration = newDuration;
+ } else {
+ m_mediaDurationKnown = !isinf(newDuration);
+ if (m_mediaDurationKnown)
+ m_mediaDuration = newDuration;
+ }
+
if (!isinf(newDuration))
m_mediaDuration = newDuration;
m_player->durationChanged();
}
-bool MediaPlayerPrivate::supportsMuting() const
+bool MediaPlayerPrivateGStreamer::supportsMuting() const
{
return true;
}
-void MediaPlayerPrivate::setMuted(bool muted)
+void MediaPlayerPrivateGStreamer::setMuted(bool muted)
{
if (!m_playBin)
return;
@@ -1114,22 +1160,20 @@ void MediaPlayerPrivate::setMuted(bool muted)
g_object_set(m_playBin, "mute", muted, NULL);
}
-void MediaPlayerPrivate::muteChangedCallback()
+void MediaPlayerPrivateGStreamer::muteChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*)
{
gboolean muted;
g_object_get(m_playBin, "mute", &muted, NULL);
m_player->muteChanged(static_cast<bool>(muted));
}
-void MediaPlayerPrivate::muteChanged()
+void MediaPlayerPrivateGStreamer::muteChanged()
{
- if (m_muteIdleId)
- g_source_remove(m_muteIdleId);
-
- m_muteIdleId = g_idle_add((GSourceFunc) notifyMuteIdleCallback, this);
+ Timer<MediaPlayerPrivateGStreamer> muteChangedTimer(this, &MediaPlayerPrivateGStreamer::muteChangedTimerFired);
+ muteChangedTimer.startOneShot(0);
}
-void MediaPlayerPrivate::loadingFailed(MediaPlayer::NetworkState error)
+void MediaPlayerPrivateGStreamer::loadingFailed(MediaPlayer::NetworkState error)
{
m_errorOccured = true;
if (m_networkState != error) {
@@ -1142,21 +1186,21 @@ void MediaPlayerPrivate::loadingFailed(MediaPlayer::NetworkState error)
}
}
-void MediaPlayerPrivate::setSize(const IntSize& size)
+void MediaPlayerPrivateGStreamer::setSize(const IntSize& size)
{
m_size = size;
}
-void MediaPlayerPrivate::setVisible(bool visible)
+void MediaPlayerPrivateGStreamer::setVisible(bool visible)
{
}
-void MediaPlayerPrivate::repaint()
+void MediaPlayerPrivateGStreamer::repaint()
{
m_player->repaint();
}
-void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
+void MediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect& rect)
{
if (context->paintingDisabled())
return;
@@ -1166,42 +1210,12 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
if (!m_buffer)
return;
- 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);
-
- // translate and scale the context to correct size
- cairo_translate(cr, rect.x(), rect.y());
- 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);
+ RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer);
+ if (!gstImage)
+ return;
- cairo_surface_destroy(src);
- gst_caps_unref(caps);
+ context->drawImage(reinterpret_cast<Image*>(gstImage->image().get()), sRGBColorSpace,
+ rect, CompositeCopy, false);
}
static HashSet<String> mimeTypeCache()
@@ -1209,7 +1223,7 @@ static HashSet<String> mimeTypeCache()
doGstInit();
- static HashSet<String> cache;
+ DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
static bool typeListInitialized = false;
if (!typeListInitialized) {
@@ -1307,12 +1321,12 @@ static HashSet<String> mimeTypeCache()
return cache;
}
-void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
+void MediaPlayerPrivateGStreamer::getSupportedTypes(HashSet<String>& types)
{
types = mimeTypeCache();
}
-MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
+MediaPlayer::SupportsType MediaPlayerPrivateGStreamer::supportsType(const String& type, const String& codecs)
{
if (type.isNull() || type.isEmpty())
return MediaPlayer::IsNotSupported;
@@ -1323,29 +1337,36 @@ MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, c
return MediaPlayer::IsNotSupported;
}
-bool MediaPlayerPrivate::hasSingleSecurityOrigin() const
+bool MediaPlayerPrivateGStreamer::hasSingleSecurityOrigin() const
{
return true;
}
-bool MediaPlayerPrivate::supportsFullscreen() const
+bool MediaPlayerPrivateGStreamer::supportsFullscreen() const
{
return true;
}
-void MediaPlayerPrivate::setAutobuffer(bool autoBuffer)
+void MediaPlayerPrivateGStreamer::setPreload(MediaPlayer::Preload preload)
{
ASSERT(m_playBin);
+ m_preload = preload;
+
GstPlayFlags flags;
g_object_get(m_playBin, "flags", &flags, NULL);
- if (autoBuffer)
- g_object_set(m_playBin, "flags", flags | GST_PLAY_FLAG_DOWNLOAD, NULL);
- else
+ if (preload == MediaPlayer::None)
g_object_set(m_playBin, "flags", flags & ~GST_PLAY_FLAG_DOWNLOAD, NULL);
+ else
+ g_object_set(m_playBin, "flags", flags | GST_PLAY_FLAG_DOWNLOAD, NULL);
+
+ if (m_delayingLoad && m_preload != MediaPlayer::None) {
+ m_delayingLoad = false;
+ commitLoad();
+ }
}
-void MediaPlayerPrivate::createGSTPlayBin()
+void MediaPlayerPrivateGStreamer::createGSTPlayBin()
{
ASSERT(!m_playBin);
m_playBin = gst_element_factory_make("playbin2", "play");
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
index e19b686..06519fa 100644
--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
@@ -28,7 +28,6 @@
#include "MediaPlayerPrivate.h"
#include "Timer.h"
-#include <cairo.h>
#include <glib.h>
#include <gst/gst.h>
@@ -47,25 +46,27 @@ class String;
gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
void mediaPlayerPrivateVolumeChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
+void mediaPlayerPrivateMuteChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
-class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
+class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
friend gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
- friend void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer* buffer, MediaPlayerPrivate* playerPrivate);
+ friend void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer* buffer, MediaPlayerPrivateGStreamer* playerPrivate);
friend void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
public:
static void registerMediaEngine(MediaEngineRegistrar);
- ~MediaPlayerPrivate();
IntSize naturalSize() const;
bool hasVideo() const;
bool hasAudio() const;
void load(const String &url);
+ void commitLoad();
void cancelLoad();
bool loadNextLocation();
+ void prepareToPlay();
void play();
void pause();
@@ -80,15 +81,15 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
void setVolume(float);
void volumeChanged();
- void volumeChangedCallback();
+ void volumeChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
bool supportsMuting() const;
void setMuted(bool);
void muteChanged();
- void muteChangedCallback();
+ void muteChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
- void setAutobuffer(bool);
- bool queryBufferingStats();
+ void setPreload(MediaPlayer::Preload);
+ void fillTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
MediaPlayer::NetworkState networkState() const;
MediaPlayer::ReadyState readyState() const;
@@ -116,10 +117,13 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
bool supportsFullscreen() const;
+ GstElement* pipeline() const { return m_playBin; }
bool pipelineReset() const { return m_resetPipeline; }
private:
- MediaPlayerPrivate(MediaPlayer*);
+ MediaPlayerPrivateGStreamer(MediaPlayer*);
+ ~MediaPlayerPrivateGStreamer();
+
static MediaPlayerPrivateInterface* create(MediaPlayer* player);
static void getSupportedTypes(HashSet<String>&);
@@ -128,7 +132,7 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
void updateStates();
void cancelSeek();
- void endPointTimerFired(Timer<MediaPlayerPrivate>*);
+ void endPointTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
float maxTimeLoaded() const;
void startEndPointTimerIfNeeded();
@@ -149,24 +153,25 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
bool m_isEndReached;
MediaPlayer::NetworkState m_networkState;
MediaPlayer::ReadyState m_readyState;
- bool m_startedPlaying;
mutable bool m_isStreaming;
IntSize m_size;
GstBuffer* m_buffer;
GstStructure* m_mediaLocations;
- gint m_mediaLocationCurrentIndex;
+ int m_mediaLocationCurrentIndex;
bool m_resetPipeline;
bool m_paused;
bool m_seeking;
+ bool m_buffering;
float m_playbackRate;
bool m_errorOccured;
- guint m_volumeIdleId;
gfloat m_mediaDuration;
- guint m_muteIdleId;
bool m_startedBuffering;
- guint m_fillTimeoutId;
+ Timer<MediaPlayerPrivateGStreamer> m_fillTimer;
float m_maxTimeLoaded;
- gdouble m_fillStatus;
+ int m_bufferingPercentage;
+ MediaPlayer::Preload m_preload;
+ bool m_delayingLoad;
+ bool m_mediaDurationKnown;
};
}
diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp
index 5e0f8e2..dd8c3ee 100644
--- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp
@@ -213,8 +213,10 @@ webkit_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer)
buffer = priv->buffer = newBuffer;
}
- // Use HIGH_IDLE+20 priority, like Gtk+ for redrawing operations.
- priv->timeout_id = g_timeout_add_full(G_PRIORITY_HIGH_IDLE + 20, 0,
+ // This should likely use a lower priority, but glib currently starves
+ // lower priority sources.
+ // See: https://bugzilla.gnome.org/show_bug.cgi?id=610830.
+ priv->timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT, 0,
webkit_video_sink_timeout_func,
gst_object_ref(sink),
(GDestroyNotify)gst_object_unref);
diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h
index 7ea7d91..7ea7d91 100644
--- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h
diff --git a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
index 74a7852..daee506 100644
--- a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
@@ -19,7 +19,6 @@
#include "config.h"
#include "WebKitWebSourceGStreamer.h"
-#include "CString.h"
#include "Document.h"
#include "GOwnPtr.h"
#include "GRefPtr.h"
@@ -29,6 +28,7 @@
#include "ResourceHandleInternal.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
+#include <wtf/text/CString.h>
#include <gst/app/gstappsrc.h>
#include <gst/pbutils/missing-plugins.h>
@@ -255,6 +255,7 @@ static void webkit_web_src_init(WebKitWebSrc* src,
// already if the queue is 20% empty, it's much more
// likely that libsoup already provides new data before
// the queue is really empty.
+ // This might need tweaking for ports not using libsoup.
if (priv->haveAppSrc27)
g_object_set(priv->appsrc, "min-percent", 20, NULL);
@@ -414,7 +415,7 @@ static bool webKitWebSrcStart(WebKitWebSrc* src)
// Needed to use DLNA streaming servers
request.setHTTPHeaderField("transferMode.dlna", "Streaming");
- priv->resourceHandle = ResourceHandle::create(request, priv->client, 0, false, false, false);
+ priv->resourceHandle = ResourceHandle::create(request, priv->client, 0, false, false);
if (!priv->resourceHandle) {
GST_ERROR_OBJECT(src, "Failed to create ResourceHandle");
return false;
@@ -505,17 +506,14 @@ static gboolean webKitWebSrcSetUri(GstURIHandler* handler, const gchar* uri)
if (!uri)
return TRUE;
- SoupURI* soupUri = soup_uri_new(uri);
+ KURL url(KURL(), uri);
- if (!soupUri || !SOUP_URI_VALID_FOR_HTTP(soupUri)) {
+ if (!url.isValid() || !url.protocolInHTTPFamily()) {
GST_ERROR_OBJECT(src, "Invalid URI '%s'", uri);
- soup_uri_free(soupUri);
return FALSE;
}
- priv->uri = soup_uri_to_string(soupUri, FALSE);
- soup_uri_free(soupUri);
-
+ priv->uri = g_strdup(url.string().utf8().data());
return TRUE;
}
@@ -535,9 +533,13 @@ static gboolean webKitWebSrcNeedDataMainCb(WebKitWebSrc* src)
{
WebKitWebSrcPrivate* priv = src->priv;
+#if USE(NETWORK_SOUP)
ResourceHandleInternal* d = priv->resourceHandle->getInternal();
if (d->m_msg)
soup_session_unpause_message(ResourceHandle::defaultSession(), d->m_msg);
+#endif
+ // Ports not using libsoup need to call the unpause/schedule API of their
+ // underlying network implementation here.
priv->paused = FALSE;
priv->needDataID = 0;
@@ -553,16 +555,20 @@ static void webKitWebSrcNeedDataCb(GstAppSrc* appsrc, guint length, gpointer use
if (priv->needDataID || !priv->paused)
return;
- priv->needDataID = g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc) webKitWebSrcNeedDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref);
+ priv->needDataID = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, (GSourceFunc) webKitWebSrcNeedDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref);
}
static gboolean webKitWebSrcEnoughDataMainCb(WebKitWebSrc* src)
{
WebKitWebSrcPrivate* priv = src->priv;
+#if USE(NETWORK_SOUP)
ResourceHandleInternal* d = priv->resourceHandle->getInternal();
soup_session_pause_message(ResourceHandle::defaultSession(), d->m_msg);
-
+#endif
+ // Ports not using libsoup need to call the pause/unschedule API of their
+ // underlying network implementation here.
+
priv->paused = TRUE;
priv->enoughDataID = 0;
return FALSE;
@@ -577,7 +583,7 @@ static void webKitWebSrcEnoughDataCb(GstAppSrc* appsrc, gpointer userData)
if (priv->enoughDataID || priv->paused)
return;
- priv->enoughDataID = g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc) webKitWebSrcEnoughDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref);
+ priv->enoughDataID = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, (GSourceFunc) webKitWebSrcEnoughDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref);
}
static gboolean webKitWebSrcSeekMainCb(WebKitWebSrc* src)
@@ -606,7 +612,7 @@ static gboolean webKitWebSrcSeekDataCb(GstAppSrc* appsrc, guint64 offset, gpoint
priv->requestedOffset = offset;
if (priv->seekID)
g_source_remove(priv->seekID);
- priv->seekID = g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc) webKitWebSrcSeekMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref);
+ priv->seekID = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, (GSourceFunc) webKitWebSrcSeekMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref);
return TRUE;
}
diff --git a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h
index ae19640..ae19640 100644
--- a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h
diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp
index 5c320e0..29b83dc 100644
--- a/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -288,7 +288,7 @@ static PangoLayout* getDefaultPangoLayout(const TextRun& run)
return layout;
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow*) const
{
if (run.length() == 0)
return 0.0f;
diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp b/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp
index 8a1a5f1..59cd3da 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp
+++ b/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp
@@ -25,9 +25,9 @@
#include "config.h"
#include "FontPlatformData.h"
-#include "CString.h"
#include "PlatformString.h"
#include "FontDescription.h"
+#include <wtf/text/CString.h>
#include <cairo.h>
#include <assert.h>
@@ -137,7 +137,7 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool italic)
{
}
-FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, int size, bool bold, bool italic)
+FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic)
: m_context(0)
, m_font(0)
, m_size(size)
diff --git a/WebCore/platform/graphics/gtk/IconGtk.cpp b/WebCore/platform/graphics/gtk/IconGtk.cpp
index 71b897e..d56b52d 100644
--- a/WebCore/platform/graphics/gtk/IconGtk.cpp
+++ b/WebCore/platform/graphics/gtk/IconGtk.cpp
@@ -30,10 +30,10 @@
#include "config.h"
#include "Icon.h"
-#include "CString.h"
#include "GraphicsContext.h"
#include "MIMETypeRegistry.h"
#include "PassRefPtr.h"
+#include <wtf/text/CString.h>
#include <gtk/gtk.h>
diff --git a/WebCore/platform/graphics/gtk/ImageGtk.cpp b/WebCore/platform/graphics/gtk/ImageGtk.cpp
index c62d988..daa70ef 100644
--- a/WebCore/platform/graphics/gtk/ImageGtk.cpp
+++ b/WebCore/platform/graphics/gtk/ImageGtk.cpp
@@ -26,12 +26,72 @@
#include "config.h"
#include "BitmapImage.h"
-#include "CString.h"
#include "GOwnPtr.h"
-
+#include "SharedBuffer.h"
+#include <wtf/text/CString.h>
#include <cairo.h>
#include <gtk/gtk.h>
+#ifdef _WIN32
+# include <mbstring.h>
+# include <shlobj.h>
+/* search for data relative to where we are installed */
+
+static HMODULE hmodule;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+BOOL WINAPI
+DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ hmodule = hinstDLL;
+ break;
+ }
+
+ return TRUE;
+}
+#ifdef __cplusplus
+}
+#endif
+
+static char *
+get_webkit_datadir(void)
+{
+ static char retval[1000];
+ static int beenhere = 0;
+
+ unsigned char *p;
+
+ if (beenhere)
+ return retval;
+
+ if (!GetModuleFileName (hmodule, (CHAR *) retval, sizeof(retval) - 10))
+ return DATA_DIR;
+
+ p = _mbsrchr((const unsigned char *) retval, '\\');
+ *p = '\0';
+ p = _mbsrchr((const unsigned char *) retval, '\\');
+ if (p) {
+ if (!stricmp((const char *) (p+1), "bin"))
+ *p = '\0';
+ }
+ strcat(retval, "\\share");
+
+ beenhere = 1;
+
+ return retval;
+}
+
+#undef DATA_DIR
+#define DATA_DIR get_webkit_datadir ()
+#endif
+
+
namespace WTF {
template <> void freeOwnedGPtr<GtkIconInfo>(GtkIconInfo* info)
@@ -96,8 +156,13 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name)
CString fileName;
if (!strcmp("missingImage", name))
fileName = getThemeIconFileName(GTK_STOCK_MISSING_IMAGE, 16);
- if (fileName.isNull())
- fileName = String::format("%s/webkit-1.0/images/%s.png", DATA_DIR, name).utf8();
+ if (fileName.isNull()) {
+ gchar* imagename = g_strdup_printf("%s.png", name);
+ gchar* glibFileName = g_build_filename(DATA_DIR, "webkit-1.0", "images", imagename, 0);
+ fileName = glibFileName;
+ g_free(imagename);
+ g_free(glibFileName);
+ }
return loadImageFromFile(fileName);
}
@@ -107,12 +172,12 @@ PassRefPtr<Image> Image::loadPlatformThemeIcon(const char* name, int size)
return loadImageFromFile(getThemeIconFileName(name, size));
}
-static inline unsigned char* getCairoSurfacePixel(unsigned char* data, uint x, uint y, uint rowStride)
+static inline unsigned char* getCairoSurfacePixel(unsigned char* data, unsigned x, unsigned y, unsigned rowStride)
{
return data + (y * rowStride) + x * 4;
}
-static inline guchar* getGdkPixbufPixel(guchar* data, uint x, uint y, uint rowStride)
+static inline guchar* getGdkPixbufPixel(guchar* data, unsigned x, unsigned y, unsigned rowStride)
{
return data + (y * rowStride) + x * 4;
}
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
index 975143e..0ed5393 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
@@ -119,7 +119,7 @@ void SimpleFontData::determinePitch()
m_treatAsFixedPitch = m_platformData.isFixedPitch();
}
-float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const
{
ASSERT(m_platformData.m_scaledFont);
@@ -130,7 +130,10 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
float w = (float)m_spaceWidth;
if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0)
w = (float)extents.x_advance;
- return w;
+
+ GlyphMetrics metrics;
+ metrics.horizontalAdvance = w;
+ return metrics;
}
}
diff --git a/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp
index 7ade370..f8c2aa0 100644
--- a/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
* Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved.
*
@@ -37,7 +38,7 @@
#include "FontPlatformData.h"
#include "NotImplemented.h"
#include <String.h>
-
+#include <interface/Font.h>
namespace WebCore {
@@ -59,10 +60,11 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
SimpleFontData* 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 getCachedFontData(fontDescription, defaultString);
+ font_family family;
+ font_style style;
+ be_plain_font->GetFamilyAndStyle(&family, &style);
+ AtomicString plainFontFamily(family);
+ return getCachedFontData(fontDescription, plainFontFamily);
}
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
diff --git a/WebCore/platform/graphics/haiku/FontHaiku.cpp b/WebCore/platform/graphics/haiku/FontHaiku.cpp
index 48744d9..d4622cb 100644
--- a/WebCore/platform/graphics/haiku/FontHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/FontHaiku.cpp
@@ -94,7 +94,7 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
notImplemented();
return 0;
diff --git a/WebCore/platform/graphics/haiku/GradientHaiku.cpp b/WebCore/platform/graphics/haiku/GradientHaiku.cpp
index 469a17f..fdc4690 100644
--- a/WebCore/platform/graphics/haiku/GradientHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/GradientHaiku.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2008 Kevin Ollivier <kevino@theolliviers.com> All rights reserved.
* Copyright (C) 2009 Maxime Simon <simon.maxime@theolliviers.com>
+ * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,26 +28,45 @@
#include "config.h"
#include "Gradient.h"
-#include "CSSParser.h"
-#include "NotImplemented.h"
+#include "GraphicsContext.h"
+#include <GradientLinear.h>
+#include <GradientRadial.h>
+#include <View.h>
namespace WebCore {
void Gradient::platformDestroy()
{
- notImplemented();
+ delete m_gradient;
}
PlatformGradient Gradient::platformGradient()
{
- notImplemented();
- return 0;
+ if (m_gradient)
+ return m_gradient;
+
+ if (m_radial) {
+ // TODO: Support m_r0?
+ m_gradient = new BGradientRadial(m_p0, m_r1);
+ } else
+ m_gradient = new BGradientLinear(m_p0, m_p1);
+ size_t size = m_stops.size();
+ for (size_t i = 0; i < size; i++) {
+ const ColorStop& stop = m_stops[i];
+ rgb_color color;
+ color.red = static_cast<uint8>(stop.red * 255);
+ color.green = static_cast<uint8>(stop.green * 255);
+ color.blue = static_cast<uint8>(stop.blue * 255);
+ color.alpha = static_cast<uint8>(stop.alpha * 255);
+ m_gradient->AddColor(color, stop.stop);
+ }
+ return m_gradient;
}
-void Gradient::fill(GraphicsContext*, const FloatRect&)
+void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
{
- notImplemented();
+ context->platformContext()->FillRect(rect, *platformGradient());
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
index 7ab3a40..8db512c 100644
--- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
@@ -29,13 +29,13 @@
#include "GraphicsContext.h"
#include "AffineTransform.h"
-#include "CString.h"
#include "Color.h"
#include "Font.h"
#include "FontData.h"
#include "NotImplemented.h"
#include "Path.h"
#include "Pen.h"
+#include <wtf/text/CString.h>
#include <GraphicsDefs.h>
#include <Region.h>
#include <View.h>
diff --git a/WebCore/platform/graphics/haiku/ImageHaiku.cpp b/WebCore/platform/graphics/haiku/ImageHaiku.cpp
index 976154c..5a55d7c 100644
--- a/WebCore/platform/graphics/haiku/ImageHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/ImageHaiku.cpp
@@ -39,6 +39,7 @@
#include "ImageObserver.h"
#include "NotImplemented.h"
#include "PlatformString.h"
+#include "SharedBuffer.h"
#include "TransformationMatrix.h"
#include <Application.h>
#include <Bitmap.h>
@@ -120,7 +121,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
imageObserver()->didDraw(this);
}
-void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& srcPoint, ColorSpace, CompositeOperator op, const FloatRect& dstRect)
+void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& dstRect)
{
BBitmap* image = nativeImageForCurrentFrame();
if (!image || !image->IsValid()) // If the image hasn't fully loaded.
diff --git a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
index adb7573..f429ab5 100644
--- a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
@@ -93,7 +93,7 @@ void SimpleFontData::determinePitch()
m_treatAsFixedPitch = m_platformData.font() && m_platformData.font()->IsFixed();
}
-float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const
{
if (!m_platformData.font())
return 0;
@@ -103,7 +103,9 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
charUnicodeToUTF8HACK(glyph, charArray);
m_platformData.font()->GetEscapements(charArray, 1, escapements);
- return escapements[0] * m_platformData.font()->Size();
+ GlyphMetrics metrics;
+ metrics.horizontalAdvance = escapements[0] * m_platformData.font()->Size();
+ return metrics;
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/haiku/StillImageHaiku.cpp b/WebCore/platform/graphics/haiku/StillImageHaiku.cpp
new file mode 100644
index 0000000..7f9fb15
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/StillImageHaiku.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
+ *
+ * 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 "StillImageHaiku.h"
+
+#include "GraphicsContext.h"
+#include "IntSize.h"
+#include <View.h>
+
+namespace WebCore {
+
+StillImage::StillImage(const BBitmap& bitmap)
+ : m_bitmap(&bitmap)
+{
+}
+
+void StillImage::destroyDecodedData(bool destroyAll)
+{
+ // This is used for "large" animations to free image data.
+ // It appears it would not apply to StillImage.
+}
+
+unsigned StillImage::decodedSize() const
+{
+ // FIXME: It could be wise to return 0 here, since we don't want WebCore
+ // to think we eat up memory, since we are not freeing any in
+ // destroyDecodedData() either.
+ return m_bitmap.BitsLength();
+}
+
+IntSize StillImage::size() const
+{
+ return IntSize(m_bitmap.Bounds().IntegerWidth() + 1, m_bitmap.Bounds().IntegerHeight() + 1);
+}
+
+NativeImagePtr StillImage::nativeImageForCurrentFrame()
+{
+ return &m_bitmap;
+}
+
+void StillImage::draw(GraphicsContext* context, const FloatRect& destRect,
+ const FloatRect& sourceRect, ColorSpace, CompositeOperator op)
+{
+ if (!m_bitmap.IsValid())
+ return;
+
+ context->save();
+ context->setCompositeOperation(op);
+ context->platformContext()->DrawBitmap(&m_bitmap, sourceRect, destRect);
+ context->restore();
+}
+
+}
diff --git a/WebCore/platform/graphics/haiku/StillImageHaiku.h b/WebCore/platform/graphics/haiku/StillImageHaiku.h
new file mode 100644
index 0000000..f4bcbe1
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/StillImageHaiku.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
+ *
+ * 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 StillImageHaiku_h
+#define StillImageHaiku_h
+
+#include "Image.h"
+#include <Bitmap.h>
+
+namespace WebCore {
+
+class StillImage : public Image {
+public:
+ static PassRefPtr<StillImage> create(const BBitmap& bitmap)
+ {
+ return adoptRef(new StillImage(bitmap));
+ }
+
+ virtual void destroyDecodedData(bool destroyAll = true);
+ virtual unsigned decodedSize() const;
+
+ virtual IntSize size() const;
+ virtual NativeImagePtr nativeImageForCurrentFrame();
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
+
+private:
+ StillImage(const BBitmap&);
+
+ BBitmap m_bitmap;
+};
+
+} // namespace WebCore
+
+#endif // StillImageHaiku_h
diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.h b/WebCore/platform/graphics/mac/Canvas3DLayer.h
index 122ef39..4609010 100644
--- a/WebCore/platform/graphics/mac/Canvas3DLayer.h
+++ b/WebCore/platform/graphics/mac/Canvas3DLayer.h
@@ -32,16 +32,18 @@
namespace WebCore {
class GraphicsLayer;
+ class GraphicsContext3D;
}
@interface Canvas3DLayer : CAOpenGLLayer
{
WebCore::GraphicsLayer* m_layerOwner;
+ WebCore::GraphicsContext3D* m_context;
CGLContextObj m_contextObj;
GLuint m_texture;
}
-- (id)initWithContext:(CGLContextObj)context texture:(GLuint)texture;
+- (id)initWithContext:(WebCore::GraphicsContext3D*)context;
- (CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace;
diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.mm b/WebCore/platform/graphics/mac/Canvas3DLayer.mm
index 59a7384..22a0a10 100644
--- a/WebCore/platform/graphics/mac/Canvas3DLayer.mm
+++ b/WebCore/platform/graphics/mac/Canvas3DLayer.mm
@@ -41,10 +41,11 @@ using namespace WebCore;
@implementation Canvas3DLayer
--(id)initWithContext:(CGLContextObj)context texture:(GLuint)texture
+-(id)initWithContext:(GraphicsContext3D*)context
{
- m_contextObj = context;
- m_texture = texture;
+ m_context = context;
+ m_contextObj = static_cast<CGLContextObj>(context->platformGraphicsContext3D());
+ m_texture = static_cast<GLuint>(context->platformTexture());
self = [super init];
return self;
}
@@ -70,8 +71,8 @@ using namespace WebCore;
-(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
{
- CGLSetCurrentContext(m_contextObj);
- glFinish();
+ m_context->prepareTexture();
+
CGLSetCurrentContext(glContext);
CGRect frame = [self frame];
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp
index 543d885..b501293 100644
--- a/WebCore/platform/graphics/mac/ComplexTextController.cpp
+++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -68,6 +68,10 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
, m_characterInCurrentGlyph(0)
, m_finalRoundingWidth(0)
, m_fallbackFonts(fallbackFonts)
+ , m_minGlyphBoundingBoxX(numeric_limits<float>::max())
+ , m_maxGlyphBoundingBoxX(numeric_limits<float>::min())
+ , m_minGlyphBoundingBoxY(numeric_limits<float>::max())
+ , m_maxGlyphBoundingBoxY(numeric_limits<float>::min())
, m_lastRoundingGlyph(0)
{
m_padding = m_run.padding();
@@ -394,7 +398,12 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
// 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 (glyphStartOffset == glyphEndOffset) {
+ // When there are multiple glyphs per character we need to advance by the full width of the glyph.
+ ASSERT(m_characterInCurrentGlyph == oldCharacterInCurrentGlyph);
+ m_runWidthSoFar += adjustedAdvance.width;
+ } else
+ m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset);
if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter)
return;
@@ -433,6 +442,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
CGFloat roundedSpaceWidth = roundCGFloat(fontData->spaceWidth());
bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();
bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled();
+ CGPoint glyphOrigin = CGPointZero;
CFIndex lastCharacterIndex = m_run.ltr() ? numeric_limits<CFIndex>::min() : numeric_limits<CFIndex>::max();
bool isMonotonic = true;
@@ -536,6 +546,16 @@ void ComplexTextController::adjustGlyphsAndAdvances()
advance.height *= -1;
m_adjustedAdvances.append(advance);
m_adjustedGlyphs.append(glyph);
+
+ GlyphMetrics glyphMetrics = fontData->metricsForGlyph(glyph);
+ glyphMetrics.boundingBox.move(glyphOrigin.x, glyphOrigin.y);
+ m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphMetrics.boundingBox.x());
+ m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphMetrics.boundingBox.right());
+ m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphMetrics.boundingBox.y());
+ m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphMetrics.boundingBox.bottom());
+ glyphOrigin.x += advance.width;
+ glyphOrigin.y += advance.height;
+
lastCharacterIndex = characterIndex;
}
if (!isMonotonic)
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h
index 53e8f7a..280327f 100644
--- a/WebCore/platform/graphics/mac/ComplexTextController.h
+++ b/WebCore/platform/graphics/mac/ComplexTextController.h
@@ -62,6 +62,11 @@ public:
// Extra width to the left of the leftmost glyph.
float finalRoundingWidth() const { return m_finalRoundingWidth; }
+ float minGlyphBoundingBoxX() const { return m_minGlyphBoundingBoxX; }
+ float maxGlyphBoundingBoxX() const { return m_maxGlyphBoundingBoxX; }
+ float minGlyphBoundingBoxY() const { return m_minGlyphBoundingBoxY; }
+ float maxGlyphBoundingBoxY() const { return m_maxGlyphBoundingBoxY; }
+
private:
class ComplexTextRun : public RefCounted<ComplexTextRun> {
public:
@@ -173,6 +178,11 @@ private:
HashSet<const SimpleFontData*>* m_fallbackFonts;
+ float m_minGlyphBoundingBoxX;
+ float m_maxGlyphBoundingBoxX;
+ float m_minGlyphBoundingBoxY;
+ float m_maxGlyphBoundingBoxY;
+
unsigned m_lastRoundingGlyph;
};
diff --git a/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
index 0db2601..b7ed0e9 100644
--- a/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
+++ b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
@@ -33,6 +33,8 @@
#include "SimpleFontData.h"
#include <wtf/MathExtras.h>
+using namespace std;
+
namespace WebCore {
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h,
@@ -83,9 +85,15 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
drawGlyphBuffer(context, glyphBuffer, run, startPoint);
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
ComplexTextController controller(this, run, true, fallbackFonts);
+ if (glyphOverflow) {
+ glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - ascent());
+ glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - descent());
+ glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX()));
+ glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth()));
+ }
return controller.totalWidth();
}
diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm
index bb9561e..87057fa 100644
--- a/WebCore/platform/graphics/mac/FontMac.mm
+++ b/WebCore/platform/graphics/mac/FontMac.mm
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -47,6 +47,28 @@ bool Font::canReturnFallbackFontsForComplexText()
return true;
}
+static void showGlyphsWithAdvances(const FontPlatformData& font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
+{
+ if (!font.isColorBitmapFont())
+ CGContextShowGlyphsWithAdvances(context, glyphs, advances, count);
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ else {
+ if (!count)
+ return;
+
+ Vector<CGPoint, 256> positions(count);
+ CGAffineTransform matrix = CGAffineTransformInvert(CGContextGetTextMatrix(context));
+ positions[0] = CGPointZero;
+ for (size_t i = 1; i < count; ++i) {
+ CGSize advance = CGSizeApplyAffineTransform(advances[i - 1], matrix);
+ positions[i].x = positions[i - 1].x + advance.width;
+ positions[i].y = positions[i - 1].y + advance.height;
+ }
+ CTFontDrawGlyphs(toCTFontRef(font.font()), glyphs, positions.data(), count, context);
+ }
+#endif
+}
+
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
CGContextRef cgContext = context->platformContext();
@@ -98,7 +120,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
CGContextSetFont(cgContext, platformData.cgFont());
CGAffineTransform matrix = CGAffineTransformIdentity;
- if (drawFont)
+ if (drawFont && !platformData.isColorBitmapFont())
memcpy(&matrix, [drawFont matrix], sizeof(matrix));
matrix.b = -matrix.b;
matrix.d = -matrix.d;
@@ -112,13 +134,14 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
} else
CGContextSetFontSize(cgContext, platformData.m_size);
+
IntSize shadowSize;
int shadowBlur;
Color shadowColor;
ColorSpace fillColorSpace = context->fillColorSpace();
context->getShadow(shadowSize, shadowBlur, shadowColor);
- bool hasSimpleShadow = context->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur;
+ bool hasSimpleShadow = context->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont();
if (hasSimpleShadow) {
// Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
context->clearShadow();
@@ -126,19 +149,19 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
context->setFillColor(shadowFillColor, fillColorSpace);
CGContextSetTextPosition(cgContext, point.x() + shadowSize.width(), point.y() + shadowSize.height());
- CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
+ showGlyphsWithAdvances(platformData, 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);
+ showGlyphsWithAdvances(platformData, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
context->setFillColor(fillColor, fillColorSpace);
}
CGContextSetTextPosition(cgContext, point.x(), point.y());
- CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
+ showGlyphsWithAdvances(platformData, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
if (font->syntheticBoldOffset()) {
CGContextSetTextPosition(cgContext, point.x() + font->syntheticBoldOffset(), point.y());
- CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
+ showGlyphsWithAdvances(platformData, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
if (hasSimpleShadow)
diff --git a/WebCore/platform/graphics/mac/FontPlatformData.h b/WebCore/platform/graphics/mac/FontPlatformData.h
index faf5f2e..23016e7 100644
--- a/WebCore/platform/graphics/mac/FontPlatformData.h
+++ b/WebCore/platform/graphics/mac/FontPlatformData.h
@@ -61,6 +61,7 @@ struct FontPlatformData {
#ifdef BUILDING_ON_TIGER
, m_cgFont(0)
#endif
+ , m_isColorBitmapFont(false)
{
}
@@ -73,6 +74,7 @@ struct FontPlatformData {
, m_size(size)
, m_font(0)
, m_cgFont(cgFont)
+ , m_isColorBitmapFont(false)
{
}
@@ -113,6 +115,7 @@ struct FontPlatformData {
bool roundsGlyphAdvances() const;
bool allowsLigatures() const;
+ bool isColorBitmapFont() const { return m_isColorBitmapFont; }
#ifndef BUILDING_ON_TIGER
CGFontRef cgFont() const { return m_cgFont.get(); }
@@ -133,6 +136,8 @@ private:
#else
CGFontRef m_cgFont; // It is not necessary to refcount this, since either an NSFont owns it or some CachedFont has it referenced.
#endif
+
+ bool m_isColorBitmapFont;
};
}
diff --git a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
index 0118c8b..53b0282 100644
--- a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
+++ b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
@@ -1,7 +1,7 @@
/*
* This file is part of the internal font implementation.
*
- * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -33,6 +33,11 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool synt
: m_syntheticBold(syntheticBold)
, m_syntheticOblique(syntheticOblique)
, m_font(nsFont)
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ , m_isColorBitmapFont(CTFontGetSymbolicTraits(toCTFontRef(nsFont)) & kCTFontColorGlyphsTrait)
+#else
+ , m_isColorBitmapFont(false)
+#endif
{
if (nsFont)
CFRetain(nsFont);
@@ -54,6 +59,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& f)
m_size = f.m_size;
m_cgFont = f.m_cgFont;
m_atsuFontID = f.m_atsuFontID;
+ m_isColorBitmapFont = f.m_isColorBitmapFont;
}
FontPlatformData:: ~FontPlatformData()
@@ -76,6 +82,7 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f)
if (m_font && m_font != reinterpret_cast<NSFont *>(-1))
CFRelease(m_font);
m_font = f.m_font;
+ m_isColorBitmapFont = f.m_isColorBitmapFont;
return *this;
}
@@ -96,6 +103,9 @@ void FontPlatformData::setFont(NSFont *font)
m_cgFont = wkGetCGFontFromNSFont(font);
m_atsuFontID = wkGetNSFontATSUFontId(font);
#endif
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(font)) & kCTFontColorGlyphsTrait;
+#endif
}
bool FontPlatformData::roundsGlyphAdvances() const
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
index 096cdbd..82c314e 100644
--- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
@@ -30,14 +30,13 @@
#include "GraphicsContext3D.h"
#include "CanvasObject.h"
-#include "CString.h"
#include "ImageBuffer.h"
#include "NotImplemented.h"
#include "WebGLActiveInfo.h"
#include "WebGLArray.h"
#include "WebGLBuffer.h"
-#include "WebGLFramebuffer.h"
#include "WebGLFloatArray.h"
+#include "WebGLFramebuffer.h"
#include "WebGLIntArray.h"
#include "WebGLProgram.h"
#include "WebGLRenderbuffer.h"
@@ -46,7 +45,9 @@
#include "WebGLUnsignedByteArray.h"
#include <CoreGraphics/CGBitmapContext.h>
#include <OpenGL/CGLRenderers.h>
+#include <OpenGL/gl.h>
#include <wtf/UnusedParam.h>
+#include <wtf/text/CString.h>
namespace WebCore {
@@ -75,28 +76,26 @@ static void setPixelFormat(Vector<CGLPixelFormatAttribute>& attribs, int colorBi
attribs.append(static_cast<CGLPixelFormatAttribute>(0));
}
-PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs)
+PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow)
{
- OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs));
+ OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs, hostWindow));
return context->m_contextObj ? context.release() : 0;
}
-GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs)
- : m_attrs(attrs)
+GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow)
+ : m_currentWidth(0)
+ , m_currentHeight(0)
+ , m_attrs(attrs)
, m_contextObj(0)
, m_texture(0)
, m_fbo(0)
- , m_depthBuffer(0)
-{
- // FIXME: we need to take into account the user's requested
- // context creation attributes, in particular stencil and
- // antialias, and determine which could and could not be honored
- // based on the capabilities of the OpenGL implementation.
- m_attrs.alpha = true;
- m_attrs.depth = true;
- m_attrs.stencil = false;
- m_attrs.antialias = false;
- m_attrs.premultipliedAlpha = true;
+ , m_depthStencilBuffer(0)
+ , m_boundFBO(0)
+ , m_multisampleFBO(0)
+ , m_multisampleDepthStencilBuffer(0)
+ , m_multisampleColorBuffer(0)
+{
+ UNUSED_PARAM(hostWindow);
Vector<CGLPixelFormatAttribute> attribs;
CGLPixelFormatObj pixelFormatObj = 0;
@@ -145,6 +144,8 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs)
// Set the current context to the one given to us.
CGLSetCurrentContext(m_contextObj);
+ validateAttributes();
+
// create a texture to render into
::glGenTextures(1, &m_texture);
::glBindTexture(GL_TEXTURE_2D, m_texture);
@@ -152,21 +153,27 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs)
::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);
+ m_boundFBO = m_fbo;
+ if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth))
+ ::glGenRenderbuffersEXT(1, &m_depthStencilBuffer);
+
+ // create an multisample FBO
+ if (m_attrs.antialias) {
+ ::glGenFramebuffersEXT(1, &m_multisampleFBO);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
+ m_boundFBO = m_multisampleFBO;
+ ::glGenRenderbuffersEXT(1, &m_multisampleColorBuffer);
+ if (m_attrs.stencil || m_attrs.depth)
+ ::glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer);
+ }
+ ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
::glClearColor(0, 0, 0, 0);
}
@@ -174,14 +181,46 @@ GraphicsContext3D::~GraphicsContext3D()
{
if (m_contextObj) {
CGLSetCurrentContext(m_contextObj);
- ::glDeleteRenderbuffersEXT(1, & m_depthBuffer);
::glDeleteTextures(1, &m_texture);
+ if (m_attrs.antialias) {
+ ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer);
+ if (m_attrs.stencil || m_attrs.depth)
+ ::glDeleteRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer);
+ ::glDeleteFramebuffersEXT(1, &m_multisampleFBO);
+ } else {
+ if (m_attrs.stencil || m_attrs.depth)
+ ::glDeleteRenderbuffersEXT(1, &m_depthStencilBuffer);
+ }
::glDeleteFramebuffersEXT(1, &m_fbo);
CGLSetCurrentContext(0);
CGLDestroyContext(m_contextObj);
}
}
+void GraphicsContext3D::validateAttributes()
+{
+ const char* extensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS));
+ if (m_attrs.stencil) {
+ if (std::strstr(extensions, "GL_EXT_packed_depth_stencil")) {
+ if (!m_attrs.depth)
+ m_attrs.depth = true;
+ } else
+ m_attrs.stencil = false;
+ }
+ if (m_attrs.antialias) {
+ bool isValidVendor = true;
+ // Currently in Mac we only turn on antialias if vendor is NVIDIA.
+ const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR));
+ if (!std::strstr(vendor, "NVIDIA"))
+ isValidVendor = false;
+ if (!isValidVendor || !std::strstr(extensions, "GL_EXT_framebuffer_multisample"))
+ m_attrs.antialias = false;
+ }
+ // FIXME: instead of enforcing premultipliedAlpha = true, implement the
+ // correct behavior when premultipliedAlpha = false is requested.
+ m_attrs.premultipliedAlpha = true;
+}
+
void GraphicsContext3D::makeContextCurrent()
{
CGLSetCurrentContext(m_contextObj);
@@ -206,24 +245,86 @@ void GraphicsContext3D::reshape(int width, int height)
CGLSetCurrentContext(m_contextObj);
+ GLuint internalColorFormat, colorFormat, internalDepthStencilFormat = 0;
+ if (m_attrs.alpha) {
+ internalColorFormat = GL_RGBA8;
+ colorFormat = GL_RGBA;
+ } else {
+ internalColorFormat = GL_RGB8;
+ colorFormat = GL_RGB;
+ }
+ if (m_attrs.stencil || m_attrs.depth) {
+ // We don't allow the logic where stencil is required and depth is not.
+ // See GraphicsContext3D constructor.
+ if (m_attrs.stencil && m_attrs.depth)
+ internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT;
+ else
+ internalDepthStencilFormat = GL_DEPTH_COMPONENT;
+ }
+
+ bool mustRestoreFBO = false;
+
+ // resize multisample FBO
+ if (m_attrs.antialias) {
+ GLint maxSampleCount;
+ ::glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount);
+ GLint sampleCount = std::min(8, maxSampleCount);
+ if (sampleCount > maxSampleCount)
+ sampleCount = maxSampleCount;
+ if (m_boundFBO != m_multisampleFBO) {
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
+ mustRestoreFBO = true;
+ }
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer);
+ ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalColorFormat, width, height);
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer);
+ if (m_attrs.stencil || m_attrs.depth) {
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer);
+ ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalDepthStencilFormat, width, height);
+ if (m_attrs.stencil)
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer);
+ if (m_attrs.depth)
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer);
+ }
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ // FIXME: cleanup.
+ notImplemented();
+ }
+ }
+
+ // resize regular FBO
+ if (m_boundFBO != m_fbo) {
+ mustRestoreFBO = true;
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+ }
::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);
-
+ ::glTexImage2D(GL_TEXTURE_2D, 0, internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 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) {
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+ if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) {
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer);
+ ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height);
+ if (m_attrs.stencil)
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer);
+ if (m_attrs.depth)
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ }
+ if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
// FIXME: cleanup
notImplemented();
}
- ::glClear(GL_COLOR_BUFFER_BIT);
+ if (mustRestoreFBO)
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
+
+ GLenum clearMask = GL_COLOR_BUFFER_BIT;
+ if (m_attrs.depth)
+ clearMask |= GL_DEPTH_BUFFER_BIT;
+ if (m_attrs.stencil)
+ clearMask |= GL_STENCIL_BUFFER_BIT;
+ ::glClear(clearMask);
::glFlush();
}
@@ -237,6 +338,18 @@ static inline void ensureContext(CGLContextObj context)
CGLSetCurrentContext(context);
}
+void GraphicsContext3D::prepareTexture()
+{
+ if (m_attrs.antialias) {
+ ensureContext(m_contextObj);
+ ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
+ ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
+ ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
+ }
+ ::glFinish();
+}
+
void GraphicsContext3D::activeTexture(unsigned long texture)
{
ensureContext(m_contextObj);
@@ -268,7 +381,15 @@ void GraphicsContext3D::bindBuffer(unsigned long target, WebGLBuffer* buffer)
void GraphicsContext3D::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer)
{
ensureContext(m_contextObj);
- ::glBindFramebufferEXT(target, (buffer && buffer->object()) ? (GLuint) buffer->object() : m_fbo);
+ GLuint fbo;
+ if (buffer && buffer->object())
+ fbo = (GLuint)buffer->object();
+ else
+ fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo);
+ if (fbo != m_boundFBO) {
+ ::glBindFramebufferEXT(target, fbo);
+ m_boundFBO = fbo;
+ }
}
void GraphicsContext3D::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderbuffer)
@@ -384,13 +505,29 @@ void GraphicsContext3D::compileShader(WebGLShader* shader)
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);
+ if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) {
+ ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
+ ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
+ ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+ }
::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ if (m_attrs.antialias && m_boundFBO == m_multisampleFBO)
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
}
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);
+ if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) {
+ ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
+ ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
+ ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+ }
::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+ if (m_attrs.antialias && m_boundFBO == m_multisampleFBO)
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
}
void GraphicsContext3D::cullFace(unsigned long mode)
@@ -476,7 +613,12 @@ void GraphicsContext3D::flush()
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);
+ GLuint renderbuffer = (buffer ? (GLuint) buffer->object() : 0);
+ if (attachment == DEPTH_STENCIL_ATTACHMENT) {
+ ::glFramebufferRenderbufferEXT(target, DEPTH_ATTACHMENT, renderbuffertarget, renderbuffer);
+ ::glFramebufferRenderbufferEXT(target, STENCIL_ATTACHMENT, renderbuffertarget, renderbuffer);
+ } else
+ ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer);
}
void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture* texture, long level)
@@ -665,20 +807,22 @@ void GraphicsContext3D::polygonOffset(double factor, double units)
::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)
+void GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data)
{
+ // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e.,
+ // all previous rendering calls should be done before reading pixels.
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;
+ ::glFlush();
+ if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) {
+ ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
+ ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
+ ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+ ::glFlush();
+ }
+ ::glReadPixels(x, y, width, height, format, type, data);
+ if (m_attrs.antialias && m_boundFBO == m_multisampleFBO)
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
}
void GraphicsContext3D::releaseShaderCompiler()
@@ -691,6 +835,10 @@ void GraphicsContext3D::releaseShaderCompiler()
void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height)
{
ensureContext(m_contextObj);
+ if (internalformat == DEPTH_STENCIL)
+ internalformat = GL_DEPTH24_STENCIL8_EXT;
+ else if (internalformat == DEPTH_COMPONENT16)
+ internalformat = GL_DEPTH_COMPONENT;
::glRenderbufferStorageEXT(target, internalformat, width, height);
}
@@ -986,6 +1134,8 @@ void GraphicsContext3D::getFloatv(unsigned long pname, float* value)
void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname, int* value)
{
ensureContext(m_contextObj);
+ if (attachment == DEPTH_STENCIL_ATTACHMENT)
+ attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works.
::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
}
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
index 5362562..49aebba 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
@@ -340,6 +340,7 @@ private:
RetainPtr<WebAnimationDelegate> m_animationDelegate;
+ RetainPtr<CGImageRef> m_uncorrectedContentsImage;
RetainPtr<CGImageRef> m_pendingContentsImage;
struct LayerAnimation {
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index 22e39f5..294c82f 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -34,7 +34,6 @@
#if ENABLE(3D_CANVAS)
#import "Canvas3DLayer.h"
#endif
-#import "CString.h"
#import "FloatConversion.h"
#import "FloatRect.h"
#import "Image.h"
@@ -769,7 +768,17 @@ void GraphicsLayerCA::pauseAnimation(const String& keyframesName, double timeOff
void GraphicsLayerCA::setContentsToImage(Image* image)
{
if (image) {
- m_pendingContentsImage = image->nativeImageForCurrentFrame();
+ CGImageRef newImage = image->nativeImageForCurrentFrame();
+ if (!newImage)
+ return;
+
+ // Check to see if the image changed; we have to do this because the call to
+ // CGImageCreateCopyWithColorSpace() below can create a new image every time.
+ if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage)
+ return;
+
+ m_uncorrectedContentsImage = newImage;
+ m_pendingContentsImage = newImage;
CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
@@ -783,6 +792,7 @@ void GraphicsLayerCA::setContentsToImage(Image* image)
if (!m_contentsLayer)
noteSublayersChanged();
} else {
+ m_uncorrectedContentsImage = 0;
m_pendingContentsImage = 0;
m_contentsLayerPurpose = NoContentsLayer;
if (m_contentsLayer)
@@ -1716,7 +1726,7 @@ void GraphicsLayerCA::setContentsToGraphicsContext3D(const GraphicsContext3D* gr
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)]);
+ m_contentsLayer.adoptNS([[Canvas3DLayer alloc] initWithContext:const_cast<GraphicsContext3D*>(graphicsContext3D)]);
#ifndef NDEBUG
[m_contentsLayer.get() setName:@"3D Layer"];
#endif
@@ -1859,12 +1869,28 @@ void GraphicsLayerCA::setupAnimation(CAPropertyAnimation* propertyAnim, const An
else if (anim->direction() == Animation::AnimationDirectionAlternate)
repeatCount /= 2;
+ NSString* fillMode = 0;
+ switch (anim->fillMode()) {
+ case AnimationFillModeNone:
+ fillMode = kCAFillModeForwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash.
+ break;
+ case AnimationFillModeBackwards:
+ fillMode = kCAFillModeBoth; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash.
+ break;
+ case AnimationFillModeForwards:
+ fillMode = kCAFillModeForwards;
+ break;
+ case AnimationFillModeBoth:
+ fillMode = kCAFillModeBoth;
+ break;
+ }
+
[propertyAnim setDuration:duration];
[propertyAnim setRepeatCount:repeatCount];
[propertyAnim setAutoreverses:anim->direction()];
[propertyAnim setRemovedOnCompletion:NO];
[propertyAnim setAdditive:additive];
- [propertyAnim setFillMode:@"extended"];
+ [propertyAnim setFillMode:fillMode];
[propertyAnim setDelegate:m_animationDelegate.get()];
}
@@ -2226,6 +2252,7 @@ void GraphicsLayerCA::setupContentsLayer(CALayer* contentsLayer)
{
// Turn off implicit animations on the inner layer.
[contentsLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
+ [contentsLayer setMasksToBounds:YES];
if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) {
CATransform3D flipper = {
diff --git a/WebCore/platform/graphics/mac/ImageMac.mm b/WebCore/platform/graphics/mac/ImageMac.mm
index 672c3c8..96b93be 100644
--- a/WebCore/platform/graphics/mac/ImageMac.mm
+++ b/WebCore/platform/graphics/mac/ImageMac.mm
@@ -30,6 +30,7 @@
#import "FoundationExtras.h"
#import "GraphicsContext.h"
#import "PlatformString.h"
+#import "SharedBuffer.h"
@interface WebCoreBundleFinder : NSObject
@end
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 355aa68..2636aeb 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -59,7 +59,6 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
public:
static void registerMediaEngine(MediaEngineRegistrar);
- ~MediaPlayerPrivate();
void repaint();
void loadStateChanged();
@@ -70,6 +69,7 @@ public:
private:
MediaPlayerPrivate(MediaPlayer*);
+ ~MediaPlayerPrivate();
// engine support
static MediaPlayerPrivateInterface* create(MediaPlayer* player);
@@ -89,9 +89,12 @@ private:
void load(const String& url);
void cancelLoad();
+ void loadInternal(const String& url);
+ void resumeLoad();
void play();
void pause();
+ void prepareToPlay();
bool paused() const;
bool seeking() const;
@@ -107,6 +110,8 @@ private:
bool hasClosedCaptions() const;
void setClosedCaptionsVisible(bool);
+ void setPreload(MediaPlayer::Preload);
+
MediaPlayer::NetworkState networkState() const { return m_networkState; }
MediaPlayer::ReadyState readyState() const { return m_readyState; }
@@ -172,6 +177,7 @@ private:
RetainPtr<QTMovieView> m_qtMovieView;
RetainPtr<QTVideoRendererWebKitOnly> m_qtVideoRenderer;
RetainPtr<WebCoreMovieObserver> m_objcObserver;
+ String m_movieURL;
float m_seekTo;
Timer<MediaPlayerPrivate> m_seekTimer;
MediaPlayer::NetworkState m_networkState;
@@ -184,11 +190,13 @@ private:
float m_cachedDuration;
float m_timeToRestore;
RetainPtr<QTMovieLayer> m_qtVideoLayer;
+ MediaPlayer::Preload m_preload;
bool m_startedPlaying;
bool m_isStreaming;
bool m_visible;
bool m_hasUnsupportedTracks;
bool m_videoFrameHasDrawn;
+ bool m_delayingLoad;
#if DRAW_FRAME_RATE
int m_frameCountWhilePlaying;
double m_timeStartedPlaying;
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 2b90f7a..c837b51 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -211,6 +211,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_reportedDuration(-1)
, m_cachedDuration(-1)
, m_timeToRestore(-1)
+ , m_preload(MediaPlayer::Auto)
, m_startedPlaying(false)
, m_isStreaming(false)
, m_visible(false)
@@ -549,8 +550,30 @@ QTTime MediaPlayerPrivate::createQTTime(float time) const
return QTMakeTime(time * timeScale, timeScale);
}
+void MediaPlayerPrivate::resumeLoad()
+{
+ m_delayingLoad = false;
+
+ if (m_movieURL)
+ loadInternal(m_movieURL);
+}
+
void MediaPlayerPrivate::load(const String& url)
{
+ m_movieURL = url;
+
+ // If the element is not supposed to load any data return immediately because QTKit
+ // doesn't have API to throttle loading.
+ if (m_preload == MediaPlayer::None) {
+ m_delayingLoad = true;
+ return;
+ }
+
+ loadInternal(url);
+}
+
+void MediaPlayerPrivate::loadInternal(const String& url)
+{
if (m_networkState != MediaPlayer::Loading) {
m_networkState = MediaPlayer::Loading;
m_player->networkStateChanged();
@@ -570,6 +593,12 @@ void MediaPlayerPrivate::load(const String& url)
[m_objcObserver.get() setDelayCallbacks:NO];
}
+void MediaPlayerPrivate::prepareToPlay()
+{
+ if (!m_qtMovie || m_delayingLoad)
+ resumeLoad();
+}
+
PlatformMedia MediaPlayerPrivate::platformMedia() const
{
PlatformMedia plaftformMedia = { m_qtMovie.get() };
@@ -910,6 +939,7 @@ void MediaPlayerPrivate::updateStates()
loadState = QTMovieLoadStateError;
if (loadState != QTMovieLoadStateError) {
+ wkQTMovieSelectPreferredAlternates(m_qtMovie.get());
cacheMovieScale();
MediaPlayer::MovieLoadType movieType = movieLoadType();
m_isStreaming = movieType == MediaPlayer::StoredStream || movieType == MediaPlayer::LiveStream;
@@ -1437,6 +1467,12 @@ MediaPlayer::MovieLoadType MediaPlayerPrivate::movieLoadType() const
return movieType;
}
+void MediaPlayerPrivate::setPreload(MediaPlayer::Preload preload)
+{
+ m_preload = preload;
+ if (m_delayingLoad && m_preload != MediaPlayer::None)
+ resumeLoad();
+}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/MediaPlayerProxy.h b/WebCore/platform/graphics/mac/MediaPlayerProxy.h
index 6060484..cc7ec95 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerProxy.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerProxy.h
@@ -40,8 +40,8 @@ enum MediaPlayerProxyNotificationType {
MediaPlayerNotificationStartUsingNetwork,
MediaPlayerNotificationStopUsingNetwork,
- MediaPlayerNotificationEnteredFullScreen,
- MediaPlayerNotificationExitedFullScreen,
+ MediaPlayerNotificationEnteredFullscreen,
+ MediaPlayerNotificationExitedFullscreen,
MediaPlayerNotificationReadyForInspection,
MediaPlayerNotificationReadyForPlayback,
diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index 09947d8..562f56e 100644
--- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -407,17 +407,29 @@ void SimpleFontData::determinePitch()
[name caseInsensitiveCompare:@"MonotypeCorsiva"] != NSOrderedSame;
}
-float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const
{
- NSFont* font = m_platformData.font();
- float pointSize = m_platformData.m_size;
+ NSFont* font = platformData().font();
+ float pointSize = platformData().m_size;
CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
CGSize advance;
- if (!wkGetGlyphTransformedAdvances(m_platformData.cgFont(), font, &m, &glyph, &advance)) {
+ if (!wkGetGlyphTransformedAdvances(platformData().cgFont(), font, &m, &glyph, &advance)) {
LOG_ERROR("Unable to cache glyph widths for %@ %f", [font displayName], pointSize);
advance.width = 0;
}
- return advance.width + m_syntheticBoldOffset;
+ GlyphMetrics metrics;
+ metrics.horizontalAdvance = advance.width + m_syntheticBoldOffset;
+ if (metricsMode == GlyphBoundingBox) {
+#ifndef BUILDING_ON_TIGER
+ CGRect boundingBox;
+ CGFontGetGlyphBBoxes(platformData().cgFont(), &glyph, 1, &boundingBox);
+ CGFloat scale = pointSize / unitsPerEm();
+ metrics.boundingBox = CGRectApplyAffineTransform(boundingBox, CGAffineTransformMakeScale(scale, -scale));
+ if (m_syntheticBoldOffset)
+ metrics.boundingBox.setWidth(metrics.boundingBox.width() + m_syntheticBoldOffset);
+#endif
+ }
+ return metrics;
}
#if USE(ATSUI)
diff --git a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp
index 3c7eaf2..d681d75 100644
--- a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp
+++ b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp
@@ -263,6 +263,30 @@ EGLSurface EGLDisplayOpenVG::createPbufferSurface(const IntSize& size, const EGL
return surface;
}
+EGLSurface EGLDisplayOpenVG::createPbufferFromClientBuffer(
+ EGLClientBuffer clientBuffer, EGLenum bufferType, const EGLConfig& config, EGLint* errorCode)
+{
+ EGLSurface surface = eglCreatePbufferFromClientBuffer(m_display,
+ bufferType, clientBuffer, config, 0 /* attribList */);
+
+ if (errorCode)
+ *errorCode = eglGetError();
+ else
+ ASSERT_EGL_NO_ERROR();
+
+ if (surface == EGL_NO_SURFACE)
+ return EGL_NO_SURFACE;
+
+ EGLint surfaceConfigId;
+ EGLBoolean success = eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &surfaceConfigId);
+ ASSERT(success == EGL_TRUE);
+ ASSERT(surfaceConfigId != EGL_BAD_ATTRIBUTE);
+
+ ASSERT(!m_surfaceConfigIds.contains(surface));
+ m_surfaceConfigIds.set(surface, surfaceConfigId);
+ return surface;
+}
+
EGLSurface EGLDisplayOpenVG::surfaceForWindow(EGLNativeWindowType wId, const EGLConfig& config)
{
if (m_windowSurfaces.contains(wId))
diff --git a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h
index fd8353d..0dff6c9 100644
--- a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h
+++ b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h
@@ -51,6 +51,7 @@ public:
* If no surface could be created and errorCode is zero, this method
* will trigger an assertion by itself. */
EGLSurface createPbufferSurface(const IntSize&, const EGLConfig&, EGLint* errorCode = 0);
+ EGLSurface createPbufferFromClientBuffer(EGLClientBuffer, EGLenum bufferType, const EGLConfig&, EGLint* errorCode = 0);
EGLSurface surfaceForWindow(EGLNativeWindowType, const EGLConfig&);
diff --git a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
index 5ed892c..54cc7ee 100644
--- a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
+++ b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
@@ -20,11 +20,12 @@
#include "config.h"
#include "GraphicsContext.h"
+#include "AffineTransform.h"
#include "GraphicsContextPrivate.h"
+#include "KURL.h"
#include "NotImplemented.h"
#include "PainterOpenVG.h"
#include "SurfaceOpenVG.h"
-#include "TransformationMatrix.h"
#include <wtf/Assertions.h>
#include <wtf/MathExtras.h>
@@ -69,12 +70,12 @@ PlatformGraphicsContext* GraphicsContext::platformContext() const
return m_data->baseSurface();
}
-TransformationMatrix GraphicsContext::getCTM() const
+AffineTransform GraphicsContext::getCTM() const
{
if (paintingDisabled())
- return TransformationMatrix();
+ return AffineTransform();
- return m_data->transformationMatrix();
+ return m_data->transformation();
}
void GraphicsContext::savePlatformState()
@@ -143,7 +144,7 @@ void GraphicsContext::fillPath()
if (paintingDisabled())
return;
- notImplemented();
+ m_data->drawPath(VG_FILL_PATH, m_common->state.fillRule);
}
void GraphicsContext::strokePath()
@@ -151,7 +152,15 @@ void GraphicsContext::strokePath()
if (paintingDisabled())
return;
- notImplemented();
+ m_data->drawPath(VG_STROKE_PATH, m_common->state.fillRule);
+}
+
+void GraphicsContext::drawPath()
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->drawPath(VG_FILL_PATH | VG_STROKE_PATH, m_common->state.fillRule);
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -193,7 +202,7 @@ void GraphicsContext::beginPath()
if (paintingDisabled())
return;
- notImplemented();
+ m_data->beginPath();
}
void GraphicsContext::addPath(const Path& path)
@@ -201,7 +210,7 @@ void GraphicsContext::addPath(const Path& path)
if (paintingDisabled())
return;
- notImplemented();
+ m_data->addPath(path);
}
void GraphicsContext::clip(const FloatRect& rect)
@@ -217,8 +226,7 @@ void GraphicsContext::clipPath(WindRule clipRule)
if (paintingDisabled())
return;
- notImplemented();
- UNUSED_PARAM(clipRule);
+ m_data->clipPath(*(m_data->currentPath()), PainterOpenVG::IntersectClip, clipRule);
}
void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
@@ -281,7 +289,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
if (paintingDisabled())
return FloatRect();
- return FloatRect(enclosingIntRect(m_data->transformationMatrix().mapRect(rect)));
+ return FloatRect(enclosingIntRect(m_data->transformation().mapRect(rect)));
}
void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace)
@@ -404,8 +412,7 @@ void GraphicsContext::clip(const Path& path)
if (paintingDisabled())
return;
- notImplemented();
- UNUSED_PARAM(path);
+ m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule);
}
void GraphicsContext::canvasClip(const Path& path)
@@ -418,8 +425,7 @@ void GraphicsContext::clipOut(const Path& path)
if (paintingDisabled())
return;
- notImplemented();
- UNUSED_PARAM(path);
+ m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
}
void GraphicsContext::scale(const FloatSize& scaleFactors)
@@ -451,8 +457,8 @@ IntPoint GraphicsContext::origin()
if (paintingDisabled())
return IntPoint();
- TransformationMatrix matrix = m_data->transformationMatrix();
- return IntPoint(roundf(matrix.m41()), roundf(matrix.m42()));
+ AffineTransform transformation = m_data->transformation();
+ return IntPoint(roundf(transformation.e()), roundf(transformation.f()));
}
void GraphicsContext::clipOut(const IntRect& rect)
@@ -460,8 +466,9 @@ void GraphicsContext::clipOut(const IntRect& rect)
if (paintingDisabled())
return;
- notImplemented();
- UNUSED_PARAM(rect);
+ Path path;
+ path.addRect(rect);
+ m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
}
void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
@@ -469,8 +476,9 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
if (paintingDisabled())
return;
- notImplemented();
- UNUSED_PARAM(rect);
+ Path path;
+ path.addEllipse(rect);
+ m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
}
void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
@@ -488,17 +496,20 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
if (paintingDisabled())
return;
- notImplemented();
- UNUSED_PARAM(rect);
- UNUSED_PARAM(thickness);
+ Path path;
+ path.addEllipse(rect);
+ path.addEllipse(FloatRect(rect.x() + thickness, rect.y() + thickness,
+ rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
+
+ m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule);
}
-void GraphicsContext::concatCTM(const TransformationMatrix& transform)
+void GraphicsContext::concatCTM(const AffineTransform& transformation)
{
if (paintingDisabled())
return;
- m_data->concatTransformationMatrix(transform);
+ m_data->concatTransformation(transformation);
}
void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
diff --git a/WebCore/platform/graphics/openvg/PainterOpenVG.cpp b/WebCore/platform/graphics/openvg/PainterOpenVG.cpp
index 3b7cf85..5842afd 100644
--- a/WebCore/platform/graphics/openvg/PainterOpenVG.cpp
+++ b/WebCore/platform/graphics/openvg/PainterOpenVG.cpp
@@ -20,6 +20,7 @@
#include "config.h"
#include "PainterOpenVG.h"
+#include "AffineTransform.h"
#include "Color.h"
#include "DashArray.h"
#include "FloatPoint.h"
@@ -28,8 +29,8 @@
#include "IntRect.h"
#include "IntSize.h"
#include "NotImplemented.h"
+#include "PlatformPathOpenVG.h"
#include "SurfaceOpenVG.h"
-#include "TransformationMatrix.h"
#include "VGUtils.h"
#if PLATFORM(EGL)
@@ -43,12 +44,9 @@
namespace WebCore {
-static bool isNonRotatedAffineTransformation(const TransformationMatrix& matrix)
+static bool isNonRotatedAffineTransformation(const AffineTransform& t)
{
- return matrix.m12() <= FLT_EPSILON && matrix.m13() <= FLT_EPSILON && matrix.m14() <= FLT_EPSILON
- && matrix.m21() <= FLT_EPSILON && matrix.m23() <= FLT_EPSILON && matrix.m24() <= FLT_EPSILON
- && matrix.m31() <= FLT_EPSILON && matrix.m32() <= FLT_EPSILON && matrix.m34() <= FLT_EPSILON
- && matrix.m44() >= 1 - FLT_EPSILON;
+ return t.b() <= FLT_EPSILON && t.c() <= FLT_EPSILON;
}
static VGCapStyle toVGCapStyle(LineCap lineCap)
@@ -103,12 +101,16 @@ static void setVGSolidColor(VGPaintMode paintMode, const Color& color)
struct PlatformPainterState {
- TransformationMatrix surfaceTransformationMatrix;
+ AffineTransform surfaceTransformation;
CompositeOperator compositeOperation;
float opacity;
bool scissoringEnabled;
FloatRect scissorRect;
+#ifdef OPENVG_VERSION_1_1
+ bool maskingChangedAndEnabled;
+ VGMaskLayer mask;
+#endif
Color fillColor;
StrokeStyle strokeStyle;
@@ -120,12 +122,17 @@ struct PlatformPainterState {
DashArray strokeDashArray;
float strokeDashOffset;
+ int textDrawingMode;
bool antialiasingEnabled;
PlatformPainterState()
: compositeOperation(CompositeSourceOver)
, opacity(1.0)
, scissoringEnabled(false)
+#ifdef OPENVG_VERSION_1_1
+ , maskingChangedAndEnabled(false)
+ , mask(VG_INVALID_HANDLE)
+#endif
, fillColor(Color::black)
, strokeStyle(NoStroke)
, strokeThickness(0.0)
@@ -133,19 +140,40 @@ struct PlatformPainterState {
, strokeLineJoin(MiterJoin)
, strokeMiterLimit(4.0)
, strokeDashOffset(0.0)
+ , textDrawingMode(cTextFill)
, antialiasingEnabled(true)
{
}
+ ~PlatformPainterState()
+ {
+#ifdef OPENVG_VERSION_1_1
+ if (maskingChangedAndEnabled && mask != VG_INVALID_HANDLE) {
+ vgDestroyMaskLayer(mask);
+ ASSERT_VG_NO_ERROR();
+ mask = VG_INVALID_HANDLE;
+ }
+#endif
+ }
+
PlatformPainterState(const PlatformPainterState& state)
{
- surfaceTransformationMatrix = state.surfaceTransformationMatrix;
+ surfaceTransformation = state.surfaceTransformation;
scissoringEnabled = state.scissoringEnabled;
scissorRect = state.scissorRect;
+#ifdef OPENVG_VERSION_1_1
+ maskingChangedAndEnabled = false;
+ mask = state.mask;
+#endif
copyPaintState(&state);
}
+ inline bool maskingEnabled()
+ {
+ return maskingChangedAndEnabled || mask != VG_INVALID_HANDLE;
+ }
+
void copyPaintState(const PlatformPainterState* other)
{
compositeOperation = other->compositeOperation;
@@ -161,6 +189,7 @@ struct PlatformPainterState {
strokeDashArray = other->strokeDashArray;
strokeDashOffset = other->strokeDashOffset;
+ textDrawingMode = other->textDrawingMode;
antialiasingEnabled = other->antialiasingEnabled;
}
@@ -184,8 +213,18 @@ struct PlatformPainterState {
applyBlending(painter);
applyStrokeStyle();
- applyTransformationMatrix(painter);
+ applyTransformation(painter);
applyScissorRect();
+
+#ifdef OPENVG_VERSION_1_1
+ if (maskingEnabled()) {
+ vgSeti(VG_MASKING, VG_TRUE);
+ if (mask != VG_INVALID_HANDLE)
+ vgMask(mask, VG_SET_MASK, 0, 0, painter->surface()->width(), painter->surface()->height());
+ } else
+ vgSeti(VG_MASKING, VG_FALSE);
+#endif
+ ASSERT_VG_NO_ERROR();
}
void applyBlending(PainterOpenVG* painter)
@@ -267,12 +306,12 @@ struct PlatformPainterState {
ASSERT_VG_NO_ERROR();
}
- void applyTransformationMatrix(PainterOpenVG* painter)
+ void applyTransformation(PainterOpenVG* painter)
{
// There are *five* separate transforms that can be applied to OpenVG as of 1.1
// but it is not clear that we need to set them separately. Instead we set them
// all right here and let this be a call to essentially set the world transformation!
- VGMatrix vgMatrix(surfaceTransformationMatrix);
+ VGMatrix vgMatrix(surfaceTransformation);
const VGfloat* vgFloatArray = vgMatrix.toVGfloat();
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
@@ -337,18 +376,36 @@ struct PlatformPainterState {
{
return (compositeOperation == CompositeSourceOver && !fillColor.alpha());
}
+
+ void saveMaskIfNecessary(PainterOpenVG* painter)
+ {
+#ifdef OPENVG_VERSION_1_1
+ if (maskingChangedAndEnabled) {
+ if (mask != VG_INVALID_HANDLE) {
+ vgDestroyMaskLayer(mask);
+ ASSERT_VG_NO_ERROR();
+ }
+ mask = vgCreateMaskLayer(painter->surface()->width(), painter->surface()->height());
+ ASSERT(mask != VG_INVALID_HANDLE);
+ vgCopyMask(mask, 0, 0, 0, 0, painter->surface()->width(), painter->surface()->height());
+ ASSERT_VG_NO_ERROR();
+ }
+#endif
+ }
};
PainterOpenVG::PainterOpenVG()
: m_state(0)
, m_surface(0)
+ , m_currentPath(0)
{
}
PainterOpenVG::PainterOpenVG(SurfaceOpenVG* surface)
: m_state(0)
, m_surface(0)
+ , m_currentPath(0)
{
ASSERT(surface);
begin(surface);
@@ -357,6 +414,7 @@ PainterOpenVG::PainterOpenVG(SurfaceOpenVG* surface)
PainterOpenVG::~PainterOpenVG()
{
end();
+ delete m_currentPath;
}
void PainterOpenVG::begin(SurfaceOpenVG* surface)
@@ -417,31 +475,53 @@ void PainterOpenVG::blitToSurface()
m_surface->flush();
}
-TransformationMatrix PainterOpenVG::transformationMatrix() const
+AffineTransform PainterOpenVG::transformation() const
{
ASSERT(m_state);
- return m_state->surfaceTransformationMatrix;
+ return m_state->surfaceTransformation;
}
-void PainterOpenVG::concatTransformationMatrix(const TransformationMatrix& matrix)
+void PainterOpenVG::concatTransformation(const AffineTransform& transformation)
{
ASSERT(m_state);
m_surface->makeCurrent();
- // We do the multiplication ourself using WebCore's TransformationMatrix rather than
- // offloading this to VG via vgMultMatrix to keep things simple and so we can maintain
- // state ourselves.
- m_state->surfaceTransformationMatrix.multLeft(matrix);
- m_state->applyTransformationMatrix(this);
+ // We do the multiplication ourself using WebCore's AffineTransform rather
+ // than offloading this to VG via vgMultMatrix() to keep things simple and
+ // so we can maintain state ourselves.
+ m_state->surfaceTransformation.multLeft(transformation);
+ m_state->applyTransformation(this);
}
-void PainterOpenVG::setTransformationMatrix(const TransformationMatrix& matrix)
+void PainterOpenVG::setTransformation(const AffineTransform& transformation)
{
ASSERT(m_state);
m_surface->makeCurrent();
- m_state->surfaceTransformationMatrix = matrix;
- m_state->applyTransformationMatrix(this);
+ m_state->surfaceTransformation = transformation;
+ m_state->applyTransformation(this);
+}
+
+void PainterOpenVG::transformPath(VGPath dst, VGPath src, const AffineTransform& transformation)
+{
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+
+ // Save the transform state
+ VGfloat currentMatrix[9];
+ vgGetMatrix(currentMatrix);
+ ASSERT_VG_NO_ERROR();
+
+ // Load the new transform
+ vgLoadMatrix(VGMatrix(transformation).toVGfloat());
+ ASSERT_VG_NO_ERROR();
+
+ // Apply the new transform
+ vgTransformPath(dst, src);
+ ASSERT_VG_NO_ERROR();
+
+ // Restore the transform state
+ vgLoadMatrix(currentMatrix);
+ ASSERT_VG_NO_ERROR();
}
CompositeOperator PainterOpenVG::compositeOperation() const
@@ -575,6 +655,18 @@ void PainterOpenVG::setFillColor(const Color& color)
setVGSolidColor(VG_FILL_PATH, color);
}
+int PainterOpenVG::textDrawingMode() const
+{
+ ASSERT(m_state);
+ return m_state->textDrawingMode;
+}
+
+void PainterOpenVG::setTextDrawingMode(int mode)
+{
+ ASSERT(m_state);
+ m_state->textDrawingMode = mode;
+}
+
bool PainterOpenVG::antialiasingEnabled() const
{
ASSERT(m_state);
@@ -599,9 +691,9 @@ void PainterOpenVG::scale(const FloatSize& scaleFactors)
ASSERT(m_state);
m_surface->makeCurrent();
- TransformationMatrix matrix = m_state->surfaceTransformationMatrix;
- matrix.scaleNonUniform(scaleFactors.width(), scaleFactors.height());
- setTransformationMatrix(matrix);
+ AffineTransform transformation = m_state->surfaceTransformation;
+ transformation.scaleNonUniform(scaleFactors.width(), scaleFactors.height());
+ setTransformation(transformation);
}
void PainterOpenVG::rotate(float radians)
@@ -609,9 +701,9 @@ void PainterOpenVG::rotate(float radians)
ASSERT(m_state);
m_surface->makeCurrent();
- TransformationMatrix matrix = m_state->surfaceTransformationMatrix;
- matrix.rotate(rad2deg(radians));
- setTransformationMatrix(matrix);
+ AffineTransform transformation = m_state->surfaceTransformation;
+ transformation.rotate(rad2deg(radians));
+ setTransformation(transformation);
}
void PainterOpenVG::translate(float dx, float dy)
@@ -619,9 +711,50 @@ void PainterOpenVG::translate(float dx, float dy)
ASSERT(m_state);
m_surface->makeCurrent();
- TransformationMatrix matrix = m_state->surfaceTransformationMatrix;
- matrix.translate(dx, dy);
- setTransformationMatrix(matrix);
+ AffineTransform transformation = m_state->surfaceTransformation;
+ transformation.translate(dx, dy);
+ setTransformation(transformation);
+}
+
+void PainterOpenVG::beginPath()
+{
+ delete m_currentPath;
+ m_currentPath = new Path();
+}
+
+void PainterOpenVG::addPath(const Path& path)
+{
+ m_currentPath->platformPath()->makeCompatibleContextCurrent();
+
+ vgAppendPath(m_currentPath->platformPath()->vgPath(), path.platformPath()->vgPath());
+ ASSERT_VG_NO_ERROR();
+}
+
+Path* PainterOpenVG::currentPath() const
+{
+ return m_currentPath;
+}
+
+void PainterOpenVG::drawPath(VGbitfield specifiedPaintModes, WindRule fillRule)
+{
+ ASSERT(m_state);
+
+ VGbitfield paintModes = 0;
+ if (!m_state->strokeDisabled())
+ paintModes |= VG_STROKE_PATH;
+ if (!m_state->fillDisabled())
+ paintModes |= VG_FILL_PATH;
+
+ paintModes &= specifiedPaintModes;
+
+ if (!paintModes)
+ return;
+
+ m_surface->makeCurrent();
+
+ vgSeti(VG_FILL_RULE, toVGFillRule(fillRule));
+ vgDrawPath(m_currentPath->platformPath()->vgPath(), paintModes);
+ ASSERT_VG_NO_ERROR();
}
void PainterOpenVG::intersectScissorRect(const FloatRect& rect)
@@ -649,7 +782,7 @@ void PainterOpenVG::intersectClipRect(const FloatRect& rect)
ASSERT(m_state);
m_surface->makeCurrent();
- if (m_state->surfaceTransformationMatrix.isIdentity()) {
+ if (m_state->surfaceTransformation.isIdentity()) {
// No transformation required, skip all the complex stuff.
intersectScissorRect(rect);
return;
@@ -660,16 +793,49 @@ void PainterOpenVG::intersectClipRect(const FloatRect& rect)
// (potentially more expensive) path clipping. Note that scissoring is not
// subject to transformations, so we need to do the transformation to
// surface coordinates by ourselves.
- FloatQuad effectiveScissorQuad =
- m_state->surfaceTransformationMatrix.mapQuad(FloatQuad(rect));
+ FloatQuad effectiveScissorQuad = m_state->surfaceTransformation.mapQuad(FloatQuad(rect));
if (effectiveScissorQuad.isRectilinear())
intersectScissorRect(effectiveScissorQuad.boundingBox());
else {
// The transformed scissorRect cannot be represented as FloatRect
- // anymore, so we need to perform masking instead. Not yet implemented.
- notImplemented();
+ // anymore, so we need to perform masking instead.
+ Path scissorRectPath;
+ scissorRectPath.addRect(rect);
+ clipPath(scissorRectPath, PainterOpenVG::IntersectClip);
+ }
+}
+
+void PainterOpenVG::clipPath(const Path& path, PainterOpenVG::ClipOperation maskOp, WindRule clipRule)
+{
+#ifdef OPENVG_VERSION_1_1
+ ASSERT(m_state);
+ m_surface->makeCurrent();
+
+ if (m_state->mask != VG_INVALID_HANDLE && !m_state->maskingChangedAndEnabled) {
+ // The parent's mask has been inherited - dispose the handle so that
+ // it won't be overwritten.
+ m_state->maskingChangedAndEnabled = true;
+ m_state->mask = VG_INVALID_HANDLE;
+ } else if (!m_state->maskingEnabled()) {
+ // None of the parent painter states had a mask enabled yet.
+ m_state->maskingChangedAndEnabled = true;
+ vgSeti(VG_MASKING, VG_TRUE);
+ // Make sure not to inherit previous mask state from previously written
+ // (but disabled) masks. For VG_FILL_MASK the first argument is ignored,
+ // we pass VG_INVALID_HANDLE which is what the OpenVG spec suggests.
+ vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, m_surface->width(), m_surface->height());
}
+
+ // Intersect the path from the mask, or subtract it from there.
+ // (In either case we always decrease the visible area, never increase it,
+ // which means masking never has to modify scissor rectangles.)
+ vgSeti(VG_FILL_RULE, toVGFillRule(clipRule));
+ vgRenderToMask(path.platformPath()->vgPath(), VG_FILL_PATH, (VGMaskOperation) maskOp);
+ ASSERT_VG_NO_ERROR();
+#elseif
+ notImplemented();
+#endif
}
void PainterOpenVG::drawRect(const FloatRect& rect, VGbitfield specifiedPaintModes)
@@ -919,6 +1085,58 @@ void PainterOpenVG::drawPolygon(size_t numPoints, const FloatPoint* points, VGbi
ASSERT_VG_NO_ERROR();
}
+#ifdef OPENVG_VERSION_1_1
+void PainterOpenVG::drawText(VGFont vgFont, Vector<VGuint>& characters, VGfloat* adjustmentsX, VGfloat* adjustmentsY, const FloatPoint& point)
+{
+ ASSERT(m_state);
+
+ VGbitfield paintModes = 0;
+
+ if (m_state->textDrawingMode & cTextClip)
+ return; // unsupported for every port except CG at the time of writing
+ if (m_state->textDrawingMode & cTextFill && !m_state->fillDisabled())
+ paintModes |= VG_FILL_PATH;
+ if (m_state->textDrawingMode & cTextStroke && !m_state->strokeDisabled())
+ paintModes |= VG_STROKE_PATH;
+
+ m_surface->makeCurrent();
+
+ FloatPoint effectivePoint = m_state->surfaceTransformation.mapPoint(point);
+ FloatPoint p = point;
+ AffineTransform* originalTransformation = 0;
+
+ // In case the font isn't drawn at a pixel-exact baseline and we can easily
+ // fix that (which is the case for non-rotated affine transforms), let's
+ // align the starting point to the pixel boundary in order to prevent
+ // font rendering issues such as glyphs that appear off by a pixel.
+ // This causes us to have inconsistent spacing between baselines in a
+ // larger paragraph, but that seems to be the least of all evils.
+ if ((fmod(effectivePoint.x() + 0.01, 1.0) > 0.02 || fmod(effectivePoint.y() + 0.01, 1.0) > 0.02)
+ && isNonRotatedAffineTransformation(m_state->surfaceTransformation))
+ {
+ originalTransformation = new AffineTransform(m_state->surfaceTransformation);
+ setTransformation(AffineTransform(
+ m_state->surfaceTransformation.a(), 0,
+ 0, m_state->surfaceTransformation.d(),
+ roundf(effectivePoint.x()), roundf(effectivePoint.y())));
+ p = FloatPoint();
+ }
+
+ const VGfloat vgPoint[2] = { p.x(), p.y() };
+ vgSetfv(VG_GLYPH_ORIGIN, 2, vgPoint);
+ ASSERT_VG_NO_ERROR();
+
+ vgDrawGlyphs(vgFont, characters.size(), characters.data(),
+ adjustmentsX, adjustmentsY, paintModes, VG_TRUE /* allow autohinting */);
+ ASSERT_VG_NO_ERROR();
+
+ if (originalTransformation) {
+ setTransformation(*originalTransformation);
+ delete originalTransformation;
+ }
+}
+#endif
+
void PainterOpenVG::save(PainterOpenVG::SaveMode saveMode)
{
ASSERT(m_state);
@@ -930,15 +1148,18 @@ void PainterOpenVG::save(PainterOpenVG::SaveMode saveMode)
m_surface->makeCurrent(SurfaceOpenVG::DontSaveOrApplyPainterState);
if (saveMode == PainterOpenVG::CreateNewState) {
+ m_state->saveMaskIfNecessary(this);
PlatformPainterState* state = new PlatformPainterState(*m_state);
m_stateStack.append(state);
m_state = m_stateStack.last();
- } else { // if (saveMode == PainterOpenVG::CreateNewStateWithPaintStateOnly) {
+ } else if (saveMode == PainterOpenVG::CreateNewStateWithPaintStateOnly) {
+ m_state->saveMaskIfNecessary(this);
PlatformPainterState* state = new PlatformPainterState();
state->copyPaintState(m_state);
m_stateStack.append(state);
m_state = m_stateStack.last();
- }
+ } else // if (saveMode == PainterOpenVG::KeepCurrentState)
+ m_state->saveMaskIfNecessary(this);
}
void PainterOpenVG::restore()
diff --git a/WebCore/platform/graphics/openvg/PainterOpenVG.h b/WebCore/platform/graphics/openvg/PainterOpenVG.h
index 6936eee..30cdf31 100644
--- a/WebCore/platform/graphics/openvg/PainterOpenVG.h
+++ b/WebCore/platform/graphics/openvg/PainterOpenVG.h
@@ -26,17 +26,17 @@
#include <openvg.h>
#include <wtf/Noncopyable.h>
-#include <wtf/Platform.h>
#include <wtf/Vector.h>
namespace WebCore {
+class AffineTransform;
class FloatPoint;
class FloatRect;
class IntRect;
class IntSize;
+class Path;
class SurfaceOpenVG;
-class TransformationMatrix;
struct PlatformPainterState;
@@ -47,8 +47,13 @@ public:
enum SaveMode {
CreateNewState,
+ KeepCurrentState,
CreateNewStateWithPaintStateOnly // internal usage only, do not use outside PainterOpenVG
};
+ enum ClipOperation {
+ IntersectClip = VG_INTERSECT_MASK,
+ SubtractClip = VG_SUBTRACT_MASK
+ };
PainterOpenVG();
PainterOpenVG(SurfaceOpenVG*);
@@ -57,9 +62,11 @@ public:
void begin(SurfaceOpenVG*);
void end();
- TransformationMatrix transformationMatrix() const;
- void setTransformationMatrix(const TransformationMatrix&);
- void concatTransformationMatrix(const TransformationMatrix&);
+ AffineTransform transformation() const;
+ void setTransformation(const AffineTransform&);
+ void concatTransformation(const AffineTransform&);
+
+ static void transformPath(VGPath dst, VGPath src, const AffineTransform&);
CompositeOperator compositeOperation() const;
void setCompositeOperation(CompositeOperator);
@@ -82,6 +89,9 @@ public:
Color fillColor() const;
void setFillColor(const Color&);
+ int textDrawingMode() const;
+ void setTextDrawingMode(int mode);
+
bool antialiasingEnabled() const;
void setAntialiasingEnabled(bool);
@@ -91,12 +101,21 @@ public:
void drawArc(const IntRect& ellipseBounds, int startAngle, int angleSpan, VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH));
void drawEllipse(const IntRect& bounds, VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH));
void drawPolygon(size_t numPoints, const FloatPoint* points, VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH));
+#ifdef OPENVG_VERSION_1_1
+ void drawText(VGFont, Vector<VGuint>& characters, VGfloat* adjustmentsX, VGfloat* adjustmentsY, const FloatPoint&);
+#endif
void scale(const FloatSize& scaleFactors);
void rotate(float radians);
void translate(float dx, float dy);
+ void beginPath();
+ void addPath(const Path&);
+ Path* currentPath() const;
+ void drawPath(VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH), WindRule fillRule = RULE_NONZERO);
+
void intersectClipRect(const FloatRect&);
+ void clipPath(const Path&, PainterOpenVG::ClipOperation, WindRule clipRule = RULE_NONZERO);
void save(PainterOpenVG::SaveMode saveMode = CreateNewState);
void restore();
@@ -114,6 +133,7 @@ private:
Vector<PlatformPainterState*> m_stateStack;
PlatformPainterState* m_state;
SurfaceOpenVG* m_surface;
+ Path* m_currentPath;
};
}
diff --git a/WebCore/platform/graphics/openvg/PathOpenVG.cpp b/WebCore/platform/graphics/openvg/PathOpenVG.cpp
new file mode 100644
index 0000000..2c366ee
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/PathOpenVG.cpp
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. 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 "Path.h"
+
+#include "AffineTransform.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "PainterOpenVG.h"
+#include "PlatformPathOpenVG.h"
+#include "PlatformString.h"
+#include "StrokeStyleApplier.h"
+#include "VGUtils.h"
+
+#include <openvg.h>
+#include <wtf/MathExtras.h>
+
+#define WEBKIT_VG_PATH_CAPABILITIES VG_PATH_CAPABILITY_ALL
+
+#define FUZZY_COMPARE(number, reference, delta) \
+ (number >= (reference - delta) && number <= (reference + delta))
+
+namespace WebCore {
+
+PlatformPathOpenVG::PlatformPathOpenVG()
+ : SharedResourceOpenVG()
+{
+ createPath();
+}
+
+PlatformPathOpenVG::PlatformPathOpenVG(const PlatformPathOpenVG& other)
+ : SharedResourceOpenVG()
+ , m_currentPoint(other.m_currentPoint)
+ , m_subpathStartPoint(other.m_subpathStartPoint)
+{
+ createPath();
+ // makeCompatibleContextCurrent() is called by createPath(), so not necessary here.
+ vgAppendPath(m_vgPath, other.m_vgPath);
+ ASSERT_VG_NO_ERROR();
+}
+
+PlatformPathOpenVG& PlatformPathOpenVG::operator=(const PlatformPathOpenVG& other)
+{
+ if (&other != this) {
+ clear();
+ // makeCompatibleContextCurrent() is called by clear(), so not necessary here.
+ vgAppendPath(m_vgPath, other.m_vgPath);
+ ASSERT_VG_NO_ERROR();
+ }
+ return *this;
+}
+
+PlatformPathOpenVG::~PlatformPathOpenVG()
+{
+ makeCompatibleContextCurrent();
+
+ vgDestroyPath(m_vgPath);
+ ASSERT_VG_NO_ERROR();
+}
+
+void PlatformPathOpenVG::clear()
+{
+ makeCompatibleContextCurrent();
+
+ vgClearPath(m_vgPath, WEBKIT_VG_PATH_CAPABILITIES);
+ ASSERT_VG_NO_ERROR();
+
+ m_subpathStartPoint.setX(0);
+ m_subpathStartPoint.setY(0);
+ m_currentPoint = m_subpathStartPoint;
+}
+
+void PlatformPathOpenVG::createPath()
+{
+ makeSharedContextCurrent();
+
+ m_vgPath = vgCreatePath(
+ VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
+ 1.0 /* scale */, 0.0 /* bias */,
+ 0 /* expected number of segments */,
+ 0 /* expected number of total coordinates */,
+ WEBKIT_VG_PATH_CAPABILITIES);
+ ASSERT_VG_NO_ERROR();
+}
+
+
+Path::Path()
+{
+ m_path = new PlatformPathOpenVG();
+}
+
+Path::~Path()
+{
+ delete m_path;
+}
+
+Path::Path(const Path& other)
+{
+ m_path = new PlatformPathOpenVG(*(other.m_path));
+}
+
+Path& Path::operator=(const Path& other)
+{
+ *m_path = *(other.m_path);
+ return *this;
+}
+
+bool Path::contains(const FloatPoint& point, WindRule rule) const
+{
+ notImplemented();
+
+ // OpenVG has no path-contains function, so for now we approximate by
+ // using the bounding rect of the path.
+ return boundingRect().contains(point);
+}
+
+bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
+{
+ notImplemented();
+
+ // OpenVG has no path-contains function, so for now we approximate by
+ // using the stroke bounding rect of the path.
+ return (const_cast<Path*>(this))->strokeBoundingRect().contains(point);
+}
+
+void Path::translate(const FloatSize& size)
+{
+ AffineTransform transformation;
+ transformation.translate(size.width(), size.height());
+ transform(transformation);
+}
+
+FloatRect Path::boundingRect() const
+{
+ VGfloat minX;
+ VGfloat minY;
+ VGfloat width;
+ VGfloat height;
+
+ m_path->makeCompatibleContextCurrent();
+ vgPathBounds(m_path->vgPath(), &minX, &minY, &width, &height);
+ ASSERT_VG_NO_ERROR();
+
+ return FloatRect(FloatPoint(minX, minY), FloatSize(width, height));
+}
+
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+{
+ notImplemented();
+
+ // vgPathBounds() ignores stroke parameters, and we don't currently have
+ // an approximation that takes stroke parameters into account.
+ return boundingRect();
+}
+
+void Path::moveTo(const FloatPoint& point)
+{
+ static const VGubyte pathSegments[] = { VG_MOVE_TO_ABS };
+ const VGfloat pathData[] = { point.x(), point.y() };
+
+ m_path->makeCompatibleContextCurrent();
+ vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData);
+ ASSERT_VG_NO_ERROR();
+
+ m_path->m_currentPoint = m_path->m_subpathStartPoint = point;
+}
+
+void Path::addLineTo(const FloatPoint& point)
+{
+ static const VGubyte pathSegments[] = { VG_LINE_TO_ABS };
+ const VGfloat pathData[] = { point.x(), point.y() };
+
+ m_path->makeCompatibleContextCurrent();
+ vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData);
+ ASSERT_VG_NO_ERROR();
+
+ m_path->m_currentPoint = point;
+}
+
+void Path::addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& endPoint)
+{
+ static const VGubyte pathSegments[] = { VG_QUAD_TO_ABS };
+ const VGfloat pathData[] = { controlPoint.x(), controlPoint.y(), endPoint.x(), endPoint.y() };
+
+ m_path->makeCompatibleContextCurrent();
+ vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData);
+ ASSERT_VG_NO_ERROR();
+
+ m_path->m_currentPoint = endPoint;
+}
+
+void Path::addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint)
+{
+ static const VGubyte pathSegments[] = { VG_CUBIC_TO_ABS };
+ const VGfloat pathData[] = { controlPoint1.x(), controlPoint1.y(), controlPoint2.x(), controlPoint2.y(), endPoint.x(), endPoint.y() };
+
+ m_path->makeCompatibleContextCurrent();
+ vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData);
+ ASSERT_VG_NO_ERROR();
+
+ m_path->m_currentPoint = endPoint;
+}
+
+void Path::addArcTo(const FloatPoint& point1, const FloatPoint& point2, float radius)
+{
+ // See http://philip.html5.org/tests/canvas/suite/tests/spec.html#arcto.
+
+ const FloatPoint& point0 = m_path->m_currentPoint;
+ if (!radius || point0 == point1 || point1 == point2) {
+ addLineTo(point1);
+ return;
+ }
+
+ FloatSize v01 = point0 - point1;
+ FloatSize v21 = point2 - point1;
+
+ // sin(A - B) = sin(A) * cos(B) - sin(B) * cos(A)
+ double cross = v01.width() * v21.height() - v01.height() * v21.width();
+
+ if (fabs(cross) < 1E-10) {
+ // on one line
+ addLineTo(point1);
+ return;
+ }
+
+ double d01 = hypot(v01.width(), v01.height());
+ double d21 = hypot(v21.width(), v21.height());
+ double angle = (piDouble - fabs(asin(cross / (d01 * d21)))) * 0.5;
+ double span = radius * tan(angle);
+ double rate = span / d01;
+ FloatPoint startPoint = FloatPoint(point1.x() + v01.width() * rate,
+ point1.y() + v01.height() * rate);
+ rate = span / d21;
+ FloatPoint endPoint = FloatPoint(point1.x() + v21.width() * rate,
+ point1.y() + v21.height() * rate);
+
+ // Fa: large arc flag, makes the difference between SCWARC_TO and LCWARC_TO
+ // respectively SCCWARC_TO and LCCWARC_TO arcs. We always use small
+ // arcs for arcTo(), as the arc is defined as the "shortest arc" of the
+ // circle specified in HTML 5.
+
+ // Fs: sweep flag, specifying whether the arc is drawn in increasing (true)
+ // or decreasing (0) direction.
+ const bool anticlockwise = cross < 0;
+
+ // Translate the large arc and sweep flags into an OpenVG segment command.
+ const VGubyte segmentCommand = anticlockwise ? VG_SCCWARC_TO_ABS : VG_SCWARC_TO_ABS;
+
+ const VGubyte pathSegments[] = {
+ VG_LINE_TO_ABS,
+ segmentCommand
+ };
+ const VGfloat pathData[] = {
+ startPoint.x(), startPoint.y(),
+ radius, radius, 0, endPoint.x(), endPoint.y()
+ };
+
+ m_path->makeCompatibleContextCurrent();
+ vgAppendPathData(m_path->vgPath(), 2, pathSegments, pathData);
+ ASSERT_VG_NO_ERROR();
+
+ m_path->m_currentPoint = endPoint;
+}
+
+void Path::closeSubpath()
+{
+ static const VGubyte pathSegments[] = { VG_CLOSE_PATH };
+ // pathData must not be 0, but certain compilers also don't create
+ // zero-size arrays. So let's use a random aligned value (sizeof(VGfloat)),
+ // it won't be accessed anyways as VG_CLOSE_PATH doesn't take coordinates.
+ static const VGfloat* pathData = reinterpret_cast<VGfloat*>(sizeof(VGfloat));
+
+ m_path->makeCompatibleContextCurrent();
+ vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData);
+ ASSERT_VG_NO_ERROR();
+
+ m_path->m_currentPoint = m_path->m_subpathStartPoint;
+}
+
+void Path::addArc(const FloatPoint& center, float radius, float startAngle, float endAngle, bool anticlockwise)
+{
+ // The OpenVG spec says nothing about inf as radius or start/end angle.
+ // WebKit seems to pass those (e.g. https://bugs.webkit.org/show_bug.cgi?id=16449),
+ // so abort instead of risking undefined behavior.
+ if (!isfinite(radius) || !isfinite(startAngle) || !isfinite(endAngle))
+ return;
+
+ // For some reason, the HTML 5 spec defines the angle as going clockwise
+ // from the positive X axis instead of going standard anticlockwise.
+ // So let's make it a proper angle in order to keep sanity.
+ startAngle = fmod((2.0 * piDouble) - startAngle, 2.0 * piDouble);
+ endAngle = fmod((2.0 * piDouble) - endAngle, 2.0 * piDouble);
+
+ // Make it so that endAngle > startAngle. fmod() above takes care of
+ // keeping the difference below 360 degrees.
+ if (endAngle <= startAngle)
+ endAngle += 2.0 * piDouble;
+
+ const VGfloat angleDelta = anticlockwise
+ ? (endAngle - startAngle)
+ : (startAngle - endAngle + (2.0 * piDouble));
+
+ // OpenVG uses endpoint parameterization while this method receives its
+ // values in center parameterization. It lacks an ellipse rotation
+ // parameter so we use 0 for that, and also the radius is only a single
+ // value which makes for rh == rv. In order to convert from endpoint to
+ // center parameterization, we use the formulas from the OpenVG/SVG specs:
+
+ // (x,y) = (cos rot, -sin rot; sin rot, -cos rot) * (rh * cos angle, rv * sin angle) + (center.x, center.y)
+ // rot is 0, which simplifies this a bit:
+ // (x,y) = (1, 0; 0, -1) * (rh * cos angle, rv * sin angle) + (center.x, center.y)
+ // = (1 * rh * cos angle + 0 * rv * sin angle, 0 * rh * cos angle + -1 * rv * sin angle) + (center.x, center.y)
+ // = (rh * cos angle, -rv * sin angle) + (center.x, center.y)
+ // (Set angle = {startAngle, endAngle} to retrieve the respective endpoints.)
+
+ const VGfloat startX = radius * cos(startAngle) + center.x();
+ const VGfloat startY = -radius * sin(startAngle) + center.y();
+ const VGfloat endX = radius * cos(endAngle) + center.x();
+ const VGfloat endY = -radius * sin(endAngle) + center.y();
+
+ // Fa: large arc flag, makes the difference between SCWARC_TO and LCWARC_TO
+ // respectively SCCWARC_TO and LCCWARC_TO arcs.
+ const bool largeArc = (angleDelta > piDouble);
+
+ // Fs: sweep flag, specifying whether the arc is drawn in increasing (true)
+ // or decreasing (0) direction. No need to calculate this value, as it
+ // we already get it passed as a parameter (Fs == !anticlockwise).
+
+ // Translate the large arc and sweep flags into an OpenVG segment command.
+ // As OpenVG thinks of everything upside down, we need to reverse the
+ // anticlockwise parameter in order to get the specified rotation.
+ const VGubyte segmentCommand = !anticlockwise
+ ? (largeArc ? VG_LCCWARC_TO_ABS : VG_SCCWARC_TO_ABS)
+ : (largeArc ? VG_LCWARC_TO_ABS : VG_SCWARC_TO_ABS);
+
+ // So now, we've got all the parameters in endpoint parameterization format
+ // as OpenVG requires it. Which means we can just pass it like this.
+ const VGubyte pathSegments[] = {
+ hasCurrentPoint() ? VG_LINE_TO_ABS : VG_MOVE_TO_ABS,
+ segmentCommand
+ };
+ const VGfloat pathData[] = {
+ startX, startY,
+ radius, radius, 0, endX, endY
+ };
+
+ m_path->makeCompatibleContextCurrent();
+ vgAppendPathData(m_path->vgPath(), 2, pathSegments, pathData);
+ ASSERT_VG_NO_ERROR();
+
+ m_path->m_currentPoint.setX(endX);
+ m_path->m_currentPoint.setY(endY);
+}
+
+void Path::addRect(const FloatRect& rect)
+{
+ static const VGubyte pathSegments[] = {
+ VG_MOVE_TO_ABS,
+ VG_HLINE_TO_REL,
+ VG_VLINE_TO_REL,
+ VG_HLINE_TO_REL,
+ VG_CLOSE_PATH
+ };
+ const VGfloat pathData[] = {
+ rect.x(), rect.y(),
+ rect.width(),
+ rect.height(),
+ -rect.width()
+ };
+
+ m_path->makeCompatibleContextCurrent();
+ vgAppendPathData(m_path->vgPath(), 5, pathSegments, pathData);
+ ASSERT_VG_NO_ERROR();
+
+ m_path->m_currentPoint = m_path->m_subpathStartPoint = rect.location();
+}
+
+void Path::addEllipse(const FloatRect& rect)
+{
+ static const VGubyte pathSegments[] = {
+ VG_MOVE_TO_ABS,
+ VG_SCCWARC_TO_REL,
+ VG_SCCWARC_TO_REL,
+ VG_CLOSE_PATH
+ };
+ const VGfloat pathData[] = {
+ rect.x() + rect.width() / 2.0, rect.y(),
+ rect.width() / 2.0, rect.height() / 2.0, 0, 0, rect.height(),
+ rect.width() / 2.0, rect.height() / 2.0, 0, 0, -rect.height()
+ };
+
+ m_path->makeCompatibleContextCurrent();
+ vgAppendPathData(m_path->vgPath(), 4, pathSegments, pathData);
+ ASSERT_VG_NO_ERROR();
+}
+
+void Path::clear()
+{
+ m_path->clear();
+}
+
+bool Path::isEmpty() const
+{
+ m_path->makeCompatibleContextCurrent();
+ return !vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS);
+}
+
+bool Path::hasCurrentPoint() const
+{
+ m_path->makeCompatibleContextCurrent();
+ return vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS) > 0;
+}
+
+String Path::debugString() const
+{
+ String debugString = "";
+
+ // OpenVG provides no means to retrieve path segment information.
+ // This is a bit unfortunate, we might need to store the segments in
+ // memory if we want to implement this function properly.
+ notImplemented();
+
+ return debugString;
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ // OpenVG provides no means to retrieve path segment information.
+ // This is *very* unfortunate, we might need to store the segments in
+ // memory if we want to implement this function properly.
+ // See http://www.khronos.org/message_boards/viewtopic.php?f=6&t=1887
+ notImplemented();
+}
+
+void Path::transform(const AffineTransform& transformation)
+{
+ PlatformPathOpenVG* dst = new PlatformPathOpenVG();
+ // dst->makeCompatibleContextCurrent() is called by the platform path
+ // constructor, therefore not necessary to call it again here.
+ PainterOpenVG::transformPath(dst->vgPath(), m_path->vgPath(), transformation);
+ delete m_path;
+ m_path = dst;
+
+ m_path->m_currentPoint = transform.mapPoint(m_path->m_currentPoint);
+ m_path->m_subpathStartPoint = transform.mapPoint(m_path->m_subpathStartPoint);
+}
+
+
+// Path::length(), Path::pointAtLength() and Path::normalAngleAtLength() are
+// reimplemented here instead of in Path.cpp, because OpenVG has its own
+// functions and Path::apply() doesn't really work as long as we rely on VGPath
+// as primary path storage.
+
+float Path::length()
+{
+ m_path->makeCompatibleContextCurrent();
+ VGfloat length = vgPathLength(m_path->vgPath(), 0, vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS));
+ ASSERT_VG_NO_ERROR();
+ return length;
+}
+
+FloatPoint Path::pointAtLength(float length, bool& ok)
+{
+ VGfloat x = 0, y = 0;
+ m_path->makeCompatibleContextCurrent();
+
+ vgPointAlongPath(m_path->vgPath(), 0, vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS),
+ length, &x, &y, 0, 0);
+ ok = (vgGetError() == VG_NO_ERROR);
+ return FloatPoint(x, y);
+}
+
+float Path::normalAngleAtLength(float length, bool& ok)
+{
+ VGfloat tangentX, tangentY;
+ m_path->makeCompatibleContextCurrent();
+
+ vgPointAlongPath(m_path->vgPath(), 0, vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS),
+ length, 0, 0, &tangentX, &tangentY);
+ ok = (vgGetError() == VG_NO_ERROR);
+ return atan2f(tangentY, tangentX) * 180.0 / piFloat; // convert to degrees
+}
+
+}
diff --git a/WebCore/platform/graphics/openvg/PlatformPathOpenVG.h b/WebCore/platform/graphics/openvg/PlatformPathOpenVG.h
new file mode 100644
index 0000000..286da53
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/PlatformPathOpenVG.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. 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 PlatformPathOpenVG_h
+#define PlatformPathOpenVG_h
+
+#include "FloatPoint.h"
+#include "SharedResourceOpenVG.h"
+
+#include <openvg.h>
+
+namespace WebCore {
+
+class PlatformPathOpenVG : public SharedResourceOpenVG {
+public:
+ PlatformPathOpenVG();
+ PlatformPathOpenVG(const PlatformPathOpenVG&);
+ ~PlatformPathOpenVG();
+
+ PlatformPathOpenVG& operator=(const PlatformPathOpenVG&);
+
+ VGPath vgPath() { return m_vgPath; }
+ void clear();
+
+public:
+ FloatPoint m_currentPoint;
+ FloatPoint m_subpathStartPoint;
+
+private:
+ void createPath();
+
+ VGPath m_vgPath;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/openvg/SharedResourceOpenVG.cpp b/WebCore/platform/graphics/openvg/SharedResourceOpenVG.cpp
new file mode 100644
index 0000000..a843db5
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/SharedResourceOpenVG.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009. 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 "SharedResourceOpenVG.h"
+
+#include "SurfaceOpenVG.h"
+
+#if PLATFORM(EGL)
+#include "EGLDisplayOpenVG.h"
+#endif
+
+namespace WebCore {
+
+void SharedResourceOpenVG::makeSharedContextCurrent()
+{
+#if PLATFORM(EGL)
+ EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent();
+#endif
+}
+
+void SharedResourceOpenVG::makeCompatibleContextCurrent()
+{
+#if PLATFORM(EGL)
+ EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCompatibleCurrent();
+#endif
+}
+
+}
diff --git a/WebCore/platform/graphics/openvg/SharedResourceOpenVG.h b/WebCore/platform/graphics/openvg/SharedResourceOpenVG.h
new file mode 100644
index 0000000..436ae90
--- /dev/null
+++ b/WebCore/platform/graphics/openvg/SharedResourceOpenVG.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009. 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 SharedResourceOpenVG_h
+#define SharedResourceOpenVG_h
+
+namespace WebCore {
+
+class SharedResourceOpenVG {
+public:
+ void makeSharedContextCurrent();
+ void makeCompatibleContextCurrent();
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp b/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp
index 9539f2c..6700c6f 100644
--- a/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp
+++ b/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp
@@ -64,6 +64,25 @@ SurfaceOpenVG::SurfaceOpenVG(const IntSize& size, const EGLDisplay& display, EGL
EGLDisplayOpenVG::registerPlatformSurface(this);
}
+SurfaceOpenVG::SurfaceOpenVG(EGLClientBuffer buffer, EGLenum bufferType, const EGLDisplay& display, EGLConfig* confPtr, EGLint* errorCode)
+ : m_activePainter(0)
+ , m_eglDisplay(display)
+ , m_eglSurface(EGL_NO_SURFACE)
+ , m_eglContext(EGL_NO_CONTEXT)
+{
+ ASSERT(m_eglDisplay != EGL_NO_DISPLAY);
+
+ EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay);
+ EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultPbufferConfig();
+ m_eglSurface = displayManager->createPbufferFromClientBuffer(buffer, bufferType, config, errorCode);
+
+ if (m_eglSurface == EGL_NO_SURFACE)
+ return;
+
+ m_eglContext = displayManager->contextForSurface(m_eglSurface);
+ EGLDisplayOpenVG::registerPlatformSurface(this);
+}
+
SurfaceOpenVG::SurfaceOpenVG(EGLNativeWindowType window, const EGLDisplay& display, EGLConfig* confPtr)
: m_activePainter(0)
, m_eglDisplay(display)
@@ -173,6 +192,11 @@ void SurfaceOpenVG::makeCurrent(MakeCurrentMode mode)
ASSERT_EGL_NO_ERROR();
if (currentSurface != m_eglSurface) {
+ // Save other context before switching over.
+ if (s_currentPainter && mode != DontSaveOrApplyPainterState
+ && s_currentPainter->surface()->m_eglSurface == currentSurface)
+ s_currentPainter->save(PainterOpenVG::KeepCurrentState);
+
eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
ASSERT_EGL_NO_ERROR();
s_currentPainter = 0;
@@ -202,6 +226,10 @@ void SurfaceOpenVG::makeCompatibleCurrent()
s_currentPainter = m_activePainter;
}
} else if (!EGLDisplayOpenVG::forDisplay(m_eglDisplay)->surfacesCompatible(currentSurface, m_eglSurface)) {
+ // Save other context before switching over.
+ if (s_currentPainter && s_currentPainter->surface()->m_eglSurface == currentSurface)
+ s_currentPainter->save(PainterOpenVG::KeepCurrentState);
+
eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
ASSERT_EGL_NO_ERROR();
s_currentPainter = 0;
diff --git a/WebCore/platform/graphics/openvg/SurfaceOpenVG.h b/WebCore/platform/graphics/openvg/SurfaceOpenVG.h
index dc288dd..46d1646 100644
--- a/WebCore/platform/graphics/openvg/SurfaceOpenVG.h
+++ b/WebCore/platform/graphics/openvg/SurfaceOpenVG.h
@@ -25,7 +25,6 @@
#endif
#include <wtf/Noncopyable.h>
-#include <wtf/Platform.h>
namespace WebCore {
@@ -48,6 +47,7 @@ public:
enum MakeCurrentMode {
ApplyPainterStateOnSurfaceSwitch,
DontApplyPainterState,
+ DontSaveOrApplyPainterState
};
static SurfaceOpenVG* currentSurface();
@@ -68,6 +68,26 @@ public:
SurfaceOpenVG(const IntSize& size, const EGLDisplay& display, EGLConfig* config = 0, EGLint* errorCode = 0);
/**
+ * Create a new EGL pbuffer surface that will be bound to the given
+ * client buffer (read: VGImage), with the specified config on the
+ * given display. If config is not specified, the display's default
+ * pbuffer config is used.
+ *
+ * After the surface is created, you will only be able to access the
+ * client buffer image if the surface is not current. The recommended way
+ * to ensure this is to call surface->sharedSurface()->makeCurrent() if you
+ * simply want to access the image's pixel contents, or if you intend to
+ * draw the image directly, making the draw target surface current.
+ *
+ * This constructor will trigger an assertion if creation of the surface
+ * fails, unless you pledge to manually process the error code by passing
+ * a non-zero pointer as errorCode parameter. The error code returned by
+ * eglGetError() will be written to that variable.
+ */
+ SurfaceOpenVG(EGLClientBuffer buffer, EGLenum bufferType,
+ const EGLDisplay& display, EGLConfig* config = 0, EGLint* errorCode = 0);
+
+ /**
* Create a new EGL window surface with the specified native window handle
* and config on the given display. If config is not specified, the
* display's default window config is used.
diff --git a/WebCore/platform/graphics/openvg/VGUtils.cpp b/WebCore/platform/graphics/openvg/VGUtils.cpp
index 72ba5b2..ce9bcd2 100644
--- a/WebCore/platform/graphics/openvg/VGUtils.cpp
+++ b/WebCore/platform/graphics/openvg/VGUtils.cpp
@@ -20,6 +20,7 @@
#include "config.h"
#include "VGUtils.h"
+#include "AffineTransform.h"
#include "FloatRect.h"
#include "TransformationMatrix.h"
@@ -38,6 +39,19 @@ VGMatrix::VGMatrix(const VGfloat data[9])
m_data[8] = data[8];
}
+VGMatrix::VGMatrix(const AffineTransform& transformation)
+{
+ m_data[0] = transformation.a();
+ m_data[1] = transformation.b();
+ m_data[2] = 0;
+ m_data[3] = transformation.c();
+ m_data[4] = transformation.d();
+ m_data[5] = 0;
+ m_data[6] = transformation.e();
+ m_data[7] = transformation.f();
+ m_data[8] = 1;
+}
+
VGMatrix::VGMatrix(const TransformationMatrix& matrix)
{
m_data[0] = matrix.m11();
@@ -51,21 +65,30 @@ VGMatrix::VGMatrix(const TransformationMatrix& matrix)
m_data[8] = matrix.m44();
}
+VGMatrix::operator AffineTransform() const
+{
+ AffineTransform transformation(
+ m_data[0], m_data[1],
+ m_data[3], m_data[4],
+ m_data[6], m_data[7]);
+ return transformation;
+}
+
VGMatrix::operator TransformationMatrix() const
{
- TransformationMatrix matrix;
- matrix.setM11(m_data[0]);
- matrix.setM12(m_data[1]);
- matrix.setM14(m_data[2]);
- matrix.setM21(m_data[3]);
- matrix.setM22(m_data[4]);
- matrix.setM24(m_data[5]);
- matrix.setM41(m_data[6]);
- matrix.setM42(m_data[7]);
- matrix.setM44(m_data[8]);
+ TransformationMatrix matrix(
+ m_data[0], m_data[1], 0, m_data[2],
+ m_data[3], m_data[4], 0, m_data[5],
+ 0, 0, 1, 0,
+ m_data[6], m_data[7], 0, m_data[8]);
return matrix;
}
+AffineTransform::operator VGMatrix() const
+{
+ return VGMatrix(*this);
+}
+
TransformationMatrix::operator VGMatrix() const
{
return VGMatrix(*this);
diff --git a/WebCore/platform/graphics/openvg/VGUtils.h b/WebCore/platform/graphics/openvg/VGUtils.h
index 083c15a..3a290cb 100644
--- a/WebCore/platform/graphics/openvg/VGUtils.h
+++ b/WebCore/platform/graphics/openvg/VGUtils.h
@@ -59,14 +59,17 @@ static inline const char* toVGErrorConstant(VGErrorCode error)
namespace WebCore {
+class AffineTransform;
class FloatRect;
class TransformationMatrix;
class VGMatrix {
public:
VGMatrix(const VGfloat data[9]);
+ VGMatrix(const AffineTransform&);
VGMatrix(const TransformationMatrix&);
const VGfloat* toVGfloat() const { return m_data; }
+ operator AffineTransform() const;
operator TransformationMatrix() const;
private:
VGfloat m_data[9];
diff --git a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
index 0a1075f..0565deb 100644
--- a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
+++ b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
@@ -58,6 +58,9 @@ FontPlatformData::FontPlatformData(const FontDescription& description, const Ato
font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
const bool smallCaps = description.smallCaps();
font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ font.setStyleStrategy(QFont::ForceIntegerMetrics);
+#endif
m_data->bold = font.bold();
m_data->size = font.pointSizeF();
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index 9ff7c1a..974c179 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- Copyright (C) 2008 Holger Hans Peter Freyther
+ Copyright (C) 2008, 2010 Holger Hans Peter Freyther
Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
This library is free software; you can redistribute it and/or
@@ -134,7 +134,7 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float
clip.adjust(dx1, dx2, dy1, dy2);
}
p->save();
- p->setClipRect(clip.toRect());
+ p->setClipRect(clip.toRect(), Qt::IntersectClip);
QPointF pt(point.x(), point.y() - ascent);
if (hasShadow) {
p->save();
@@ -169,17 +169,24 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float
p->drawText(pt, string, flags, run.padding());
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
{
if (!run.length())
return 0;
+ if (run.length() == 1 && treatAsSpace(run[0]))
+ return QFontMetrics(font()).width(run[0]) - m_wordSpacing + run.padding();
+
String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
QString string = fromRawDataWithoutRef(sanitized);
QTextLayout layout(string, font());
QTextLine line = setupLayout(&layout, run);
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ int w = int(line.horizontalAdvance());
+#else
int w = int(line.naturalTextWidth());
+#endif
// WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
if (treatAsSpace(run[0]))
w -= m_wordSpacing;
@@ -216,8 +223,10 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint&
QFont Font::font() const
{
QFont f = primaryFont()->getQtFont();
- f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing);
- f.setWordSpacing(m_wordSpacing);
+ if (m_letterSpacing != 0)
+ f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing);
+ if (m_wordSpacing != 0)
+ f.setWordSpacing(m_wordSpacing);
return f;
}
diff --git a/WebCore/platform/graphics/qt/GradientQt.cpp b/WebCore/platform/graphics/qt/GradientQt.cpp
index 9b9acc2..8b9e2d7 100644
--- a/WebCore/platform/graphics/qt/GradientQt.cpp
+++ b/WebCore/platform/graphics/qt/GradientQt.cpp
@@ -51,6 +51,8 @@ QGradient* Gradient::platformGradient()
else
m_gradient = new QLinearGradient(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y());
+ sortStopsIfNecessary();
+
QColor stopColor;
Vector<ColorStop>::iterator stopIterator = m_stops.begin();
qreal lastStop(0.0);
@@ -64,9 +66,17 @@ QGradient* Gradient::platformGradient()
if (m_radial && m_r0)
lastStop = m_r0 / m_r1 + lastStop * (1.0f - m_r0 / m_r1);
m_gradient->setColorAt(lastStop, stopColor);
+ // Keep the lastStop as orginal value, since the following stopColor depend it
+ lastStop = stopIterator->stop;
++stopIterator;
}
+ if (m_stops.isEmpty()) {
+ // The behavior of QGradient with no stops is defined differently from HTML5 spec,
+ // where the latter requires the gradient to be transparent black.
+ m_gradient->setColorAt(0.0, QColor(0, 0, 0, 0));
+ }
+
switch (m_spreadMethod) {
case SpreadMethodPad:
m_gradient->setSpread(QGradient::PadSpread);
diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
new file mode 100644
index 0000000..b0dd289
--- /dev/null
+++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -0,0 +1,1651 @@
+/*
+ Copyright (C) 2010 Tieto Corporation.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "config.h"
+
+#include "GraphicsContext3D.h"
+
+#include "CanvasObject.h"
+#include "GraphicsContext.h"
+#include "HTMLCanvasElement.h"
+#include "HostWindow.h"
+#include "ImageBuffer.h"
+#include "NotImplemented.h"
+#include "QWebPageClient.h"
+#include "WebGLActiveInfo.h"
+#include "WebGLArray.h"
+#include "WebGLBuffer.h"
+#include "WebGLFloatArray.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLIntArray.h"
+#include "WebGLProgram.h"
+#include "WebGLRenderbuffer.h"
+#include "WebGLRenderingContext.h"
+#include "WebGLShader.h"
+#include "WebGLTexture.h"
+#include "WebGLUnsignedByteArray.h"
+#include <QAbstractScrollArea>
+#include <wtf/UnusedParam.h>
+#include <wtf/text/CString.h>
+
+#if ENABLE(3D_CANVAS)
+
+namespace WebCore {
+
+#if !defined(GLchar)
+typedef char GLchar;
+#endif
+
+#if !defined(APIENTRY)
+#define APIENTRY
+#endif
+
+typedef ptrdiff_t GLsizeiptrType;
+typedef ptrdiff_t GLintptrType;
+
+typedef void (APIENTRY* glActiveTextureType) (GLenum);
+typedef void (APIENTRY* glAttachShaderType) (GLuint, GLuint);
+typedef void (APIENTRY* glBindAttribLocationType) (GLuint, GLuint, const char*);
+typedef void (APIENTRY* glBindBufferType) (GLenum, GLuint);
+typedef void (APIENTRY* glBindFramebufferType) (GLenum, GLuint);
+typedef void (APIENTRY* glBindRenderbufferType) (GLenum, GLuint);
+typedef void (APIENTRY* glBlendColorType) (GLclampf, GLclampf, GLclampf, GLclampf);
+typedef void (APIENTRY* glBlendEquationType) (GLenum);
+typedef void (APIENTRY* glBlendEquationSeparateType)(GLenum, GLenum);
+typedef void (APIENTRY* glBlendFuncSeparateType)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (APIENTRY* glBufferDataType) (GLenum, GLsizeiptrType, const GLvoid*, GLenum);
+typedef void (APIENTRY* glBufferSubDataType) (GLenum, GLintptrType, GLsizeiptrType, const GLvoid*);
+typedef GLenum (APIENTRY* glCheckFramebufferStatusType) (GLenum);
+typedef void (APIENTRY* glCompileShaderType) (GLuint);
+typedef GLuint (APIENTRY* glCreateProgramType) ();
+typedef GLuint (APIENTRY* glCreateShaderType) (GLenum);
+typedef void (APIENTRY* glDeleteBuffersType) (GLsizei, const GLuint*);
+typedef void (APIENTRY* glDeleteFramebuffersType) (GLsizei n, const GLuint*);
+typedef void (APIENTRY* glDeleteProgramType) (GLuint);
+typedef void (APIENTRY* glDeleteRenderbuffersType) (GLsizei n, const GLuint*);
+typedef void (APIENTRY* glDeleteShaderType) (GLuint);
+typedef void (APIENTRY* glDetachShaderType) (GLuint, GLuint);
+typedef void (APIENTRY* glDisableVertexAttribArrayType) (GLuint);
+typedef void (APIENTRY* glEnableVertexAttribArrayType) (GLuint);
+typedef void (APIENTRY* glFramebufferRenderbufferType) (GLenum, GLenum, GLenum, GLuint);
+typedef void (APIENTRY* glFramebufferTexture2DType) (GLenum, GLenum, GLenum, GLuint, GLint);
+typedef void (APIENTRY* glGenBuffersType) (GLsizei, GLuint*);
+typedef void (APIENTRY* glGenerateMipmapType) (GLenum target);
+typedef void (APIENTRY* glGenFramebuffersType) (GLsizei, GLuint*);
+typedef void (APIENTRY* glGenRenderbuffersType) (GLsizei, GLuint*);
+typedef void (APIENTRY* glGetActiveAttribType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
+typedef void (APIENTRY* glGetActiveUniformType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
+typedef GLint (APIENTRY* glGetAttribLocationType) (GLuint, const char*);
+typedef void (APIENTRY* glGetBufferParameterivType) (GLenum, GLenum, GLint*);
+typedef void (APIENTRY* glGetFramebufferAttachmentParameterivType) (GLenum, GLenum, GLenum, GLint* params);
+typedef void (APIENTRY* glGetProgramInfoLogType) (GLuint, GLsizei, GLsizei*, char*);
+typedef void (APIENTRY* glGetProgramivType) (GLuint, GLenum, GLint*);
+typedef void (APIENTRY* glGetRenderbufferParameterivType) (GLenum, GLenum, GLint*);
+typedef void (APIENTRY* glGetShaderInfoLogType) (GLuint, GLsizei, GLsizei*, char*);
+typedef void (APIENTRY* glGetShaderivType) (GLuint, GLenum, GLint*);
+typedef void (APIENTRY* glGetShaderSourceType) (GLuint, GLsizei, GLsizei*, char*);
+typedef GLint (APIENTRY* glGetUniformLocationType) (GLuint, const char*);
+typedef void (APIENTRY* glGetUniformfvType) (GLuint, GLint, GLfloat*);
+typedef void (APIENTRY* glGetUniformivType) (GLuint, GLint, GLint*);
+typedef void (APIENTRY* glGetVertexAttribfvType) (GLuint, GLenum, GLfloat*);
+typedef void (APIENTRY* glGetVertexAttribivType) (GLuint, GLenum, GLint*);
+typedef void (APIENTRY* glGetVertexAttribPointervType) (GLuint, GLenum, GLvoid**);
+typedef GLboolean (APIENTRY* glIsBufferType) (GLuint);
+typedef GLboolean (APIENTRY* glIsFramebufferType) (GLuint);
+typedef GLboolean (APIENTRY* glIsProgramType) (GLuint);
+typedef GLboolean (APIENTRY* glIsRenderbufferType) (GLuint);
+typedef GLboolean (APIENTRY* glIsShaderType) (GLuint);
+typedef void (APIENTRY* glLinkProgramType) (GLuint);
+typedef void (APIENTRY* glRenderbufferStorageType) (GLenum, GLenum, GLsizei, GLsizei);
+typedef void (APIENTRY* glSampleCoverageType) (GLclampf, GLboolean);
+typedef void (APIENTRY* glShaderSourceType) (GLuint, GLsizei, const char**, const GLint*);
+typedef void (APIENTRY* glStencilFuncSeparateType) (GLenum, GLenum, GLint, GLuint);
+typedef void (APIENTRY* glStencilMaskSeparateType) (GLenum, GLuint);
+typedef void (APIENTRY* glStencilOpSeparateType) (GLenum, GLenum, GLenum, GLenum);
+typedef void (APIENTRY* glUniform1fType) (GLint, GLfloat);
+typedef void (APIENTRY* glUniform1fvType) (GLint, GLsizei, const GLfloat*);
+typedef void (APIENTRY* glUniform1iType) (GLint, GLint);
+typedef void (APIENTRY* glUniform1ivType) (GLint, GLsizei, const GLint*);
+typedef void (APIENTRY* glUniform2fType) (GLint, GLfloat, GLfloat);
+typedef void (APIENTRY* glUniform2fvType) (GLint, GLsizei, const GLfloat*);
+typedef void (APIENTRY* glUniform2iType) (GLint, GLint, GLint);
+typedef void (APIENTRY* glUniform2ivType) (GLint, GLsizei, const GLint*);
+typedef void (APIENTRY* glUniform3fType) (GLint, GLfloat, GLfloat, GLfloat);
+typedef void (APIENTRY* glUniform3fvType) (GLint, GLsizei, const GLfloat*);
+typedef void (APIENTRY* glUniform3iType) (GLint, GLint, GLint, GLint);
+typedef void (APIENTRY* glUniform3ivType) (GLint, GLsizei, const GLint*);
+typedef void (APIENTRY* glUniform4fType) (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (APIENTRY* glUniform4fvType) (GLint, GLsizei, const GLfloat*);
+typedef void (APIENTRY* glUniform4iType) (GLint, GLint, GLint, GLint, GLint);
+typedef void (APIENTRY* glUniform4ivType) (GLint, GLsizei, const GLint*);
+typedef void (APIENTRY* glUniformMatrix2fvType) (GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRY* glUniformMatrix3fvType) (GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRY* glUniformMatrix4fvType) (GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRY* glUseProgramType) (GLuint);
+typedef void (APIENTRY* glValidateProgramType) (GLuint);
+typedef void (APIENTRY* glVertexAttrib1fType) (GLuint, const GLfloat);
+typedef void (APIENTRY* glVertexAttrib1fvType) (GLuint, const GLfloat*);
+typedef void (APIENTRY* glVertexAttrib2fType) (GLuint, const GLfloat, const GLfloat);
+typedef void (APIENTRY* glVertexAttrib2fvType) (GLuint, const GLfloat*);
+typedef void (APIENTRY* glVertexAttrib3fType) (GLuint, const GLfloat, const GLfloat, const GLfloat);
+typedef void (APIENTRY* glVertexAttrib3fvType) (GLuint, const GLfloat*);
+typedef void (APIENTRY* glVertexAttrib4fType) (GLuint, const GLfloat, const GLfloat, const GLfloat, const GLfloat);
+typedef void (APIENTRY* glVertexAttrib4fvType) (GLuint, const GLfloat*);
+typedef void (APIENTRY* glVertexAttribPointerType) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*);
+
+class GraphicsContext3DInternal {
+public:
+ GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow);
+ ~GraphicsContext3DInternal();
+
+ bool isContextValid() { return m_contextValid; }
+
+
+
+ glActiveTextureType activeTexture;
+ glAttachShaderType attachShader;
+ glBindAttribLocationType bindAttribLocation;
+ glBindBufferType bindBuffer;
+ glBindFramebufferType bindFramebuffer;
+ glBindRenderbufferType bindRenderbuffer;
+ glBlendColorType blendColor;
+ glBlendEquationType blendEquation;
+ glBlendEquationSeparateType blendEquationSeparate;
+ glBlendFuncSeparateType blendFuncSeparate;
+ glBufferDataType bufferData;
+ glBufferSubDataType bufferSubData;
+ glCheckFramebufferStatusType checkFramebufferStatus;
+ glCompileShaderType compileShader;
+ glCreateProgramType createProgram;
+ glCreateShaderType createShader;
+ glDeleteBuffersType deleteBuffers;
+ glDeleteFramebuffersType deleteFramebuffers;
+ glDeleteProgramType deleteProgram;
+ glDeleteRenderbuffersType deleteRenderbuffers;
+ glDeleteShaderType deleteShader;
+ glDetachShaderType detachShader;
+ glDisableVertexAttribArrayType disableVertexAttribArray;
+ glEnableVertexAttribArrayType enableVertexAttribArray;
+ glFramebufferRenderbufferType framebufferRenderbuffer;
+ glFramebufferTexture2DType framebufferTexture2D;
+ glGenBuffersType genBuffers;
+ glGenerateMipmapType generateMipmap;
+ glGenFramebuffersType genFramebuffers;
+ glGenRenderbuffersType genRenderbuffers;
+ glGetActiveAttribType getActiveAttrib;
+ glGetActiveUniformType getActiveUniform;
+ glGetAttribLocationType getAttribLocation;
+ glGetBufferParameterivType getBufferParameteriv;
+ glGetFramebufferAttachmentParameterivType getFramebufferAttachmentParameteriv;
+ glGetProgramInfoLogType getProgramInfoLog;
+ glGetProgramivType getProgramiv;
+ glGetRenderbufferParameterivType getRenderbufferParameteriv;
+ glGetShaderInfoLogType getShaderInfoLog;
+ glGetShaderivType getShaderiv;
+ glGetShaderSourceType getShaderSource;
+ glGetUniformfvType getUniformfv;
+ glGetUniformivType getUniformiv;
+ glGetUniformLocationType getUniformLocation;
+ glGetVertexAttribfvType getVertexAttribfv;
+ glGetVertexAttribivType getVertexAttribiv;
+ glGetVertexAttribPointervType getVertexAttribPointerv;
+ glIsBufferType isBuffer;
+ glIsFramebufferType isFramebuffer;
+ glIsProgramType isProgram;
+ glIsRenderbufferType isRenderbuffer;
+ glIsShaderType isShader;
+ glLinkProgramType linkProgram;
+ glRenderbufferStorageType renderbufferStorage;
+ glSampleCoverageType sampleCoverage;
+ glShaderSourceType shaderSource;
+ glStencilFuncSeparateType stencilFuncSeparate;
+ glStencilMaskSeparateType stencilMaskSeparate;
+ glStencilOpSeparateType stencilOpSeparate;
+ glUniform1fType uniform1f;
+ glUniform1fvType uniform1fv;
+ glUniform1iType uniform1i;
+ glUniform1ivType uniform1iv;
+ glUniform2fType uniform2f;
+ glUniform2fvType uniform2fv;
+ glUniform2iType uniform2i;
+ glUniform2ivType uniform2iv;
+ glUniform3fType uniform3f;
+ glUniform3fvType uniform3fv;
+ glUniform3iType uniform3i;
+ glUniform3ivType uniform3iv;
+ glUniform4fType uniform4f;
+ glUniform4fvType uniform4fv;
+ glUniform4iType uniform4i;
+ glUniform4ivType uniform4iv;
+ glUniformMatrix2fvType uniformMatrix2fv;
+ glUniformMatrix3fvType uniformMatrix3fv;
+ glUniformMatrix4fvType uniformMatrix4fv;
+ glUseProgramType useProgram;
+ glValidateProgramType validateProgram;
+ glVertexAttrib1fType vertexAttrib1f;
+ glVertexAttrib1fvType vertexAttrib1fv;
+ glVertexAttrib2fType vertexAttrib2f;
+ glVertexAttrib2fvType vertexAttrib2fv;
+ glVertexAttrib3fType vertexAttrib3f;
+ glVertexAttrib3fvType vertexAttrib3fv;
+ glVertexAttrib4fType vertexAttrib4f;
+ glVertexAttrib4fvType vertexAttrib4fv;
+ glVertexAttribPointerType vertexAttribPointer;
+
+ GraphicsContext3D::Attributes m_attrs;
+ QGLWidget* m_glWidget;
+ GLuint m_texture;
+ GLuint m_mainFbo;
+ GLuint m_currentFbo;
+ GLuint m_depthBuffer;
+ QImage m_pixels;
+ ListHashSet<unsigned long> m_syntheticErrors;
+
+private:
+
+ QGLWidget* getOwnerGLWidget(QWebPageClient* webPageClient);
+ void* getProcAddress(const String& proc);
+ bool m_contextValid;
+};
+
+#if defined (QT_OPENGL_ES_2)
+#define GET_PROC_ADDRESS(Proc) Proc
+#else
+#define GET_PROC_ADDRESS(Proc) reinterpret_cast<Proc##Type>(getProcAddress(#Proc));
+#endif
+
+GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow)
+ : m_attrs(attrs)
+ , m_glWidget(0)
+ , m_texture(0)
+ , m_mainFbo(0)
+ , m_currentFbo(0)
+ , m_depthBuffer(0)
+ , m_contextValid(true)
+{
+ QWebPageClient* webPageClient = hostWindow->platformPageClient();
+ QGLWidget* ownerGLWidget = getOwnerGLWidget(webPageClient);
+
+ if (ownerGLWidget)
+ m_glWidget = new QGLWidget(0, ownerGLWidget);
+ else {
+ QGLFormat format;
+ format.setDepth(true);
+ format.setSampleBuffers(true);
+ format.setStencil(false);
+
+ m_glWidget = new QGLWidget(format);
+ }
+
+ if (!m_glWidget->isValid()) {
+ LOG_ERROR("GraphicsContext3D: QGLWidget does not have a valid context");
+ m_contextValid = false;
+ return;
+ }
+
+ QGLFormat format = m_glWidget->format();
+
+ m_attrs.alpha = format.alpha();
+ m_attrs.depth = format.depth();
+ m_attrs.stencil = format.stencil();
+ m_attrs.antialias = false;
+ m_attrs.premultipliedAlpha = true;
+
+ m_glWidget->makeCurrent();
+
+ activeTexture = GET_PROC_ADDRESS(glActiveTexture);
+ attachShader = GET_PROC_ADDRESS(glAttachShader);
+ bindAttribLocation = GET_PROC_ADDRESS(glBindAttribLocation);
+ bindBuffer = GET_PROC_ADDRESS(glBindBuffer);
+ bindFramebuffer = GET_PROC_ADDRESS(glBindFramebuffer);
+ bindRenderbuffer = GET_PROC_ADDRESS(glBindRenderbuffer);
+ blendColor = GET_PROC_ADDRESS(glBlendColor);
+ blendEquation = GET_PROC_ADDRESS(glBlendEquation);
+ blendEquationSeparate = GET_PROC_ADDRESS(glBlendEquationSeparate);
+ blendFuncSeparate = GET_PROC_ADDRESS(glBlendFuncSeparate);
+ bufferData = GET_PROC_ADDRESS(glBufferData);
+ bufferSubData = GET_PROC_ADDRESS(glBufferSubData);
+ checkFramebufferStatus = GET_PROC_ADDRESS(glCheckFramebufferStatus);
+ compileShader = GET_PROC_ADDRESS(glCompileShader);
+ createProgram = GET_PROC_ADDRESS(glCreateProgram);
+ createShader = GET_PROC_ADDRESS(glCreateShader);
+ deleteBuffers = GET_PROC_ADDRESS(glDeleteBuffers);
+ deleteFramebuffers = GET_PROC_ADDRESS(glDeleteFramebuffers);
+ deleteProgram = GET_PROC_ADDRESS(glDeleteProgram);
+ deleteRenderbuffers = GET_PROC_ADDRESS(glDeleteRenderbuffers);
+ deleteShader = GET_PROC_ADDRESS(glDeleteShader);
+ detachShader = GET_PROC_ADDRESS(glDetachShader);
+ disableVertexAttribArray = GET_PROC_ADDRESS(glDisableVertexAttribArray);
+ enableVertexAttribArray = GET_PROC_ADDRESS(glEnableVertexAttribArray);
+ framebufferRenderbuffer = GET_PROC_ADDRESS(glFramebufferRenderbuffer);
+ framebufferTexture2D = GET_PROC_ADDRESS(glFramebufferTexture2D);
+ genBuffers = GET_PROC_ADDRESS(glGenBuffers);
+ generateMipmap = GET_PROC_ADDRESS(glGenerateMipmap);
+ genFramebuffers = GET_PROC_ADDRESS(glGenFramebuffers);
+ genRenderbuffers = GET_PROC_ADDRESS(glGenRenderbuffers);
+ getActiveAttrib = GET_PROC_ADDRESS(glGetActiveAttrib);
+ getActiveUniform = GET_PROC_ADDRESS(glGetActiveUniform);
+ getAttribLocation = GET_PROC_ADDRESS(glGetAttribLocation);
+ getBufferParameteriv = GET_PROC_ADDRESS(glGetBufferParameteriv);
+ getFramebufferAttachmentParameteriv = GET_PROC_ADDRESS(glGetFramebufferAttachmentParameteriv);
+ getProgramInfoLog = GET_PROC_ADDRESS(glGetProgramInfoLog);
+ getProgramiv = GET_PROC_ADDRESS(glGetProgramiv);
+ getRenderbufferParameteriv = GET_PROC_ADDRESS(glGetRenderbufferParameteriv);
+ getShaderInfoLog = GET_PROC_ADDRESS(glGetShaderInfoLog);
+ getShaderiv = GET_PROC_ADDRESS(glGetShaderiv);
+ getShaderSource = GET_PROC_ADDRESS(glGetShaderSource);
+ getUniformfv = GET_PROC_ADDRESS(glGetUniformfv);
+ getUniformiv = GET_PROC_ADDRESS(glGetUniformiv);
+ getUniformLocation = GET_PROC_ADDRESS(glGetUniformLocation);
+ getVertexAttribfv = GET_PROC_ADDRESS(glGetVertexAttribfv);
+ getVertexAttribiv = GET_PROC_ADDRESS(glGetVertexAttribiv);
+ getVertexAttribPointerv = GET_PROC_ADDRESS(glGetVertexAttribPointerv);
+ isBuffer = GET_PROC_ADDRESS(glIsBuffer);
+ isFramebuffer = GET_PROC_ADDRESS(glIsFramebuffer);
+ isProgram = GET_PROC_ADDRESS(glIsProgram);
+ isRenderbuffer = GET_PROC_ADDRESS(glIsRenderbuffer);
+ isShader = GET_PROC_ADDRESS(glIsShader);
+ linkProgram = GET_PROC_ADDRESS(glLinkProgram);
+ renderbufferStorage = GET_PROC_ADDRESS(glRenderbufferStorage);
+ sampleCoverage = GET_PROC_ADDRESS(glSampleCoverage);
+ shaderSource = GET_PROC_ADDRESS(glShaderSource);
+ stencilFuncSeparate = GET_PROC_ADDRESS(glStencilFuncSeparate);
+ stencilMaskSeparate = GET_PROC_ADDRESS(glStencilMaskSeparate);
+ stencilOpSeparate = GET_PROC_ADDRESS(glStencilOpSeparate);
+ uniform1f = GET_PROC_ADDRESS(glUniform1f);
+ uniform1fv = GET_PROC_ADDRESS(glUniform1fv);
+ uniform1i = GET_PROC_ADDRESS(glUniform1i);
+ uniform1iv = GET_PROC_ADDRESS(glUniform1iv);
+ uniform2f = GET_PROC_ADDRESS(glUniform2f);
+ uniform2fv = GET_PROC_ADDRESS(glUniform2fv);
+ uniform2i = GET_PROC_ADDRESS(glUniform2i);
+ uniform2iv = GET_PROC_ADDRESS(glUniform2iv);
+ uniform3f = GET_PROC_ADDRESS(glUniform3f);
+ uniform3fv = GET_PROC_ADDRESS(glUniform3fv);
+ uniform3i = GET_PROC_ADDRESS(glUniform3i);
+ uniform3iv = GET_PROC_ADDRESS(glUniform3iv);
+ uniform4f = GET_PROC_ADDRESS(glUniform4f);
+ uniform4fv = GET_PROC_ADDRESS(glUniform4fv);
+ uniform4i = GET_PROC_ADDRESS(glUniform4i);
+ uniform4iv = GET_PROC_ADDRESS(glUniform4iv);
+ uniformMatrix2fv = GET_PROC_ADDRESS(glUniformMatrix2fv);
+ uniformMatrix3fv = GET_PROC_ADDRESS(glUniformMatrix3fv);
+ uniformMatrix4fv = GET_PROC_ADDRESS(glUniformMatrix4fv);
+ useProgram = GET_PROC_ADDRESS(glUseProgram);
+ validateProgram = GET_PROC_ADDRESS(glValidateProgram);
+ vertexAttrib1f = GET_PROC_ADDRESS(glVertexAttrib1f);
+ vertexAttrib1fv = GET_PROC_ADDRESS(glVertexAttrib1fv);
+ vertexAttrib2f = GET_PROC_ADDRESS(glVertexAttrib2f);
+ vertexAttrib2fv = GET_PROC_ADDRESS(glVertexAttrib2fv);
+ vertexAttrib3f = GET_PROC_ADDRESS(glVertexAttrib3f);
+ vertexAttrib3fv = GET_PROC_ADDRESS(glVertexAttrib3fv);
+ vertexAttrib4f = GET_PROC_ADDRESS(glVertexAttrib4f);
+ vertexAttrib4fv = GET_PROC_ADDRESS(glVertexAttrib4fv);
+ vertexAttribPointer = GET_PROC_ADDRESS(glVertexAttribPointer);
+
+ if (!m_contextValid) {
+ LOG_ERROR("GraphicsContext3D: All needed OpenGL extensions are not available");
+ m_contextValid = false;
+ return;
+ }
+
+ glGenTextures(1, &m_texture);
+ glBindTexture(GraphicsContext3D::TEXTURE_2D, m_texture);
+ glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
+ glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
+ glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+ glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+ glTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+ glBindTexture(GraphicsContext3D::TEXTURE_2D, 0);
+
+ genFramebuffers(/* count */ 1, &m_mainFbo);
+ m_currentFbo = m_mainFbo;
+
+ bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_mainFbo);
+
+ genRenderbuffers(/* count */ 1, &m_depthBuffer);
+ bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
+#if defined(QT_OPENGL_ES_2)
+ renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, /* width */ 1, /* height */ 1);
+#else
+ renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, /* width */ 1, /* height */ 1);
+#endif
+
+ bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
+
+ framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_texture, 0);
+ framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
+ glClearColor(/* red */ 0, /* green */ 0, /* blue */ 0, /* alpha */ 0);
+
+ if (checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
+ LOG_ERROR("GraphicsContext3D: Wasn't able to create the main framebuffer");
+ m_contextValid = false;
+ }
+}
+
+GraphicsContext3DInternal::~GraphicsContext3DInternal()
+{
+ delete m_glWidget;
+ m_glWidget = 0;
+}
+
+QGLWidget* GraphicsContext3DInternal::getOwnerGLWidget(QWebPageClient* webPageClient)
+{
+ QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(webPageClient->ownerWidget());
+
+ if (scrollArea)
+ return qobject_cast<QGLWidget*>(scrollArea->viewport());
+
+ return 0;
+}
+
+void* GraphicsContext3DInternal::getProcAddress(const String& proc)
+{
+ String ext[3] = { "", "ARB", "EXT" };
+
+ for (int i = 0; i < 3; i++) {
+ String nameWithExt = proc + ext[i];
+
+ void* addr = m_glWidget->context()->getProcAddress(nameWithExt.utf8().data());
+ if (addr)
+ return addr;
+ }
+
+ LOG_ERROR("GraphicsContext3D: Did not find GL function %s", proc.utf8().data());
+ m_contextValid = false;
+ return 0;
+}
+
+PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow)
+{
+ OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs, hostWindow));
+ return context->m_internal ? context.release() : 0;
+}
+
+GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow)
+ : m_internal(new GraphicsContext3DInternal(attrs, hostWindow))
+{
+ if (!m_internal->isContextValid())
+ m_internal = 0;
+}
+
+GraphicsContext3D::~GraphicsContext3D()
+{
+}
+
+PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D()
+{
+ return m_internal->m_glWidget;
+}
+
+Platform3DObject GraphicsContext3D::platformTexture() const
+{
+ return m_internal->m_texture;
+}
+
+void GraphicsContext3D::makeContextCurrent()
+{
+ m_internal->m_glWidget->makeCurrent();
+}
+
+void GraphicsContext3D::beginPaint(WebGLRenderingContext* context)
+{
+ m_internal->m_glWidget->makeCurrent();
+
+ HTMLCanvasElement* canvas = context->canvas();
+ ImageBuffer* imageBuffer = canvas->buffer();
+
+ m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo);
+
+ glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits());
+
+ QPainter* p = imageBuffer->context()->platformContext();
+ p->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.transformed(QMatrix().rotate(180)));
+
+ m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo);
+}
+
+void GraphicsContext3D::endPaint()
+{
+}
+
+void GraphicsContext3D::reshape(int width, int height)
+{
+ if (((width == m_currentWidth) && (height == m_currentHeight)) || (!m_internal))
+ return;
+
+ m_currentWidth = width;
+ m_currentHeight = height;
+
+ m_internal->m_pixels = QImage(m_currentWidth, m_currentHeight, QImage::Format_ARGB32);
+
+ m_internal->m_glWidget->makeCurrent();
+
+ glBindTexture(GraphicsContext3D::TEXTURE_2D, m_internal->m_texture);
+ glTexImage2D(GraphicsContext3D::TEXTURE_2D, /* level */ 0, GraphicsContext3D::RGBA, width, height, /* border */ 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, /* data */ 0);
+ glBindTexture(GraphicsContext3D::TEXTURE_2D, 0);
+
+ m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo);
+ m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer);
+#if defined(QT_OPENGL_ES_2)
+ renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, width, height);
+#else
+ renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, width, height);
+#endif
+ m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
+
+ m_internal->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_internal->m_texture, 0);
+ m_internal->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer);
+
+ GLenum status = m_internal->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER);
+ if (status != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
+ LOG_ERROR("GraphicsContext3D: Wasn't able to reshape the main framebuffer");
+ notImplemented();
+ }
+
+ glClear(GraphicsContext3D::COLOR_BUFFER_BIT);
+ glFlush();
+}
+
+void GraphicsContext3D::activeTexture(unsigned long texture)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->activeTexture(texture);
+}
+
+void GraphicsContext3D::attachShader(WebGLProgram* program, WebGLShader* shader)
+{
+ ASSERT(program);
+ ASSERT(shader);
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->attachShader((GLuint) program->object(), (GLuint) shader->object());
+}
+
+void GraphicsContext3D::bindAttribLocation(WebGLProgram* program, unsigned long index, const String& name)
+{
+ ASSERT(program);
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->bindAttribLocation((GLuint) program->object(), index, name.utf8().data());
+}
+
+void GraphicsContext3D::bindBuffer(unsigned long target, WebGLBuffer* buffer)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->bindBuffer(target, buffer ? (GLuint) buffer->object() : 0);
+}
+
+void GraphicsContext3D::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->m_currentFbo = (buffer && buffer->object()) ? (GLuint) buffer->object() : m_internal->m_mainFbo;
+ m_internal->bindFramebuffer(target, m_internal->m_currentFbo);
+}
+
+void GraphicsContext3D::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderbuffer)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->bindRenderbuffer(target, renderbuffer ? (GLuint) renderbuffer->object() : 0);
+}
+
+void GraphicsContext3D::bindTexture(unsigned long target, WebGLTexture* texture)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glBindTexture(target, texture ? (GLuint) texture->object() : 0);
+}
+
+void GraphicsContext3D::blendColor(double red, double green, double blue, double alpha)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->blendColor(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha));
+}
+
+void GraphicsContext3D::blendEquation(unsigned long mode)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->blendEquation(mode);
+}
+
+void GraphicsContext3D::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->blendEquationSeparate(modeRGB, modeAlpha);
+}
+
+void GraphicsContext3D::blendFunc(unsigned long sfactor, unsigned long dfactor)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glBlendFunc(sfactor, dfactor);
+}
+
+void GraphicsContext3D::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->bufferData(target, size, /* data */ 0, usage);
+}
+
+void GraphicsContext3D::bufferData(unsigned long target, WebGLArray* array, unsigned long usage)
+{
+ if (!array || !array->length())
+ return;
+
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->bufferData(target, array->byteLength(), array->baseAddress(), usage);
+}
+
+void GraphicsContext3D::bufferSubData(unsigned long target, long offset, WebGLArray* array)
+{
+ if (!array || !array->length())
+ return;
+
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->bufferSubData(target, offset, array->byteLength(), array->baseAddress());
+}
+
+unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target)
+{
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->checkFramebufferStatus(target);
+}
+
+void GraphicsContext3D::clearColor(double r, double g, double b, double a)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glClearColor(static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a));
+}
+
+void GraphicsContext3D::clear(unsigned long mask)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glClear(mask);
+}
+
+void GraphicsContext3D::clearDepth(double depth)
+{
+ m_internal->m_glWidget->makeCurrent();
+#if defined(QT_OPENGL_ES_2)
+ glClearDepthf(depth);
+#else
+ glClearDepth(depth);
+#endif
+}
+
+void GraphicsContext3D::clearStencil(long s)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glClearStencil(s);
+}
+
+void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glColorMask(red, green, blue, alpha);
+}
+
+void GraphicsContext3D::compileShader(WebGLShader* shader)
+{
+ ASSERT(shader);
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->compileShader((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)
+{
+ m_internal->m_glWidget->makeCurrent();
+ 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)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+}
+
+void GraphicsContext3D::cullFace(unsigned long mode)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glCullFace(mode);
+}
+
+void GraphicsContext3D::depthFunc(unsigned long func)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glDepthFunc(func);
+}
+
+void GraphicsContext3D::depthMask(bool flag)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glDepthMask(flag);
+}
+
+void GraphicsContext3D::depthRange(double zNear, double zFar)
+{
+ m_internal->m_glWidget->makeCurrent();
+#if defined(QT_OPENGL_ES_2)
+ glDepthRangef(zNear, zFar);
+#else
+ glDepthRange(zNear, zFar);
+#endif
+}
+
+void GraphicsContext3D::detachShader(WebGLProgram* program, WebGLShader* shader)
+{
+ ASSERT(program);
+ ASSERT(shader);
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->detachShader((GLuint) program->object(), (GLuint) shader->object());
+}
+
+void GraphicsContext3D::disable(unsigned long cap)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glDisable(cap);
+}
+
+void GraphicsContext3D::disableVertexAttribArray(unsigned long index)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->disableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glDrawArrays(mode, first, count);
+}
+
+void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glDrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::enable(unsigned long cap)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glEnable(cap);
+}
+
+void GraphicsContext3D::enableVertexAttribArray(unsigned long index)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->enableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::finish()
+{
+ m_internal->m_glWidget->makeCurrent();
+ glFinish();
+}
+
+void GraphicsContext3D::flush()
+{
+ m_internal->m_glWidget->makeCurrent();
+ glFlush();
+}
+
+void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer* buffer)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->framebufferRenderbuffer(target, attachment, renderbuffertarget, buffer ? (GLuint) buffer->object() : 0);
+}
+
+void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture* texture, long level)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->framebufferTexture2D(target, attachment, textarget, texture ? (GLuint) texture->object() : 0, level);
+}
+
+void GraphicsContext3D::frontFace(unsigned long mode)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glFrontFace(mode);
+}
+
+void GraphicsContext3D::generateMipmap(unsigned long target)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->generateMipmap(target);
+}
+
+bool GraphicsContext3D::getActiveAttrib(WebGLProgram* program, unsigned long index, ActiveInfo& info)
+{
+ if (!program->object()) {
+ synthesizeGLError(INVALID_VALUE);
+ return false;
+ }
+
+ m_internal->m_glWidget->makeCurrent();
+
+ GLint maxLength;
+ m_internal->getProgramiv(static_cast<GLuint>(program->object()), GraphicsContext3D::ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
+
+ GLchar* name = (GLchar*) fastMalloc(maxLength);
+ GLsizei nameLength;
+ GLint size;
+ GLenum type;
+
+ m_internal->getActiveAttrib(static_cast<GLuint>(program->object()), index, maxLength, &nameLength, &size, &type, name);
+
+ if (!nameLength) {
+ fastFree(name);
+ return false;
+ }
+
+ info.name = String(name, nameLength);
+ info.type = type;
+ info.size = size;
+
+ fastFree(name);
+ return true;
+}
+
+bool GraphicsContext3D::getActiveUniform(WebGLProgram* program, unsigned long index, ActiveInfo& info)
+{
+ if (!program->object()) {
+ synthesizeGLError(INVALID_VALUE);
+ return false;
+ }
+
+ m_internal->m_glWidget->makeCurrent();
+
+ GLint maxLength;
+ m_internal->getProgramiv(static_cast<GLuint>(program->object()), GraphicsContext3D::ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
+
+ GLchar* name = (GLchar*) fastMalloc(maxLength);
+ GLsizei nameLength;
+ GLint size;
+ GLenum type;
+
+ m_internal->getActiveUniform(static_cast<GLuint>(program->object()), index, maxLength, &nameLength, &size, &type, name);
+
+ if (!nameLength) {
+ fastFree(name);
+ return false;
+ }
+
+ info.name = String(name, nameLength);
+ info.type = type;
+ info.size = size;
+
+ fastFree(name);
+ return true;
+}
+
+int GraphicsContext3D::getAttribLocation(WebGLProgram* program, const String& name)
+{
+ if (!program)
+ return -1;
+
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->getAttribLocation((GLuint) program->object(), name.utf8().data());
+}
+
+GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
+{
+ return m_internal->m_attrs;
+}
+
+unsigned long GraphicsContext3D::getError()
+{
+ if (m_internal->m_syntheticErrors.size() > 0) {
+ ListHashSet<unsigned long>::iterator iter = m_internal->m_syntheticErrors.begin();
+ unsigned long err = *iter;
+ m_internal->m_syntheticErrors.remove(iter);
+ return err;
+ }
+
+ m_internal->m_glWidget->makeCurrent();
+ return glGetError();
+}
+
+String GraphicsContext3D::getString(unsigned long name)
+{
+ m_internal->m_glWidget->makeCurrent();
+ return String((const char*) glGetString(name));
+}
+
+void GraphicsContext3D::hint(unsigned long target, unsigned long mode)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glHint(target, mode);
+}
+
+bool GraphicsContext3D::isBuffer(WebGLBuffer* buffer)
+{
+ if (!buffer)
+ return false;
+
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->isBuffer((GLuint) buffer->object());
+}
+
+bool GraphicsContext3D::isEnabled(unsigned long cap)
+{
+ m_internal->m_glWidget->makeCurrent();
+ return glIsEnabled(cap);
+}
+
+bool GraphicsContext3D::isFramebuffer(WebGLFramebuffer* framebuffer)
+{
+ if (!framebuffer)
+ return false;
+
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->isFramebuffer((GLuint) framebuffer->object());
+}
+
+bool GraphicsContext3D::isProgram(WebGLProgram* program)
+{
+ if (!program)
+ return false;
+
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->isProgram((GLuint) program->object());
+}
+
+bool GraphicsContext3D::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
+{
+ if (!renderbuffer)
+ return false;
+
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->isRenderbuffer((GLuint) renderbuffer->object());
+}
+
+bool GraphicsContext3D::isShader(WebGLShader* shader)
+{
+ if (!shader)
+ return false;
+
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->isShader((GLuint) shader->object());
+}
+
+bool GraphicsContext3D::isTexture(WebGLTexture* texture)
+{
+ if (!texture)
+ return false;
+
+ m_internal->m_glWidget->makeCurrent();
+ return glIsTexture((GLuint) texture->object());
+}
+
+void GraphicsContext3D::lineWidth(double width)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glLineWidth(static_cast<float>(width));
+}
+
+void GraphicsContext3D::linkProgram(WebGLProgram* program)
+{
+ ASSERT(program);
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->linkProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::pixelStorei(unsigned long paramName, long param)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glPixelStorei(paramName, param);
+}
+
+void GraphicsContext3D::polygonOffset(double factor, double units)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glPolygonOffset(static_cast<float>(factor), static_cast<float>(units));
+}
+
+void GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data)
+{
+ m_internal->m_glWidget->makeCurrent();
+
+ if (type != GraphicsContext3D::UNSIGNED_BYTE || format != GraphicsContext3D::RGBA)
+ return;
+
+ glReadPixels(x, y, width, height, format, type, (GLvoid*) data);
+}
+
+void GraphicsContext3D::releaseShaderCompiler()
+{
+ m_internal->m_glWidget->makeCurrent();
+ notImplemented();
+}
+
+void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->renderbufferStorage(target, internalformat, width, height);
+}
+
+void GraphicsContext3D::sampleCoverage(double value, bool invert)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->sampleCoverage(static_cast<float>(value), invert);
+}
+
+void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned long height)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glScissor(x, y, width, height);
+}
+
+void GraphicsContext3D::shaderSource(WebGLShader* shader, const String& source)
+{
+ ASSERT(shader);
+
+ m_internal->m_glWidget->makeCurrent();
+
+ CString sourceCS = source.utf8();
+ const char* data = sourceCS.data();
+ int length = source.length();
+ m_internal->shaderSource((GLuint) shader->object(), /* count */ 1, &data, &length);
+}
+
+void GraphicsContext3D::stencilFunc(unsigned long func, long ref, unsigned long mask)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glStencilFunc(func, ref, mask);
+}
+
+void GraphicsContext3D::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->stencilFuncSeparate(face, func, ref, mask);
+}
+
+void GraphicsContext3D::stencilMask(unsigned long mask)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glStencilMask(mask);
+}
+
+void GraphicsContext3D::stencilMaskSeparate(unsigned long face, unsigned long mask)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->stencilMaskSeparate(face, mask);
+}
+
+void GraphicsContext3D::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glStencilOp(fail, zfail, zpass);
+}
+
+void GraphicsContext3D::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->stencilOpSeparate(face, fail, zfail, zpass);
+}
+
+void GraphicsContext3D::texParameterf(unsigned target, unsigned paramName, float value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glTexParameterf(target, paramName, static_cast<float>(value));
+}
+
+void GraphicsContext3D::texParameteri(unsigned target, unsigned paramName, int value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glTexParameteri(target, paramName, static_cast<float>(value));
+}
+
+void GraphicsContext3D::uniform1f(long location, float v0)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform1f(location, v0);
+}
+
+void GraphicsContext3D::uniform1fv(long location, float* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform1fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2f(long location, float v0, float v1)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform2f(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2fv(long location, float* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform2fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3f(long location, float v0, float v1, float v2)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform3f(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3fv(long location, float* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform3fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4f(long location, float v0, float v1, float v2, float v3)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform4f(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4fv(long location, float* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform4fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform1i(long location, int v0)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform1i(location, v0);
+}
+
+void GraphicsContext3D::uniform1iv(long location, int* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform1iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2i(long location, int v0, int v1)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform2i(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2iv(long location, int* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform2iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3i(long location, int v0, int v1, int v2)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform3i(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3iv(long location, int* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform3iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4i(long location, int v0, int v1, int v2, int v3)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform4i(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4iv(long location, int* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniform4iv(location, size, array);
+}
+
+void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniformMatrix2fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniformMatrix3fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* array, int size)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->uniformMatrix4fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::useProgram(WebGLProgram* program)
+{
+ ASSERT(program);
+
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->useProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::validateProgram(WebGLProgram* program)
+{
+ ASSERT(program);
+
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->validateProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::vertexAttrib1f(unsigned long indx, float v0)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->vertexAttrib1f(indx, v0);
+}
+
+void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* array)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->vertexAttrib1fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib2f(unsigned long indx, float v0, float v1)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->vertexAttrib2f(indx, v0, v1);
+}
+
+void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* array)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->vertexAttrib2fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->vertexAttrib3f(indx, v0, v1, v2);
+}
+
+void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* array)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->vertexAttrib3fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->vertexAttrib4f(indx, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* array)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->vertexAttrib4fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, unsigned long stride, unsigned long offset)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->vertexAttribPointer(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)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height));
+}
+
+void GraphicsContext3D::getBooleanv(unsigned long paramName, unsigned char* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glGetBooleanv(paramName, value);
+}
+
+void GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long paramName, int* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->getBufferParameteriv(target, paramName, value);
+}
+
+void GraphicsContext3D::getFloatv(unsigned long paramName, float* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glGetFloatv(paramName, value);
+}
+
+void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long paramName, int* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->getFramebufferAttachmentParameteriv(target, attachment, paramName, value);
+}
+
+void GraphicsContext3D::getIntegerv(unsigned long paramName, int* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glGetIntegerv(paramName, value);
+}
+
+void GraphicsContext3D::getProgramiv(WebGLProgram* program, unsigned long paramName, int* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->getProgramiv((GLuint) program->object(), paramName, value);
+}
+
+String GraphicsContext3D::getProgramInfoLog(WebGLProgram* program)
+{
+ m_internal->m_glWidget->makeCurrent();
+
+ GLint length;
+ m_internal->getProgramiv((GLuint) program->object(), GraphicsContext3D::INFO_LOG_LENGTH, &length);
+
+ GLsizei size;
+
+ GLchar* info = (GLchar*) fastMalloc(length);
+ if (!info)
+ return "";
+
+ m_internal->getProgramInfoLog((GLuint) program->object(), length, &size, info);
+
+ String result(info);
+ fastFree(info);
+
+ return result;
+}
+
+void GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigned long paramName, int* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->getRenderbufferParameteriv(target, paramName, value);
+}
+
+void GraphicsContext3D::getShaderiv(WebGLShader* shader, unsigned long paramName, int* value)
+{
+ ASSERT(shader);
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->getShaderiv((GLuint) shader->object(), paramName, value);
+}
+
+String GraphicsContext3D::getShaderInfoLog(WebGLShader* shader)
+{
+ m_internal->m_glWidget->makeCurrent();
+
+ GLint length;
+ m_internal->getShaderiv((GLuint) shader->object(), GraphicsContext3D::INFO_LOG_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) fastMalloc(length);
+ if (!info)
+ return "";
+
+ m_internal->getShaderInfoLog((GLuint) shader->object(), length, &size, info);
+
+ String result(info);
+ fastFree(info);
+
+ return result;
+}
+
+String GraphicsContext3D::getShaderSource(WebGLShader* shader)
+{
+ m_internal->m_glWidget->makeCurrent();
+
+ GLint length;
+ m_internal->getShaderiv((GLuint) shader->object(), GraphicsContext3D::SHADER_SOURCE_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) fastMalloc(length);
+ if (!info)
+ return "";
+
+ m_internal->getShaderSource((GLuint) shader->object(), length, &size, info);
+
+ String result(info);
+ fastFree(info);
+
+ return result;
+}
+
+void GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long paramName, float* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glGetTexParameterfv(target, paramName, value);
+}
+
+void GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long paramName, int* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glGetTexParameteriv(target, paramName, value);
+}
+
+void GraphicsContext3D::getUniformfv(WebGLProgram* program, long location, float* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->getUniformfv((GLuint) program->object(), location, value);
+}
+
+void GraphicsContext3D::getUniformiv(WebGLProgram* program, long location, int* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->getUniformiv((GLuint) program->object(), location, value);
+}
+
+long GraphicsContext3D::getUniformLocation(WebGLProgram* program, const String& name)
+{
+ ASSERT(program);
+
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->getUniformLocation((GLuint) program->object(), name.utf8().data());
+}
+
+void GraphicsContext3D::getVertexAttribfv(unsigned long index, unsigned long paramName, float* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->getVertexAttribfv(index, paramName, value);
+}
+
+void GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long paramName, int* value)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->getVertexAttribiv(index, paramName, value);
+}
+
+long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long paramName)
+{
+ m_internal->m_glWidget->makeCurrent();
+
+ void* pointer;
+ m_internal->getVertexAttribPointerv(index, paramName, &pointer);
+ return reinterpret_cast<long>(pointer);
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels)
+{
+ glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+ return 0;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha)
+{
+ ASSERT(image);
+
+ m_internal->m_glWidget->makeCurrent();
+
+ Vector<uint8_t> imageData;
+ GLuint format;
+ GLuint internalFormat;
+
+ if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) {
+ LOG_ERROR("GraphicsContext3D::texImage2D: could not extract Image data");
+ return -1;
+ }
+
+ glTexImage2D(target, level, internalFormat, image->width(), image->height(),
+ /* border */ 0, format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data());
+
+ return 0;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels)
+{
+ glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels);
+ return 0;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, Image* image, bool flipY, bool premultiplyAlpha)
+{
+ ASSERT(image);
+
+ Vector<uint8_t> imageData;
+ GLuint format;
+ GLuint internalFormat;
+
+ if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) {
+ LOG_ERROR("GraphicsContext3D::texSubImage2D: could not extract Image data");
+ return -1;
+ }
+
+ glTexSubImage2D(target, level, xoff, yoff, image->width(), image->height(),
+ format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data());
+
+ return 0;
+}
+
+unsigned GraphicsContext3D::createBuffer()
+{
+ m_internal->m_glWidget->makeCurrent();
+ GLuint handle;
+ m_internal->genBuffers(/* count */ 1, &handle);
+ return handle;
+}
+
+unsigned GraphicsContext3D::createFramebuffer()
+{
+ m_internal->m_glWidget->makeCurrent();
+ GLuint handle;
+ m_internal->genFramebuffers(/* count */ 1, &handle);
+ return handle;
+}
+
+unsigned GraphicsContext3D::createProgram()
+{
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->createProgram();
+}
+
+unsigned GraphicsContext3D::createRenderbuffer()
+{
+ m_internal->m_glWidget->makeCurrent();
+ GLuint handle;
+ m_internal->genRenderbuffers(/* count */ 1, &handle);
+ return handle;
+}
+
+unsigned GraphicsContext3D::createShader(unsigned long type)
+{
+ m_internal->m_glWidget->makeCurrent();
+ return m_internal->createShader((type == FRAGMENT_SHADER) ? GraphicsContext3D::FRAGMENT_SHADER : GraphicsContext3D::VERTEX_SHADER);
+}
+
+unsigned GraphicsContext3D::createTexture()
+{
+ m_internal->m_glWidget->makeCurrent();
+ GLuint handle;
+ glGenTextures(1, &handle);
+ return handle;
+}
+
+void GraphicsContext3D::deleteBuffer(unsigned buffer)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->deleteBuffers(1, &buffer);
+}
+
+void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->deleteFramebuffers(1, &framebuffer);
+}
+
+void GraphicsContext3D::deleteProgram(unsigned program)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->deleteProgram(program);
+}
+
+void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->deleteRenderbuffers(1, &renderbuffer);
+}
+
+void GraphicsContext3D::deleteShader(unsigned shader)
+{
+ m_internal->m_glWidget->makeCurrent();
+ m_internal->deleteShader(shader);
+}
+
+void GraphicsContext3D::deleteTexture(unsigned texture)
+{
+ m_internal->m_glWidget->makeCurrent();
+ glDeleteTextures(1, &texture);
+}
+
+int GraphicsContext3D::sizeInBytes(int type)
+{
+ switch (type) {
+ case GraphicsContext3D::BYTE:
+ return sizeof(GLbyte);
+ case GraphicsContext3D::UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ case GraphicsContext3D::SHORT:
+ return sizeof(GLshort);
+ case GraphicsContext3D::UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GraphicsContext3D::INT:
+ return sizeof(GLint);
+ case GraphicsContext3D::UNSIGNED_INT:
+ return sizeof(GLuint);
+ case GraphicsContext3D::FLOAT:
+ return sizeof(GLfloat);
+ default:
+ return 0;
+ }
+}
+
+void GraphicsContext3D::synthesizeGLError(unsigned long error)
+{
+ m_internal->m_syntheticErrors.add(error);
+}
+
+bool GraphicsContext3D::getImageData(Image* image,
+ Vector<uint8_t>& outputVector,
+ bool premultiplyAlpha,
+ bool* hasAlphaChannel,
+ AlphaOp* neededAlphaOp,
+ unsigned int* format)
+{
+ QImage::Format imageFormat = (!premultiplyAlpha) ?
+ QImage::Format_ARGB32 :
+ QImage::Format_ARGB32_Premultiplied;
+
+ QPixmap* nativePixmap = image->nativeImageForCurrentFrame();
+
+ *hasAlphaChannel = true;
+ *neededAlphaOp = kAlphaDoNothing;
+ *format = GraphicsContext3D::RGBA;
+
+ QImage nativeImage = nativePixmap->toImage().convertToFormat(imageFormat);
+ outputVector.append(nativeImage.bits(), nativeImage.byteCount());
+
+ return true;
+}
+
+}
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index 8bcda2e..edac268 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -312,14 +312,16 @@ void GraphicsContext::drawRect(const IntRect& rect)
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));
+ if (m_common->state.shadowColor.isValid()) {
+ 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);
@@ -410,7 +412,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
patternOffset = patWidth / 2;
} else {
if (remainder)
- patternOffset = (patWidth - remainder)/2;
+ patternOffset = (patWidth - remainder) / 2;
}
}
@@ -614,10 +616,20 @@ void GraphicsContext::fillRect(const FloatRect& rect)
QPainter* p = m_data->p();
if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) {
- drawBorderlessRectShadow(this, p, rect);
+ if (m_common->state.shadowColor.isValid())
+ drawBorderlessRectShadow(this, p, rect);
if (m_common->state.fillPattern) {
AffineTransform affine;
- p->fillRect(rect, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
+ FloatRect rectM(rect);
+ QBrush brush(m_common->state.fillPattern->createPlatformPattern(affine));
+ QPixmap* image = m_common->state.fillPattern->tileImage()->nativeImageForCurrentFrame();
+
+ if (!m_common->state.fillPattern->repeatX() && image)
+ rectM.setWidth(image->width());
+ if (!m_common->state.fillPattern->repeatY() && image)
+ rectM.setHeight(image->height());
+ p->fillRect(rectM, brush);
+
} else if (m_common->state.fillGradient) {
QBrush brush(*m_common->state.fillGradient->platformGradient());
brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
@@ -636,7 +648,8 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& c, ColorSpace
m_data->solidColor.setColor(c);
QPainter* p = m_data->p();
- drawBorderlessRectShadow(this, p, rect);
+ if (m_common->state.shadowColor.isValid())
+ drawBorderlessRectShadow(this, p, rect);
p->fillRect(rect, m_data->solidColor);
}
@@ -1006,11 +1019,11 @@ void GraphicsContext::rotate(float radians)
if (paintingDisabled())
return;
- m_data->p()->rotate(180/M_PI*radians);
+ m_data->p()->rotate(180 / M_PI*radians);
if (!m_data->currentPath.isEmpty()) {
QTransform matrix;
- m_data->currentPath = m_data->currentPath * matrix.rotate(-180/M_PI*radians);
+ m_data->currentPath = m_data->currentPath * matrix.rotate(-180 / M_PI*radians);
m_common->state.pathTransform.rotate(radians);
}
}
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
index 0fd0f1a..834cd4f 100644
--- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
@@ -29,6 +29,7 @@
#include "UnitBezier.h"
#include <QtCore/qabstractanimation.h>
#include <QtCore/qdebug.h>
+#include <QtCore/qmetaobject.h>
#include <QtCore/qset.h>
#include <QtCore/qtimer.h>
#include <QtGui/qbitmap.h>
@@ -101,31 +102,37 @@ public:
// modified by the compositor, so we can know what to look for in the next flush
enum ChangeMask {
NoChanges = 0,
+
+ ParentChange = (1L << 0),
ChildrenChange = (1L << 1),
MaskLayerChange = (1L << 2),
PositionChange = (1L << 3),
+
AnchorPointChange = (1L << 4),
SizeChange = (1L << 5),
TransformChange = (1L << 6),
ContentChange = (1L << 7),
+
GeometryOrientationChange = (1L << 8),
ContentsOrientationChange = (1L << 9),
OpacityChange = (1L << 10),
ContentsRectChange = (1L << 11),
+
Preserves3DChange = (1L << 12),
MasksToBoundsChange = (1L << 13),
DrawsContentChange = (1L << 14),
ContentsOpaqueChange = (1L << 15),
+
BackfaceVisibilityChange = (1L << 16),
ChildrenTransformChange = (1L << 17),
DisplayChange = (1L << 18),
BackgroundColorChange = (1L << 19),
- ParentChange = (1L << 20),
- DistributesOpacityChange = (1L << 21)
+
+ DistributesOpacityChange = (1L << 20)
};
// the compositor lets us special-case images and colors, so we try to do so
- enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType};
+ enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType, MediaContentType};
GraphicsLayerQtImpl(GraphicsLayerQt* newLayer);
virtual ~GraphicsLayerQtImpl();
@@ -149,10 +156,6 @@ public:
// or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP)
void flushChanges(bool recursive = true, bool forceTransformUpdate = false);
- // optimization: when we have an animation running on an element with no contents, that has child-elements with contents,
- // ALL of them have to have ItemCoordinateCache and not DeviceCoordinateCache
- void adjustCachingRecursively(bool animationIsRunning);
-
// optimization: returns true if this or an ancestor has a transform animation running.
// this enables us to use ItemCoordinatesCache while the animation is running, otherwise we have to recache for every frame
bool isTransformAnimationRunning() const;
@@ -161,6 +164,9 @@ public slots:
// we need to notify the client (aka the layer compositor) when the animation actually starts
void notifyAnimationStarted();
+ // we notify WebCore of a layer changed asynchronously; otherwise we end up calling flushChanges too often.
+ void notifySyncRequired();
+
signals:
// optimization: we don't want to use QTimer::singleShot
void notifyAnimationStartedAsync();
@@ -179,6 +185,7 @@ public:
bool updateAll;
QColor contentsBackgroundColor;
QColor backgroundColor;
+ QWeakPointer<QGraphicsObject> mediaLayer;
StaticContentType contentType;
float opacity;
ContentData()
@@ -196,7 +203,9 @@ public:
int m_changeMask;
QSizeF m_size;
+#ifndef QT_NO_ANIMATION
QList<QWeakPointer<QAbstractAnimation> > m_animations;
+#endif
QTimer m_suspendTimer;
struct State {
@@ -227,7 +236,9 @@ public:
}
} m_state;
+#ifndef QT_NO_ANIMATION
friend class AnimationQtBase;
+#endif
};
GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer)
@@ -245,7 +256,7 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer)
setEnabled(true);
// we'll set the cache when we know what's going on
- setCacheMode(NoCache);
+ setCacheMode(ItemCoordinateCache);
connect(this, SIGNAL(notifyAnimationStartedAsync()), this, SLOT(notifyAnimationStarted()), Qt::QueuedConnection);
}
@@ -263,26 +274,13 @@ GraphicsLayerQtImpl::~GraphicsLayerQtImpl()
item->setParentItem(0);
}
}
-
+
+#ifndef QT_NO_ANIMATION
// we do, however, own the animations...
for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_animations.begin(); it != m_animations.end(); ++it)
if (QAbstractAnimation* anim = it->data())
delete anim;
-}
-
-void GraphicsLayerQtImpl::adjustCachingRecursively(bool animationIsRunning)
-{
- // optimization: we make sure all our children have ItemCoordinateCache -
- // otherwise we end up re-rendering them during the animation
- const QList<QGraphicsItem*> children = childItems();
-
- for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) {
- if (QGraphicsItem* item = *it)
- if (GraphicsLayerQtImpl* layer = qobject_cast<GraphicsLayerQtImpl*>(item->toGraphicsObject())) {
- if (layer->m_layer->drawsContent() && layer->m_currentContent.contentType == HTMLContentType)
- layer->setCacheMode(animationIsRunning ? QGraphicsItem::ItemCoordinateCache : QGraphicsItem::DeviceCoordinateCache);
- }
- }
+#endif
}
void GraphicsLayerQtImpl::updateTransform()
@@ -307,29 +305,26 @@ QTransform GraphicsLayerQtImpl::computeTransform(const TransformationMatrix& bas
// this has to do with how WebCore implements -webkit-perspective and -webkit-perspective-origin, which are the CSS
// attribute that call setChildrenTransform
QPointF offset = -pos() - boundingRect().bottomRight() / 2;
- const GraphicsLayerQtImpl* ancestor = this;
- while ((ancestor = qobject_cast<GraphicsLayerQtImpl*>(ancestor->parentObject()))) {
+
+ for (const GraphicsLayerQtImpl* ancestor = this; (ancestor = qobject_cast<GraphicsLayerQtImpl*>(ancestor->parentObject())); ) {
if (!ancestor->m_state.childrenTransform.isIdentity()) {
- offset += ancestor->boundingRect().bottomRight() / 2;
+ const QPointF offset = mapFromItem(ancestor, QPointF(ancestor->m_size.width() / 2, ancestor->m_size.height() / 2));
computedTransform
.translate(offset.x(), offset.y())
.multLeft(ancestor->m_state.childrenTransform)
.translate(-offset.x(), -offset.y());
break;
}
- offset -= ancestor->pos();
}
- computedTransform.multLeft(baseTransform);
-
// webkit has relative-to-size originPoint, graphics-view has a pixel originPoint, here we convert
// we have to manage this ourselves because QGraphicsView's transformOrigin is incompatible
const qreal originX = m_state.anchorPoint.x() * m_size.width();
const qreal originY = m_state.anchorPoint.y() * m_size.height();
- computedTransform = TransformationMatrix()
- .translate(originX, originY)
- .multiply(computedTransform)
- .translate(-originX, -originY);
+ computedTransform
+ .translate3d(originX, originY, m_state.anchorPoint.z())
+ .multLeft(baseTransform)
+ .translate3d(-originX, -originY, -m_state.anchorPoint.z());
// now we project to 2D
return QTransform(computedTransform);
@@ -353,6 +348,7 @@ QPainterPath GraphicsLayerQtImpl::opaqueArea() const
else {
if (m_state.contentsOpaque
|| (m_currentContent.contentType == ColorContentType && m_currentContent.contentsBackgroundColor.alpha() == 0xff)
+ || (m_currentContent.contentType == MediaContentType)
|| (m_currentContent.contentType == PixmapContentType && !m_currentContent.pixmap.hasAlpha())) {
painterPath.addRect(m_state.contentsRect);
@@ -369,14 +365,14 @@ QRectF GraphicsLayerQtImpl::boundingRect() const
void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
if (m_currentContent.backgroundColor.isValid())
- painter->fillRect(option->exposedRect, QColor(m_currentContent.backgroundColor));
+ painter->fillRect(option->rect, QColor(m_currentContent.backgroundColor));
switch (m_currentContent.contentType) {
case HTMLContentType:
if (m_state.drawsContent) {
// this is the expensive bit. we try to minimize calls to this area by proper caching
GraphicsContext gc(painter);
- m_layer->paintGraphicsLayerContents(gc, option->exposedRect.toAlignedRect());
+ m_layer->paintGraphicsLayerContents(gc, option->rect);
}
break;
case PixmapContentType:
@@ -385,19 +381,25 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte
case ColorContentType:
painter->fillRect(m_state.contentsRect, m_currentContent.contentsBackgroundColor);
break;
+ case MediaContentType:
+ // we don't need to paint anything: we have a QGraphicsItem from the media element
+ break;
}
}
-void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask)
+void GraphicsLayerQtImpl::notifySyncRequired()
{
- Q_ASSERT(this);
-
- m_changeMask |= changeMask;
-
if (m_layer->client())
m_layer->client()->notifySyncRequired(m_layer);
}
+void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask)
+{
+ m_changeMask |= changeMask;
+ static QMetaMethod syncMethod = staticMetaObject.method(staticMetaObject.indexOfMethod("notifySyncRequired()"));
+ syncMethod.invoke(this, Qt::QueuedConnection);
+}
+
void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform)
{
// this is the bulk of the work. understanding what the compositor is trying to achieve,
@@ -433,7 +435,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
w->setParentItem(this);
for (QSet<QGraphicsItem*>::const_iterator it = childrenToRemove.begin(); it != childrenToRemove.end(); ++it)
- if (QGraphicsItem* w = *it)
+ if (GraphicsLayerQtImpl* w = qobject_cast<GraphicsLayerQtImpl*>((*it)->toGraphicsObject()))
w->setParentItem(0);
// children are ordered by z-value, let graphics-view know.
@@ -450,7 +452,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
if (m_layer->maskLayer()) {
if (GraphicsLayerQtImpl* mask = qobject_cast<GraphicsLayerQtImpl*>(m_layer->maskLayer()->platformLayer()->toGraphicsObject())) {
mask->m_maskEffect = new MaskEffectQt(this, mask);
- mask->setCacheMode(NoCache);
setGraphicsEffect(mask->m_maskEffect.data());
}
}
@@ -465,11 +466,11 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
m_size = QSizeF(m_layer->size().width(), m_layer->size().height());
}
}
-
// FIXME: this is a hack, due to a probable QGraphicsScene bug when rapidly modifying the perspective
// but without this line we get graphic artifacts
if ((m_changeMask & ChildrenTransformChange) && m_state.childrenTransform != m_layer->childrenTransform())
- scene()->update();
+ if (scene())
+ scene()->update();
if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange)) {
// due to the differences between the way WebCore handles transforms and the way Qt handles transforms,
@@ -483,11 +484,19 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
update();
setFlag(ItemHasNoContents, false);
+ // no point in caching a directly composited pixmap into another pixmap
+ setCacheMode(NoCache);
+
+ break;
+ case MediaContentType:
+ setFlag(ItemHasNoContents, true);
+ setCacheMode(NoCache);
+ m_pendingContent.mediaLayer.data()->setParentItem(this);
break;
case ColorContentType:
// no point in caching a solid-color rectangle
- setCacheMode(m_layer->maskLayer() ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache);
+ setCacheMode(NoCache);
if (m_pendingContent.contentType != m_currentContent.contentType || m_pendingContent.contentsBackgroundColor != m_currentContent.contentsBackgroundColor)
update();
m_state.drawsContent = false;
@@ -500,19 +509,11 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
case HTMLContentType:
if (m_pendingContent.contentType != m_currentContent.contentType)
update();
- if (!m_state.drawsContent && m_layer->drawsContent())
+ if (!m_state.drawsContent && m_layer->drawsContent()) {
update();
- if (m_layer->drawsContent() && !m_maskEffect) {
- const QGraphicsItem::CacheMode mewCacheMode = isTransformAnimationRunning() ? ItemCoordinateCache : DeviceCoordinateCache;
-
- // optimization: QGraphicsItem doesn't always perform this test
- if (mewCacheMode != cacheMode())
- setCacheMode(mewCacheMode);
-
- // HTML content: we want to use exposedRect so we don't use WebCore rendering if we don't have to
- setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
- }
- else
+ if (m_layer->drawsContent() && !m_maskEffect)
+ setCacheMode(ItemCoordinateCache);
+ } else if (!m_layer->drawsContent())
setCacheMode(NoCache);
setFlag(ItemHasNoContents, !m_layer->drawsContent());
@@ -520,7 +521,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
}
}
- if ((m_changeMask & OpacityChange) && m_state.opacity != m_layer->opacity())
+ if ((m_changeMask & OpacityChange) && m_state.opacity != m_layer->opacity() && !m_opacityAnimationRunning)
setOpacity(m_layer->opacity());
if (m_changeMask & ContentsRectChange) {
@@ -569,6 +570,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
m_state.childrenTransform = m_layer->childrenTransform();
m_currentContent.pixmap = m_pendingContent.pixmap;
m_currentContent.contentType = m_pendingContent.contentType;
+ m_currentContent.mediaLayer = m_pendingContent.mediaLayer;
m_currentContent.backgroundColor = m_pendingContent.backgroundColor;
m_currentContent.regionToUpdate |= m_pendingContent.regionToUpdate;
m_currentContent.contentsBackgroundColor = m_pendingContent.contentsBackgroundColor;
@@ -707,116 +709,140 @@ void GraphicsLayerQt::removeFromParent()
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setMaskLayer(GraphicsLayer* layer)
+void GraphicsLayerQt::setMaskLayer(GraphicsLayer* value)
{
- GraphicsLayer::setMaskLayer(layer);
+ if (value == maskLayer())
+ return;
+ GraphicsLayer::setMaskLayer(value);
m_impl->notifyChange(GraphicsLayerQtImpl::MaskLayerChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setPosition(const FloatPoint& p)
+void GraphicsLayerQt::setPosition(const FloatPoint& value)
{
- if (position() != p)
- m_impl->notifyChange(GraphicsLayerQtImpl::PositionChange);
- GraphicsLayer::setPosition(p);
+ if (value == position())
+ return;
+ GraphicsLayer::setPosition(value);
+ m_impl->notifyChange(GraphicsLayerQtImpl::PositionChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setAnchorPoint(const FloatPoint3D& p)
+void GraphicsLayerQt::setAnchorPoint(const FloatPoint3D& value)
{
- if (anchorPoint() != p)
- m_impl->notifyChange(GraphicsLayerQtImpl::AnchorPointChange);
- GraphicsLayer::setAnchorPoint(p);
+ if (value == anchorPoint())
+ return;
+ GraphicsLayer::setAnchorPoint(value);
+ m_impl->notifyChange(GraphicsLayerQtImpl::AnchorPointChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setSize(const FloatSize& size)
+void GraphicsLayerQt::setSize(const FloatSize& value)
{
- if (this->size() != size)
- m_impl->notifyChange(GraphicsLayerQtImpl::SizeChange);
- GraphicsLayer::setSize(size);
+ if (value == size())
+ return;
+ GraphicsLayer::setSize(value);
+ m_impl->notifyChange(GraphicsLayerQtImpl::SizeChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setTransform(const TransformationMatrix& t)
+void GraphicsLayerQt::setTransform(const TransformationMatrix& value)
{
- if (!m_impl->m_transformAnimationRunning && transform() != t)
- m_impl->notifyChange(GraphicsLayerQtImpl::TransformChange);
- GraphicsLayer::setTransform(t);
+ if (value == transform())
+ return;
+ GraphicsLayer::setTransform(value);
+ m_impl->notifyChange(GraphicsLayerQtImpl::TransformChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setChildrenTransform(const TransformationMatrix& t)
+void GraphicsLayerQt::setChildrenTransform(const TransformationMatrix& value)
{
- GraphicsLayer::setChildrenTransform(t);
+ if (value == childrenTransform())
+ return;
+ GraphicsLayer::setChildrenTransform(value);
m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenTransformChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setPreserves3D(bool b)
+void GraphicsLayerQt::setPreserves3D(bool value)
{
- if (b != preserves3D());
- m_impl->notifyChange(GraphicsLayerQtImpl::Preserves3DChange);
- GraphicsLayer::setPreserves3D(b);
+ if (value == preserves3D())
+ return;
+ GraphicsLayer::setPreserves3D(value);
+ m_impl->notifyChange(GraphicsLayerQtImpl::Preserves3DChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setMasksToBounds(bool b)
+void GraphicsLayerQt::setMasksToBounds(bool value)
{
- GraphicsLayer::setMasksToBounds(b);
+ if (value == masksToBounds())
+ return;
+ GraphicsLayer::setMasksToBounds(value);
m_impl->notifyChange(GraphicsLayerQtImpl::MasksToBoundsChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setDrawsContent(bool b)
+void GraphicsLayerQt::setDrawsContent(bool value)
{
+ if (value == drawsContent())
+ return;
m_impl->notifyChange(GraphicsLayerQtImpl::DrawsContentChange);
- GraphicsLayer::setDrawsContent(b);
+ GraphicsLayer::setDrawsContent(value);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setBackgroundColor(const Color& c)
+void GraphicsLayerQt::setBackgroundColor(const Color& value)
{
+ if (value == m_impl->m_pendingContent.backgroundColor)
+ return;
+ m_impl->m_pendingContent.backgroundColor = value;
+ GraphicsLayer::setBackgroundColor(value);
m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange);
- m_impl->m_pendingContent.backgroundColor = c;
- GraphicsLayer::setBackgroundColor(c);
}
// reimp from GraphicsLayer.h
void GraphicsLayerQt::clearBackgroundColor()
{
+ if (!m_impl->m_pendingContent.backgroundColor.isValid())
+ return;
m_impl->m_pendingContent.backgroundColor = QColor();
- m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange);
GraphicsLayer::clearBackgroundColor();
+ m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setContentsOpaque(bool b)
+void GraphicsLayerQt::setContentsOpaque(bool value)
{
+ if (value == contentsOpaque())
+ return;
m_impl->notifyChange(GraphicsLayerQtImpl::ContentsOpaqueChange);
- GraphicsLayer::setContentsOpaque(b);
+ GraphicsLayer::setContentsOpaque(value);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setBackfaceVisibility(bool b)
+void GraphicsLayerQt::setBackfaceVisibility(bool value)
{
+ if (value == backfaceVisibility())
+ return;
+ GraphicsLayer::setBackfaceVisibility(value);
m_impl->notifyChange(GraphicsLayerQtImpl::BackfaceVisibilityChange);
- GraphicsLayer::setBackfaceVisibility(b);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setOpacity(float o)
+void GraphicsLayerQt::setOpacity(float value)
{
- if (!m_impl->m_opacityAnimationRunning && opacity() != o)
- m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange);
- GraphicsLayer::setOpacity(o);
+ if (value == opacity())
+ return;
+ GraphicsLayer::setOpacity(value);
+ m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange);
}
// reimp from GraphicsLayer.h
-void GraphicsLayerQt::setContentsRect(const IntRect& r)
+void GraphicsLayerQt::setContentsRect(const IntRect& value)
{
+ if (value == contentsRect())
+ return;
+ GraphicsLayer::setContentsRect(value);
m_impl->notifyChange(GraphicsLayerQtImpl::ContentsRectChange);
- GraphicsLayer::setContentsRect(r);
}
// reimp from GraphicsLayer.h
@@ -845,6 +871,19 @@ void GraphicsLayerQt::setContentsBackgroundColor(const Color& color)
GraphicsLayer::setContentsBackgroundColor(color);
}
+void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media)
+{
+ if (media) {
+ m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::MediaContentType;
+ m_impl->m_pendingContent.mediaLayer = media->toGraphicsObject();
+ } else
+ m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::HTMLContentType;
+
+ m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange);
+ GraphicsLayer::setContentsToMedia(media);
+}
+
+
// reimp from GraphicsLayer.h
void GraphicsLayerQt::setGeometryOrientation(CompositingCoordinatesOrientation orientation)
{
@@ -913,18 +952,18 @@ static inline double solveCubicBezierFunction(qreal p1x, qreal p1y, qreal p2x, q
// we want the timing function to be as close as possible to what the web-developer intended, so we're using the same function used by WebCore when compositing is disabled
// Using easing-curves would probably work for some of the cases, but wouldn't really buy us anything as we'd have to convert the bezier function back to an easing curve
-static inline qreal applyTimingFunction(const TimingFunction& timingFunction, qreal progress, int duration)
-{
- if (timingFunction.type() == LinearTimingFunction)
- return progress;
- if (timingFunction.type() == CubicBezierTimingFunction) {
- return solveCubicBezierFunction(timingFunction.x1(),
- timingFunction.y1(),
- timingFunction.x2(),
- timingFunction.y2(),
- double(progress), double(duration) / 1000);
- }
+static inline qreal applyTimingFunction(const TimingFunction& timingFunction, qreal progress, double duration)
+{
+ if (timingFunction.type() == LinearTimingFunction)
return progress;
+ if (timingFunction.type() == CubicBezierTimingFunction) {
+ return solveCubicBezierFunction(timingFunction.x1(),
+ timingFunction.y1(),
+ timingFunction.x2(),
+ timingFunction.y2(),
+ double(progress), double(duration) / 1000);
+ }
+ return progress;
}
// helper functions to safely get a value out of WebCore's AnimationValue*
@@ -943,6 +982,7 @@ static void webkitAnimationToQtAnimationValue(const AnimationValue* animationVal
realValue = animationValue ? static_cast<const FloatAnimationValue*>(animationValue)->value() : 0;
}
+#ifndef QT_NO_ANIMATION
// we put a bit of the functionality in a base class to allow casting and to save some code size
class AnimationQtBase : public QAbstractAnimation {
public:
@@ -953,7 +993,9 @@ public:
, m_duration(anim->duration() * 1000)
, m_isAlternate(anim->direction() == Animation::AnimationDirectionAlternate)
, m_webkitPropertyID(values.property())
+ , m_webkitAnimation(anim)
, m_keyframesName(name)
+ , m_fillsForwards(false)
{
}
@@ -973,7 +1015,11 @@ public:
int m_duration;
bool m_isAlternate;
AnimatedPropertyID m_webkitPropertyID;
+
+ // we might need this in case the same animation is added again (i.e. resumed by WebCore)
+ const Animation* m_webkitAnimation;
QString m_keyframesName;
+ bool m_fillsForwards;
};
// we'd rather have a templatized QAbstractAnimation than QPropertyAnimation / QVariantAnimation;
@@ -992,6 +1038,8 @@ public:
KeyframeValueQt<T> keyframeValue;
if (animationValue->timingFunction())
keyframeValue.timingFunction = *animationValue->timingFunction();
+ else
+ keyframeValue.timingFunction = anim->timingFunction();
webkitAnimationToQtAnimationValue(animationValue, keyframeValue.value);
m_keyframeValues[animationValue->keyTime()] = keyframeValue;
}
@@ -1028,7 +1076,7 @@ protected:
typename QMap<qreal, KeyframeValueQt<T> >::iterator it2 = it+1;
if (it2 == m_keyframeValues.end())
- it2 = m_keyframeValues.begin();
+ it2 = it;
const KeyframeValueQt<T>& fromKeyframe = it.value();
const KeyframeValueQt<T>& toKeyframe = it2.value();
@@ -1040,7 +1088,7 @@ protected:
// we can now process the progress and apply the frame
progress = (!progress || progress == 1 || it.key() == it2.key())
? progress
- : applyTimingFunction(timingFunc, (progress - it.key()) / (it2.key() - it.key()), duration() / 1000);
+ : applyTimingFunction(timingFunc, (progress - it.key()) / (it2.key() - it.key()), duration());
applyFrame(fromValue, toValue, progress);
}
@@ -1056,10 +1104,10 @@ public:
~TransformAnimationQt()
{
- // this came up during the compositing/animation LayoutTests
- // when the animation dies, the transform has to go back to default
- if (m_layer)
- m_layer.data()->updateTransform();
+ if (m_fillsForwards)
+ setCurrentTime(1);
+ else if (m_layer && m_layer.data()->m_layer)
+ m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform());
}
// the idea is that we let WebCore manage the transform-operations
@@ -1077,15 +1125,29 @@ public:
sourceOperations.apply(m_boxSize, sourceMatrix);
transformMatrix = m_sourceMatrix;
transformMatrix.blend(sourceMatrix, 1 - progress);
- } else if (targetOperations.size() != sourceOperations.size()) {
- transformMatrix = m_sourceMatrix;
- targetOperations.apply(m_boxSize, transformMatrix);
- transformMatrix.blend(m_sourceMatrix, progress);
} else {
- for (size_t i = 0; i < targetOperations.size(); ++i)
- targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize);
+ bool validTransformLists = true;
+ const int sourceOperationCount = sourceOperations.size();
+ if (sourceOperationCount) {
+ if (targetOperations.size() != sourceOperationCount)
+ validTransformLists = false;
+ else
+ for (size_t j = 0; j < sourceOperationCount && validTransformLists; ++j)
+ if (!sourceOperations.operations()[j]->isSameType(*targetOperations.operations()[j]))
+ validTransformLists = false;
+ }
+
+ if (validTransformLists) {
+ for (size_t i = 0; i < targetOperations.size(); ++i)
+ targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize);
+ } else {
+ targetOperations.apply(m_boxSize, transformMatrix);
+ transformMatrix.blend(m_sourceMatrix, progress);
+ }
}
m_layer.data()->setBaseTransform(transformMatrix);
+ if (m_fillsForwards)
+ m_layer.data()->m_layer->setTransform(m_layer.data()->m_baseTransform);
}
virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
@@ -1100,10 +1162,8 @@ public:
if (newState == QAbstractAnimation::Running) {
m_sourceMatrix = m_layer.data()->m_layer->transform();
m_layer.data()->m_transformAnimationRunning = true;
- m_layer.data()->adjustCachingRecursively(true);
- } else {
+ } else if (newState == QAbstractAnimation::Stopped) {
m_layer.data()->m_transformAnimationRunning = false;
- m_layer.data()->adjustCachingRecursively(false);
}
}
@@ -1117,9 +1177,25 @@ public:
{
}
+ ~OpacityAnimationQt()
+ {
+ if (m_fillsForwards)
+ setCurrentTime(1);
+ else if (m_layer && m_layer.data()->m_layer)
+ m_layer.data()->setOpacity(m_layer.data()->m_layer->opacity());
+ }
virtual void applyFrame(const qreal& fromValue, const qreal& toValue, qreal progress)
{
- m_layer.data()->setOpacity(qMin<qreal>(qMax<qreal>(fromValue + (toValue-fromValue)*progress, 0), 1));
+ qreal opacity = qBound(qreal(0), fromValue + (toValue-fromValue)*progress, qreal(1));
+
+ // FIXME: this is a hack, due to a probable QGraphicsScene bug.
+ // Without this the opacity change doesn't always have immediate effect.
+ if (!m_layer.data()->opacity() && opacity)
+ m_layer.data()->scene()->update();
+
+ m_layer.data()->setOpacity(opacity);
+ if (m_fillsForwards)
+ m_layer.data()->m_layer->setOpacity(opacity);
}
virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
@@ -1136,33 +1212,51 @@ bool GraphicsLayerQt::addAnimation(const KeyframeValueList& values, const IntSiz
if (!anim->duration() || !anim->iterationCount())
return false;
- QAbstractAnimation* newAnim;
+ AnimationQtBase* newAnim = 0;
- switch (values.property()) {
- case AnimatedPropertyOpacity:
- newAnim = new OpacityAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName);
- break;
- case AnimatedPropertyWebkitTransform:
- newAnim = new TransformAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName);
- break;
- default:
- return false;
+ // fixed: we might already have the Qt animation object associated with this WebCore::Animation object
+ for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) {
+ if (*it) {
+ AnimationQtBase* curAnimation = static_cast<AnimationQtBase*>(it->data());
+ if (curAnimation && curAnimation->m_webkitAnimation == anim)
+ newAnim = curAnimation;
+ }
}
- // we make sure WebCore::Animation and QAnimation are on the same terms
- newAnim->setLoopCount(anim->iterationCount());
- m_impl->m_animations.append(QWeakPointer<QAbstractAnimation>(newAnim));
- QObject::connect(&m_impl->m_suspendTimer, SIGNAL(timeout()), newAnim, SLOT(resume()));
- timeOffset += anim->delay();
+ if (!newAnim) {
+ switch (values.property()) {
+ case AnimatedPropertyOpacity:
+ newAnim = new OpacityAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName);
+ break;
+ case AnimatedPropertyWebkitTransform:
+ newAnim = new TransformAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName);
+ break;
+ default:
+ return false;
+ }
+
+ // we make sure WebCore::Animation and QAnimation are on the same terms
+ newAnim->setLoopCount(anim->iterationCount());
+ newAnim->m_fillsForwards = anim->fillsForwards();
+ m_impl->m_animations.append(QWeakPointer<QAbstractAnimation>(newAnim));
+ QObject::connect(&m_impl->m_suspendTimer, SIGNAL(timeout()), newAnim, SLOT(resume()));
+ }
// flush now or flicker...
m_impl->flushChanges(false);
- if (timeOffset)
- QTimer::singleShot(timeOffset * 1000, newAnim, SLOT(start()));
+ // when fill-mode is backwards/both, we set the value to 0 before the delay takes place
+ if (anim->fillsBackwards())
+ newAnim->setCurrentTime(0);
+
+ if (anim->delay())
+ QTimer::singleShot(anim->delay() * 1000, newAnim, SLOT(start()));
else
newAnim->start();
+ // we synchronize the animation's clock to WebCore's timeOffset
+ newAnim->setCurrentTime(timeOffset * 1000);
+
// we don't need to manage the animation object's lifecycle:
// WebCore would call removeAnimations when it's time to delete.
@@ -1204,8 +1298,11 @@ void GraphicsLayerQt::pauseAnimation(const String& name, double timeOffset)
continue;
AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data());
- if (anim && anim->m_keyframesName == QString(name))
- QTimer::singleShot(timeOffset * 1000, anim, SLOT(pause()));
+ if (anim && anim->m_keyframesName == QString(name)) {
+ // we synchronize the animation's clock to WebCore's timeOffset
+ anim->setCurrentTime(timeOffset * 1000);
+ anim->pause();
+ }
}
}
@@ -1235,6 +1332,7 @@ void GraphicsLayerQt::resumeAnimations()
}
}
+#endif // QT_NO_ANIMATION
}
#include <GraphicsLayerQt.moc>
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
index 3a53bd9..9e5832f 100644
--- a/WebCore/platform/graphics/qt/GraphicsLayerQt.h
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
@@ -63,13 +63,16 @@ public:
virtual void setBackfaceVisibility(bool b);
virtual void setOpacity(float opacity);
virtual void setContentsRect(const IntRect& r);
+#ifndef QT_NO_ANIMATION
virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String& keyframesName, double timeOffset);
virtual void removeAnimationsForProperty(AnimatedPropertyID);
virtual void removeAnimationsForKeyframes(const String& keyframesName);
virtual void pauseAnimation(const String& keyframesName, double timeOffset);
virtual void suspendAnimations(double time);
virtual void resumeAnimations();
+#endif // QT_NO_ANIMATION
virtual void setContentsToImage(Image*);
+ virtual void setContentsToMedia(PlatformLayer*);
virtual void setContentsBackgroundColor(const Color&);
virtual void setGeometryOrientation(CompositingCoordinatesOrientation orientation);
virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation);
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index d831566..4b85a18 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -28,11 +28,11 @@
#include "config.h"
#include "ImageBuffer.h"
-#include "CString.h"
#include "GraphicsContext.h"
#include "ImageData.h"
#include "MIMETypeRegistry.h"
#include "StillImageQt.h"
+#include <wtf/text/CString.h>
#include <QBuffer>
#include <QColor>
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 18e7f08..b48b278 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -57,7 +57,7 @@ ImageDecoderQt::~ImageDecoderQt()
void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived)
{
- if (m_failed)
+ if (failed())
return;
// No progressive loading possible
@@ -75,7 +75,7 @@ void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived)
QByteArray imageData = QByteArray::fromRawData(m_data->data(), m_data->size());
m_buffer.set(new QBuffer);
m_buffer->setData(imageData);
- m_buffer->open(QBuffer::ReadOnly);
+ m_buffer->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
m_reader.set(new QImageReader(m_buffer.get(), m_format));
// This will force the JPEG decoder to use JDCT_IFAST
@@ -106,9 +106,8 @@ size_t ImageDecoderQt::frameCount()
forceLoadEverything();
else
m_frameBufferCache.resize(imageCount);
- } else {
+ } else
m_frameBufferCache.resize(1);
- }
}
return m_frameBufferCache.size();
@@ -116,8 +115,21 @@ size_t ImageDecoderQt::frameCount()
int ImageDecoderQt::repetitionCount() const
{
- if (m_reader && m_reader->supportsAnimation())
- m_repetitionCount = qMax(0, m_reader->loopCount());
+ if (m_reader && m_reader->supportsAnimation()) {
+ m_repetitionCount = m_reader->loopCount();
+
+ // Qt and WebCore have a incompatible understanding of
+ // the loop count and we can not completely map everything.
+ // Qt | WebCore | description
+ // -1 | 0 | infinite animation
+ // 0 | cAnimationLoopOnce | show every frame once
+ // n | n | no idea if that is supported
+ // n/a | cAnimationNone | show only the first frame
+ if (m_repetitionCount == -1)
+ m_repetitionCount = 0;
+ else if (m_repetitionCount == 0)
+ m_repetitionCount = cAnimationLoopOnce;
+ }
return m_repetitionCount;
}
@@ -133,7 +145,7 @@ RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
// yet how many images we are going to have and need to
// find that out now.
size_t count = m_frameBufferCache.size();
- if (!m_failed && !count) {
+ if (!failed() && !count) {
internalDecodeSize();
count = frameCount();
}
@@ -157,8 +169,10 @@ void ImageDecoderQt::internalDecodeSize()
// If we have a QSize() something failed
QSize size = m_reader->size();
- if (size.isEmpty())
- return failRead();
+ if (size.isEmpty()) {
+ setFailed();
+ return clearPointers();
+ }
setSize(size.width(), size.height());
}
@@ -169,26 +183,33 @@ void ImageDecoderQt::internalReadImage(size_t frameIndex)
if (m_reader->supportsAnimation())
m_reader->jumpToImage(frameIndex);
- else if (frameIndex != 0)
- return failRead();
+ else if (frameIndex) {
+ setFailed();
+ return clearPointers();
+ }
- internalHandleCurrentImage(frameIndex);
+ if (!internalHandleCurrentImage(frameIndex))
+ setFailed();
// Attempt to return some memory
- for (int i = 0; i < m_frameBufferCache.size(); ++i)
+ for (int i = 0; i < m_frameBufferCache.size(); ++i) {
if (m_frameBufferCache[i].status() != RGBA32Buffer::FrameComplete)
return;
+ }
- m_reader.clear();
- m_buffer.clear();
+ clearPointers();
}
-void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
+bool ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
{
// Now get the QImage from Qt and place it in the RGBA32Buffer
QImage img;
- if (!m_reader->read(&img))
- return failRead();
+ if (!m_reader->read(&img)) {
+ frameCount();
+ repetitionCount();
+ clearPointers();
+ return false;
+ }
// now into the RGBA32Buffer - even if the image is not
QSize imageSize = img.size();
@@ -197,6 +218,7 @@ void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
buffer->setStatus(RGBA32Buffer::FrameComplete);
buffer->setDuration(m_reader->nextImageDelay());
buffer->setDecodedImage(img);
+ return true;
}
// The QImageIOHandler is not able to tell us how many frames
@@ -204,8 +226,8 @@ void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
// 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.
+// the failed bit. If we failed to decode the first image
+// then we truly failed to decode, otherwise we're OK.
// TODO: Do not increment the m_frameBufferCache.size() by one but more than one
void ImageDecoderQt::forceLoadEverything()
@@ -214,20 +236,19 @@ void ImageDecoderQt::forceLoadEverything()
do {
m_frameBufferCache.resize(++imageCount);
- internalHandleCurrentImage(imageCount - 1);
- } while (!m_failed);
+ } while (internalHandleCurrentImage(imageCount - 1));
// 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
+ // have no images and need to set the failed bit.
+ // Otherwise, we want to forget about
// the last attempt to decode a image.
m_frameBufferCache.resize(imageCount - 1);
- m_failed = imageCount == 1;
+ if (imageCount == 1)
+ setFailed();
}
-void ImageDecoderQt::failRead()
+void ImageDecoderQt::clearPointers()
{
- setFailed();
m_reader.clear();
m_buffer.clear();
}
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
index be9a9b0..ceef884 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.h
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -61,9 +61,9 @@ private:
private:
void internalDecodeSize();
void internalReadImage(size_t);
- void internalHandleCurrentImage(size_t);
+ bool internalHandleCurrentImage(size_t);
void forceLoadEverything();
- void failRead();
+ void clearPointers();
private:
QByteArray m_format;
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
index 3274db5..21e670c 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
@@ -23,23 +23,25 @@
#include <limits>
-#include "CString.h"
#include "FrameView.h"
#include "GraphicsContext.h"
+#include "MIMETypeRegistry.h"
#include "NotImplemented.h"
#include "TimeRanges.h"
#include "Widget.h"
#include <wtf/HashSet.h>
+#include <wtf/text/CString.h>
#include <QDebug>
+#include <QEvent>
+#include <QMetaEnum>
#include <QPainter>
#include <QWidget>
-#include <QMetaEnum>
#include <QUrl>
-#include <QEvent>
-#include <phonon/path.h>
#include <phonon/audiooutput.h>
+#include <phonon/backendcapabilities.h>
+#include <phonon/path.h>
#include <phonon/mediaobject.h>
#include <phonon/videowidget.h>
@@ -143,15 +145,62 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
m_mediaObject = 0;
}
-void MediaPlayerPrivate::getSupportedTypes(HashSet<String>&)
+HashSet<String>& MediaPlayerPrivate::supportedTypesCache()
{
- notImplemented();
+ static HashSet<String> supportedTypes;
+ if (!supportedTypes.isEmpty())
+ return supportedTypes;
+
+ // FIXME: we should rebuild the MIME type cache every time the backend is changed,
+ // however, this would have no effect on MIMETypeRegistry anyway, because it
+ // pulls this data only once.
+
+ QStringList types = Phonon::BackendCapabilities::availableMimeTypes();
+ foreach (const QString& type, types) {
+ QString first = type.split(QLatin1Char('/')).at(0);
+
+ // We're only interested in types which are not supported by WebCore itself.
+ if (first != QLatin1String("video")
+ && first != QLatin1String("audio")
+ && first != QLatin1String("application"))
+ continue;
+ if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
+ continue;
+
+ supportedTypes.add(String(type));
+ }
+
+ // These formats are supported by GStreamer, but not correctly advertised.
+ if (supportedTypes.contains(String("video/x-h264"))
+ || supportedTypes.contains(String("audio/x-m4a"))) {
+ supportedTypes.add(String("video/mp4"));
+ supportedTypes.add(String("audio/aac"));
+ }
+
+ if (supportedTypes.contains(String("video/x-theora")))
+ supportedTypes.add(String("video/ogg"));
+
+ if (supportedTypes.contains(String("audio/x-vorbis")))
+ supportedTypes.add(String("audio/ogg"));
+
+ if (supportedTypes.contains(String("audio/x-wav")))
+ supportedTypes.add(String("audio/wav"));
+
+ return supportedTypes;
}
-MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String&, const String&)
+void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
{
- // FIXME: do the real thing
- notImplemented();
+ types = supportedTypesCache();
+}
+
+MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
+{
+ if (type.isEmpty())
+ return MediaPlayer::IsNotSupported;
+
+ if (supportedTypesCache().contains(type))
+ return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
return MediaPlayer::IsNotSupported;
}
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
index e7630a1..ff6a01c 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
@@ -132,6 +132,7 @@ namespace WebCore {
static void getSupportedTypes(HashSet<String>&);
static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
+ static HashSet<String>& supportedTypesCache();
static bool isAvailable() { return true; }
void updateStates();
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
new file mode 100644
index 0000000..bdac2a4
--- /dev/null
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
@@ -0,0 +1,571 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "MediaPlayerPrivateQt.h"
+
+#include "FrameLoaderClientQt.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "HTMLVideoElement.h"
+#include "TimeRanges.h"
+#include "Widget.h"
+#include "qwebframe.h"
+#include "qwebpage.h"
+
+#include <QGraphicsScene>
+#include <QGraphicsVideoItem>
+#include <QMediaPlayerControl>
+#include <QMediaService>
+#include <QNetworkAccessManager>
+#include <QNetworkCookieJar>
+#include <QNetworkRequest>
+#include <QPainter>
+#include <QPoint>
+#include <QRect>
+#include <QTime>
+#include <QTimer>
+#include <QUrl>
+#include <limits>
+#include <wtf/HashSet.h>
+#include <wtf/text/CString.h>
+
+using namespace WTF;
+
+namespace WebCore {
+
+MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player)
+{
+ return new MediaPlayerPrivate(player);
+}
+
+void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar)
+{
+ registrar(create, getSupportedTypes, supportsType);
+}
+
+void MediaPlayerPrivate::getSupportedTypes(HashSet<String> &supported)
+{
+ QStringList types = QMediaPlayer::supportedMimeTypes();
+
+ for (int i = 0; i < types.size(); i++) {
+ QString mime = types.at(i);
+ if (mime.startsWith("audio/") || mime.startsWith("video/"))
+ supported.add(mime);
+ }
+}
+
+MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& mime, const String& codec)
+{
+ if (!mime.startsWith("audio/") && !mime.startsWith("video/"))
+ return MediaPlayer::IsNotSupported;
+
+ if (QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMultimedia::ProbablySupported)
+ return MediaPlayer::IsSupported;
+
+ return MediaPlayer::MayBeSupported;
+}
+
+MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
+ : m_player(player)
+ , m_mediaPlayer(new QMediaPlayer)
+ , m_mediaPlayerControl(0)
+ , m_videoItem(new QGraphicsVideoItem)
+ , m_videoScene(new QGraphicsScene)
+ , m_networkState(MediaPlayer::Empty)
+ , m_readyState(MediaPlayer::HaveNothing)
+ , m_isVisible(false)
+ , m_isSeeking(false)
+ , m_composited(false)
+ , m_queuedSeek(-1)
+{
+ m_videoItem->setMediaObject(m_mediaPlayer);
+ m_videoScene->addItem(m_videoItem);
+
+ // Signal Handlers
+ connect(m_mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ connect(m_mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)),
+ this, SLOT(stateChanged(QMediaPlayer::State)));
+ connect(m_mediaPlayer, SIGNAL(error(QMediaPlayer::Error)),
+ this, SLOT(handleError(QMediaPlayer::Error)));
+ connect(m_mediaPlayer, SIGNAL(durationChanged(qint64)),
+ this, SLOT(durationChanged(qint64)));
+ connect(m_mediaPlayer, SIGNAL(positionChanged(qint64)),
+ this, SLOT(positionChanged(qint64)));
+ connect(m_mediaPlayer, SIGNAL(volumeChanged(int)),
+ this, SLOT(volumeChanged(int)));
+ connect(m_mediaPlayer, SIGNAL(mutedChanged(bool)),
+ this, SLOT(mutedChanged(bool)));
+ connect(m_videoScene, SIGNAL(changed(QList<QRectF>)),
+ this, SLOT(repaint()));
+ connect(m_videoItem, SIGNAL(nativeSizeChanged(QSizeF)),
+ this, SLOT(nativeSizeChanged(QSizeF)));
+
+ // Grab the player control
+ QMediaService* service = m_mediaPlayer->service();
+ if (service) {
+ m_mediaPlayerControl = qobject_cast<QMediaPlayerControl *>(
+ service->control(QMediaPlayerControl_iid));
+ }
+}
+
+MediaPlayerPrivate::~MediaPlayerPrivate()
+{
+ delete m_mediaPlayer;
+ delete m_videoScene;
+}
+
+bool MediaPlayerPrivate::hasVideo() const
+{
+ return m_mediaPlayer->isVideoAvailable();
+}
+
+bool MediaPlayerPrivate::hasAudio() const
+{
+ return true;
+}
+
+void MediaPlayerPrivate::load(const String& url)
+{
+ // We are now loading
+ if (m_networkState != MediaPlayer::Loading) {
+ m_networkState = MediaPlayer::Loading;
+ m_player->networkStateChanged();
+ }
+
+ // And we don't have any data yet
+ if (m_readyState != MediaPlayer::HaveNothing) {
+ m_readyState = MediaPlayer::HaveNothing;
+ m_player->readyStateChanged();
+ }
+
+ const QUrl rUrl = QUrl(QString(url));
+ const QString scheme = rUrl.scheme().toLower();
+
+ // Grab the client media element
+ HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_player->mediaPlayerClient());
+
+ // Construct the media content with a network request if the resource is http[s]
+ if (scheme == "http" || scheme == "https") {
+ QNetworkRequest request = QNetworkRequest(rUrl);
+
+ // Grab the current document
+ Document* document = element->document();
+ if (!document)
+ document = element->ownerDocument();
+
+ // Grab the frame and network manager
+ Frame* frame = document ? document->frame() : 0;
+ FrameLoaderClientQt* frameLoader = frame ? static_cast<FrameLoaderClientQt*>(frame->loader()->client()) : 0;
+ QNetworkAccessManager* manager = frameLoader ? frameLoader->webFrame()->page()->networkAccessManager() : 0;
+
+ if (document && manager) {
+ // Set the cookies
+ QNetworkCookieJar* jar = manager->cookieJar();
+ QList<QNetworkCookie> cookies = jar->cookiesForUrl(rUrl);
+
+ // Don't set the header if there are no cookies.
+ // This prevents a warning from being emitted.
+ if (!cookies.isEmpty())
+ request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies));
+
+ // Set the refferer, but not when requesting insecure content from a secure page
+ QUrl documentUrl = QUrl(QString(document->documentURI()));
+ if (documentUrl.scheme().toLower() == "http" || scheme == "https")
+ request.setRawHeader("Referer", documentUrl.toEncoded());
+
+ // Set the user agent
+ request.setRawHeader("User-Agent", frameLoader->userAgent(rUrl).utf8().data());
+ }
+
+ m_mediaPlayer->setMedia(QMediaContent(request));
+ } else {
+ // Otherwise, just use the URL
+ m_mediaPlayer->setMedia(QMediaContent(rUrl));
+ }
+
+ // Set the current volume and mute status
+ // We get these from the element, rather than the player, in case we have
+ // transitioned from a media engine which doesn't support muting, to a media
+ // engine which does.
+ m_mediaPlayer->setMuted(element->muted());
+ m_mediaPlayer->setVolume(static_cast<int>(element->volume() * 100.0));
+}
+
+void MediaPlayerPrivate::cancelLoad()
+{
+ m_mediaPlayer->setMedia(QMediaContent());
+ updateStates();
+}
+
+void MediaPlayerPrivate::play()
+{
+ if (m_mediaPlayer->state() != QMediaPlayer::PlayingState)
+ m_mediaPlayer->play();
+}
+
+void MediaPlayerPrivate::pause()
+{
+ if (m_mediaPlayer->state() == QMediaPlayer::PlayingState)
+ m_mediaPlayer->pause();
+}
+
+bool MediaPlayerPrivate::paused() const
+{
+ return (m_mediaPlayer->state() != QMediaPlayer::PlayingState);
+}
+
+void MediaPlayerPrivate::seek(float position)
+{
+ if (!m_mediaPlayer->isSeekable())
+ return;
+
+ if (m_mediaPlayerControl && !m_mediaPlayerControl->availablePlaybackRanges().contains(position * 1000))
+ return;
+
+ if (m_isSeeking)
+ return;
+
+ if (position > duration())
+ position = duration();
+
+ // Seeking is most reliable when we're paused.
+ // Webkit will try to pause before seeking, but due to the asynchronous nature
+ // of the backend, the player may not actually be paused yet.
+ // In this case, we should queue the seek and wait until pausing has completed
+ // before attempting to seek.
+ if (m_mediaPlayer->state() == QMediaPlayer::PlayingState) {
+ m_mediaPlayer->pause();
+ m_isSeeking = true;
+ m_queuedSeek = static_cast<qint64>(position * 1000);
+
+ // Set a timeout, so that in the event that we don't get a state changed
+ // signal, we still attempt the seek.
+ QTimer::singleShot(1000, this, SLOT(queuedSeekTimeout()));
+ } else {
+ m_isSeeking = true;
+ m_mediaPlayer->setPosition(static_cast<qint64>(position * 1000));
+
+ // Set a timeout, in case we don't get a position changed signal
+ QTimer::singleShot(10000, this, SLOT(seekTimeout()));
+ }
+}
+
+bool MediaPlayerPrivate::seeking() const
+{
+ return m_isSeeking;
+}
+
+float MediaPlayerPrivate::duration() const
+{
+ if (m_readyState < MediaPlayer::HaveMetadata)
+ return 0.0f;
+
+ float duration = m_mediaPlayer->duration() / 1000.0f;
+
+ // We are streaming
+ if (duration <= 0.0f)
+ duration = std::numeric_limits<float>::infinity();
+
+ return duration;
+}
+
+float MediaPlayerPrivate::currentTime() const
+{
+ float currentTime = m_mediaPlayer->position() / 1000.0f;
+ return currentTime;
+}
+
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
+{
+ RefPtr<TimeRanges> buffered = TimeRanges::create();
+
+ if (!m_mediaPlayerControl)
+ return buffered;
+
+ QMediaTimeRange playbackRanges = m_mediaPlayerControl->availablePlaybackRanges();
+
+ foreach (const QMediaTimeInterval interval, playbackRanges.intervals()) {
+ float rangeMin = static_cast<float>(interval.start()) / 1000.0f;
+ float rangeMax = static_cast<float>(interval.end()) / 1000.0f;
+ buffered->add(rangeMin, rangeMax);
+ }
+
+ return buffered.release();
+}
+
+float MediaPlayerPrivate::maxTimeSeekable() const
+{
+ if (!m_mediaPlayerControl)
+ return 0;
+
+ return static_cast<float>(m_mediaPlayerControl->availablePlaybackRanges().latestTime()) / 1000.0f;
+}
+
+unsigned MediaPlayerPrivate::bytesLoaded() const
+{
+ unsigned percentage = m_mediaPlayer->bufferStatus();
+
+ if (percentage == 100) {
+ if (m_networkState != MediaPlayer::Idle) {
+ m_networkState = MediaPlayer::Idle;
+ m_player->networkStateChanged();
+ }
+ if (m_readyState != MediaPlayer::HaveEnoughData) {
+ m_readyState = MediaPlayer::HaveEnoughData;
+ m_player->readyStateChanged();
+ }
+ }
+
+ QLatin1String bytesLoadedKey("bytes-loaded");
+ if (m_mediaPlayer->availableExtendedMetaData().contains(bytesLoadedKey))
+ return m_mediaPlayer->extendedMetaData(bytesLoadedKey).toInt();
+
+ return percentage;
+}
+
+unsigned MediaPlayerPrivate::totalBytes() const
+{
+ if (m_mediaPlayer->availableMetaData().contains(QtMultimedia::Size))
+ return m_mediaPlayer->metaData(QtMultimedia::Size).toInt();
+
+ return 100;
+}
+
+void MediaPlayerPrivate::setRate(float rate)
+{
+ m_mediaPlayer->setPlaybackRate(rate);
+}
+
+void MediaPlayerPrivate::setVolume(float volume)
+{
+ m_mediaPlayer->setVolume(static_cast<int>(volume * 100.0));
+}
+
+bool MediaPlayerPrivate::supportsMuting() const
+{
+ return true;
+}
+
+void MediaPlayerPrivate::setMuted(bool muted)
+{
+ m_mediaPlayer->setMuted(muted);
+}
+
+MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const
+{
+ return m_networkState;
+}
+
+MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const
+{
+ return m_readyState;
+}
+
+void MediaPlayerPrivate::setVisible(bool visible)
+{
+ m_isVisible = visible;
+}
+
+void MediaPlayerPrivate::mediaStatusChanged(QMediaPlayer::MediaStatus)
+{
+ updateStates();
+}
+
+void MediaPlayerPrivate::handleError(QMediaPlayer::Error)
+{
+ updateStates();
+}
+
+void MediaPlayerPrivate::stateChanged(QMediaPlayer::State state)
+{
+ if (state != QMediaPlayer::PlayingState && m_isSeeking && m_queuedSeek >= 0) {
+ m_mediaPlayer->setPosition(m_queuedSeek);
+ m_queuedSeek = -1;
+ }
+}
+
+void MediaPlayerPrivate::nativeSizeChanged(const QSizeF&)
+{
+ m_player->sizeChanged();
+}
+
+void MediaPlayerPrivate::queuedSeekTimeout()
+{
+ // If we haven't heard anything, assume the player is now paused
+ // and we can attempt the seek
+ if (m_isSeeking && m_queuedSeek >= 0) {
+ m_mediaPlayer->setPosition(m_queuedSeek);
+ m_queuedSeek = -1;
+
+ // Set a timeout, in case we don't get a position changed signal
+ QTimer::singleShot(10000, this, SLOT(seekTimeout()));
+ }
+}
+
+void MediaPlayerPrivate::seekTimeout()
+{
+ // If we haven't heard anything, assume the seek succeeded
+ if (m_isSeeking) {
+ m_player->timeChanged();
+ m_isSeeking = false;
+ }
+}
+
+void MediaPlayerPrivate::positionChanged(qint64)
+{
+ // Only propogate this event if we are seeking
+ if (m_isSeeking && m_queuedSeek == -1) {
+ m_player->timeChanged();
+ m_isSeeking = false;
+ }
+}
+
+void MediaPlayerPrivate::durationChanged(qint64)
+{
+ m_player->durationChanged();
+}
+
+void MediaPlayerPrivate::volumeChanged(int volume)
+{
+ m_player->volumeChanged(static_cast<float>(volume) / 100.0);
+}
+
+void MediaPlayerPrivate::mutedChanged(bool muted)
+{
+ m_player->muteChanged(muted);
+}
+
+void MediaPlayerPrivate::updateStates()
+{
+ // Store the old states so that we can detect a change and raise change events
+ MediaPlayer::NetworkState oldNetworkState = m_networkState;
+ MediaPlayer::ReadyState oldReadyState = m_readyState;
+
+ QMediaPlayer::MediaStatus currentStatus = m_mediaPlayer->mediaStatus();
+ QMediaPlayer::Error currentError = m_mediaPlayer->error();
+
+ if (currentError != QMediaPlayer::NoError) {
+ m_readyState = MediaPlayer::HaveNothing;
+ if (currentError == QMediaPlayer::FormatError)
+ m_networkState = MediaPlayer::FormatError;
+ else
+ m_networkState = MediaPlayer::NetworkError;
+ } else if (currentStatus == QMediaPlayer::UnknownMediaStatus
+ || currentStatus == QMediaPlayer::NoMedia) {
+ m_networkState = MediaPlayer::Idle;
+ m_readyState = MediaPlayer::HaveNothing;
+ } else if (currentStatus == QMediaPlayer::LoadingMedia) {
+ m_networkState = MediaPlayer::Loading;
+ m_readyState = MediaPlayer::HaveNothing;
+ } else if (currentStatus == QMediaPlayer::LoadedMedia) {
+ m_networkState = MediaPlayer::Loading;
+ m_readyState = MediaPlayer::HaveMetadata;
+ } else if (currentStatus == QMediaPlayer::BufferingMedia) {
+ m_networkState = MediaPlayer::Loading;
+ m_readyState = MediaPlayer::HaveFutureData;
+ } else if (currentStatus == QMediaPlayer::StalledMedia) {
+ m_networkState = MediaPlayer::Loading;
+ m_readyState = MediaPlayer::HaveCurrentData;
+ } else if (currentStatus == QMediaPlayer::BufferedMedia
+ || currentStatus == QMediaPlayer::EndOfMedia) {
+ m_networkState = MediaPlayer::Idle;
+ m_readyState = MediaPlayer::HaveEnoughData;
+ } else if (currentStatus == QMediaPlayer::InvalidMedia) {
+ m_networkState = MediaPlayer::NetworkError;
+ m_readyState = MediaPlayer::HaveNothing;
+ }
+
+ // Log the state changes and raise the state change events
+ // NB: The readyStateChanged event must come before the networkStateChanged event.
+ // Breaking this invariant will cause the resource selection algorithm for multiple
+ // sources to fail.
+ if (m_readyState != oldReadyState)
+ m_player->readyStateChanged();
+
+ if (m_networkState != oldNetworkState)
+ m_player->networkStateChanged();
+}
+
+void MediaPlayerPrivate::setSize(const IntSize& size)
+{
+ if (size == m_currentSize)
+ return;
+
+ m_currentSize = size;
+ m_videoItem->setSize(QSizeF(QSize(size)));
+}
+
+IntSize MediaPlayerPrivate::naturalSize() const
+{
+ if (!hasVideo() || m_readyState < MediaPlayer::HaveMetadata)
+ return IntSize();
+
+ return IntSize(m_videoItem->nativeSize().toSize());
+}
+
+void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_composited)
+ return;
+#endif
+ if (context->paintingDisabled())
+ return;
+
+ if (!m_isVisible)
+ return;
+
+ // Grab the painter and widget
+ QPainter* painter = context->platformContext();
+
+ // Render the video
+ m_videoScene->render(painter, QRectF(QRect(rect)), m_videoItem->sceneBoundingRect());
+}
+
+void MediaPlayerPrivate::repaint()
+{
+ m_player->repaint();
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+void MediaPlayerPrivate::acceleratedRenderingStateChanged()
+{
+ bool composited = m_player->mediaPlayerClient()->mediaPlayerRenderingCanBeAccelerated(m_player);
+ if (composited == m_composited)
+ return;
+
+ m_composited = composited;
+ if (composited)
+ m_videoScene->removeItem(m_videoItem);
+ else
+ m_videoScene->addItem(m_videoItem);
+}
+
+PlatformLayer* MediaPlayerPrivate::platformLayer() const
+{
+ return m_composited ? m_videoItem : 0;
+}
+#endif
+
+} // namespace WebCore
+
+#include "moc_MediaPlayerPrivateQt.cpp"
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
new file mode 100644
index 0000000..d72404c
--- /dev/null
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
@@ -0,0 +1,133 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef MediaPlayerPrivateQt_h
+#define MediaPlayerPrivateQt_h
+
+#include "MediaPlayerPrivate.h"
+
+#include <QMediaPlayer>
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+class QMediaPlayerControl;
+class QGraphicsVideoItem;
+class QGraphicsScene;
+QT_END_NAMESPACE
+
+namespace WebCore {
+
+class MediaPlayerPrivate : public QObject, public MediaPlayerPrivateInterface {
+
+ Q_OBJECT
+
+public:
+ static MediaPlayerPrivateInterface* create(MediaPlayer* player);
+ ~MediaPlayerPrivate();
+
+ static void registerMediaEngine(MediaEngineRegistrar);
+ static void getSupportedTypes(HashSet<String>&);
+ static MediaPlayer::SupportsType supportsType(const String&, const String&);
+ static bool isAvailable() { return true; }
+
+ bool hasVideo() const;
+ bool hasAudio() 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);
+
+ void setRate(float);
+ void setVolume(float);
+
+ bool supportsMuting() const;
+ void setMuted(bool);
+
+ MediaPlayer::NetworkState networkState() const;
+ MediaPlayer::ReadyState readyState() const;
+
+ PassRefPtr<TimeRanges> buffered() const;
+ float maxTimeSeekable() const;
+ unsigned bytesLoaded() const;
+ unsigned totalBytes() const;
+
+ void setVisible(bool);
+
+ IntSize naturalSize() const;
+ void setSize(const IntSize&);
+
+ void paint(GraphicsContext*, const IntRect&);
+
+ bool supportsFullscreen() const { return false; }
+
+#if USE(ACCELERATED_COMPOSITING)
+ // whether accelerated rendering is supported by the media engine for the current media.
+ virtual bool supportsAcceleratedRendering() const { return true; }
+ // called when the rendering system flips the into or out of accelerated rendering mode.
+ virtual void acceleratedRenderingStateChanged();
+ // returns an object that can be directly composited via GraphicsLayerQt (essentially a QGraphicsItem*)
+ virtual PlatformLayer* platformLayer() const;
+#endif
+
+private slots:
+ void mediaStatusChanged(QMediaPlayer::MediaStatus);
+ void handleError(QMediaPlayer::Error);
+ void stateChanged(QMediaPlayer::State);
+ void nativeSizeChanged(const QSizeF&);
+ void queuedSeekTimeout();
+ void seekTimeout();
+ void positionChanged(qint64);
+ void durationChanged(qint64);
+ void volumeChanged(int);
+ void mutedChanged(bool);
+ void repaint();
+
+private:
+ void updateStates();
+
+private:
+ MediaPlayerPrivate(MediaPlayer*);
+
+ MediaPlayer* m_player;
+ QMediaPlayer* m_mediaPlayer;
+ QMediaPlayerControl* m_mediaPlayerControl;
+ QGraphicsVideoItem* m_videoItem;
+ QGraphicsScene* m_videoScene;
+
+ mutable MediaPlayer::NetworkState m_networkState;
+ mutable MediaPlayer::ReadyState m_readyState;
+
+ IntSize m_currentSize;
+ bool m_isVisible;
+ bool m_isSeeking;
+ bool m_composited;
+ qint64 m_queuedSeek;
+};
+}
+
+#endif // MediaPlayerPrivateQt_h
diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp
index 507f029..ee4af7f 100644
--- a/WebCore/platform/graphics/qt/PathQt.cpp
+++ b/WebCore/platform/graphics/qt/PathQt.cpp
@@ -269,10 +269,12 @@ void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool antic
span += ea - sa;
}
- m_path.moveTo(QPointF(xc + radius * cos(sar),
+ // connect to the previous point by a straight line
+ m_path.lineTo(QPointF(xc + radius * cos(sar),
yc - radius * sin(sar)));
m_path.arcTo(xs, ys, width, height, sa, span);
+
}
void Path::addRect(const FloatRect& r)
diff --git a/WebCore/platform/graphics/qt/StillImageQt.cpp b/WebCore/platform/graphics/qt/StillImageQt.cpp
index 1db04a7..4653c58 100644
--- a/WebCore/platform/graphics/qt/StillImageQt.cpp
+++ b/WebCore/platform/graphics/qt/StillImageQt.cpp
@@ -57,8 +57,43 @@ void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
ctxt->save();
ctxt->setCompositeOperation(op);
+
+ // To support width or height is negative
+ float sx = src.x();
+ float sy = src.y();
+ float sw = src.width();
+ float sh = src.height();
+
+ if (sw < 0) {
+ sx = sx + sw;
+ sw = -sw;
+ }
+
+ if (sh < 0) {
+ sy = sy + sh;
+ sh = -sh;
+ }
+
+ float dx = dst.x();
+ float dy = dst.y();
+ float dw = dst.width();
+ float dh = dst.height();
+
+ if (dw < 0) {
+ dx = dx + dw;
+ dw = -dw;
+ }
+
+ if (dh < 0) {
+ dy = dy + dh;
+ dh = -dh;
+ }
+
+ FloatRect srcM(sx, sy, sw, sh);
+ FloatRect dstM(dx, dy, dw, dh);
QPainter* painter(ctxt->platformContext());
- painter->drawPixmap(dst, m_pixmap, src);
+
+ painter->drawPixmap(dstM, m_pixmap, srcM);
ctxt->restore();
}
diff --git a/WebCore/platform/graphics/qt/TileQt.cpp b/WebCore/platform/graphics/qt/TileQt.cpp
new file mode 100644
index 0000000..9628448
--- /dev/null
+++ b/WebCore/platform/graphics/qt/TileQt.cpp
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "Tile.h"
+
+#if ENABLE(TILED_BACKING_STORE)
+
+#include "GraphicsContext.h"
+#include "TiledBackingStore.h"
+#include "TiledBackingStoreClient.h"
+#include <QApplication>
+#include <QObject>
+#include <QPainter>
+#include <QRegion>
+
+namespace WebCore {
+
+static const unsigned checkerSize = 16;
+static const unsigned checkerColor1 = 0xff555555;
+static const unsigned checkerColor2 = 0xffaaaaaa;
+
+static QPixmap& checkeredPixmap()
+{
+ static QPixmap* pixmap;
+ if (!pixmap) {
+ pixmap = new QPixmap(checkerSize, checkerSize);
+ QPainter painter(pixmap);
+ QColor color1(checkerColor1);
+ QColor color2(checkerColor2);
+ for (unsigned y = 0; y < checkerSize; y += checkerSize / 2) {
+ bool alternate = y % checkerSize;
+ for (unsigned x = 0; x < checkerSize; x += checkerSize / 2) {
+ painter.fillRect(x, y, checkerSize / 2, checkerSize / 2, alternate ? color1 : color2);
+ alternate = !alternate;
+ }
+ }
+ }
+ return *pixmap;
+}
+
+Tile::Tile(TiledBackingStore* backingStore, const Coordinate& tileCoordinate)
+ : m_backingStore(backingStore)
+ , m_coordinate(tileCoordinate)
+ , m_rect(m_backingStore->tileRectForCoordinate(tileCoordinate))
+ , m_buffer(0)
+ , m_backBuffer(0)
+ , m_dirtyRegion(new QRegion(m_rect))
+{
+}
+
+Tile::~Tile()
+{
+ delete m_buffer;
+ delete m_backBuffer;
+ delete m_dirtyRegion;
+}
+
+bool Tile::isDirty() const
+{
+ return !m_dirtyRegion->isEmpty();
+}
+
+bool Tile::isReadyToPaint() const
+{
+ return m_buffer;
+}
+
+void Tile::invalidate(const IntRect& dirtyRect)
+{
+ IntRect tileDirtyRect = intersection(dirtyRect, m_rect);
+ if (tileDirtyRect.isEmpty())
+ return;
+
+ *m_dirtyRegion += tileDirtyRect;
+}
+
+void Tile::updateBackBuffer()
+{
+ if (m_buffer && !isDirty())
+ return;
+
+ if (!m_backBuffer) {
+ if (!m_buffer)
+ m_backBuffer = new QPixmap(m_backingStore->m_tileSize.width(), m_backingStore->m_tileSize.height());
+ else {
+ // Currently all buffers are updated synchronously at the same time so there is no real need
+ // to have separate back and front buffers. Just use the existing buffer.
+ m_backBuffer = m_buffer;
+ m_buffer = 0;
+ }
+ }
+
+ QVector<QRect> dirtyRects = m_dirtyRegion->rects();
+ *m_dirtyRegion = QRegion();
+
+ QPainter painter(m_backBuffer);
+ GraphicsContext context(&painter);
+ context.translate(-m_rect.x(), -m_rect.y());
+
+ int size = dirtyRects.size();
+ for (int n = 0; n < size; ++n) {
+ context.save();
+ IntRect rect = dirtyRects[n];
+ context.clip(FloatRect(rect));
+ context.scale(FloatSize(m_backingStore->m_contentsScale, m_backingStore->m_contentsScale));
+ m_backingStore->m_client->tiledBackingStorePaint(&context, m_backingStore->mapToContents(rect));
+ context.restore();
+ }
+}
+
+void Tile::swapBackBufferToFront()
+{
+ if (!m_backBuffer)
+ return;
+ delete m_buffer;
+ m_buffer = m_backBuffer;
+ m_backBuffer = 0;
+}
+
+void Tile::paint(GraphicsContext* context, const IntRect& rect)
+{
+ if (!m_buffer)
+ return;
+
+ IntRect target = intersection(rect, m_rect);
+ IntRect source((target.x() - m_rect.x()),
+ (target.y() - m_rect.y()),
+ target.width(),
+ target.height());
+
+ context->platformContext()->drawPixmap(target, *m_buffer, source);
+}
+
+void Tile::paintCheckerPattern(GraphicsContext* context, const FloatRect& target)
+{
+ QPainter* painter = context->platformContext();
+ QTransform worldTransform = painter->worldTransform();
+ qreal scaleX = worldTransform.m11();
+ qreal scaleY = worldTransform.m22();
+
+ QRect targetViewRect = QRectF(target.x() * scaleX,
+ target.y() * scaleY,
+ target.width() * scaleX,
+ target.height() * scaleY).toAlignedRect();
+
+ QTransform adjustedTransform(1., worldTransform.m12(), worldTransform.m13(),
+ worldTransform.m21(), 1., worldTransform.m23(),
+ worldTransform.m31(), worldTransform.m32(), worldTransform.m33());
+ painter->setWorldTransform(adjustedTransform);
+
+ painter->drawTiledPixmap(targetViewRect,
+ checkeredPixmap(),
+ QPoint(targetViewRect.left() % checkerSize,
+ targetViewRect.top() % checkerSize));
+
+ painter->setWorldTransform(worldTransform);
+}
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
index cd86e6d..cc4ca2e 100644
--- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
@@ -33,6 +33,8 @@
#include "Image.h"
#include "NativeImageSkia.h"
+#include <algorithm>
+
namespace WebCore {
bool GraphicsContext3D::getImageData(Image* image,
@@ -59,13 +61,17 @@ bool GraphicsContext3D::getImageData(Image* image,
ASSERT(rowBytes == width * 4);
uint8_t* pixels = reinterpret_cast<uint8_t*>(skiaImage->getPixels());
outputVector.resize(rowBytes * height);
- memcpy(outputVector.data(), pixels, rowBytes * height);
+ int size = rowBytes * height;
+ memcpy(outputVector.data(), pixels, size);
*hasAlphaChannel = true;
if (!premultiplyAlpha)
// FIXME: must fetch the image data before the premultiplication step
*neededAlphaOp = kAlphaDoUnmultiply;
- // FIXME: remove this dependency on desktop OpenGL
- *format = 0x80E1; // GL_BGRA
+ // Convert from BGRA to RGBA. FIXME: add GL_BGRA extension support
+ // to all underlying OpenGL implementations.
+ for (int i = 0; i < size; i += 4)
+ std::swap(outputVector[i], outputVector[i + 2]);
+ *format = RGBA;
return true;
}
diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp
index ba9f824..b1bfbdd 100644
--- a/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -457,8 +457,7 @@ void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt,
PassRefPtr<BitmapImageSingleFrameSkia> BitmapImageSingleFrameSkia::create(const SkBitmap& bitmap)
{
RefPtr<BitmapImageSingleFrameSkia> image(adoptRef(new BitmapImageSingleFrameSkia()));
- if (!bitmap.copyTo(&image->m_nativeImage, bitmap.config()))
- return 0;
+ bitmap.copyTo(&image->m_nativeImage, bitmap.config());
return image.release();
}
diff --git a/WebCore/platform/graphics/transforms/AffineTransform.cpp b/WebCore/platform/graphics/transforms/AffineTransform.cpp
index d6688d2..be18e07 100644
--- a/WebCore/platform/graphics/transforms/AffineTransform.cpp
+++ b/WebCore/platform/graphics/transforms/AffineTransform.cpp
@@ -314,14 +314,28 @@ FloatRect AffineTransform::mapRect(const FloatRect& rect) const
return mappedRect;
}
- FloatQuad q(rect);
+ FloatQuad result;
+ result.setP1(mapPoint(rect.location()));
+ result.setP2(mapPoint(FloatPoint(rect.right(), rect.y())));
+ result.setP3(mapPoint(FloatPoint(rect.right(), rect.bottom())));
+ result.setP4(mapPoint(FloatPoint(rect.x(), rect.bottom())));
+ return result.boundingBox();
+}
+
+FloatQuad AffineTransform::mapQuad(const FloatQuad& q) const
+{
+ if (isIdentityOrTranslation()) {
+ FloatQuad mappedQuad(q);
+ mappedQuad.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5]));
+ return mappedQuad;
+ }
FloatQuad result;
result.setP1(mapPoint(q.p1()));
result.setP2(mapPoint(q.p2()));
result.setP3(mapPoint(q.p3()));
result.setP4(mapPoint(q.p4()));
- return result.boundingBox();
+ return result;
}
void AffineTransform::blend(const AffineTransform& from, double progress)
diff --git a/WebCore/platform/graphics/transforms/AffineTransform.h b/WebCore/platform/graphics/transforms/AffineTransform.h
index 00631c2..289ec54 100644
--- a/WebCore/platform/graphics/transforms/AffineTransform.h
+++ b/WebCore/platform/graphics/transforms/AffineTransform.h
@@ -36,6 +36,8 @@
#include <CoreGraphics/CGAffineTransform.h>
#elif PLATFORM(CAIRO)
#include <cairo.h>
+#elif PLATFORM(OPENVG)
+#include "VGUtils.h"
#elif PLATFORM(QT)
#include <QTransform>
#elif PLATFORM(SKIA)
@@ -74,6 +76,7 @@ public:
IntRect mapRect(const IntRect&) const;
FloatRect mapRect(const FloatRect&) const;
+ FloatQuad mapQuad(const FloatQuad&) const;
bool isIdentity() const;
@@ -120,6 +123,11 @@ public:
{
return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && m_transform[3] == 1;
}
+
+ bool isIdentityOrTranslationOrFlipped() const
+ {
+ return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && (m_transform[3] == 1 || m_transform[3] == -1);
+ }
bool operator== (const AffineTransform& m2) const
{
@@ -152,6 +160,8 @@ public:
operator CGAffineTransform() const;
#elif PLATFORM(CAIRO)
operator cairo_matrix_t() const;
+#elif PLATFORM(OPENVG)
+ operator VGMatrix() const;
#elif PLATFORM(QT)
operator QTransform() const;
#elif PLATFORM(SKIA)
diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp
index 8ed8712..e4eb159 100644
--- a/WebCore/platform/graphics/win/FontCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -321,12 +321,9 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
ASSERT_NOT_REACHED();
}
- if (font->platformData().useGDI()) {
- static bool canCreateCGFontWithLOGFONT = wkCanCreateCGFontWithLOGFONT();
- if (!shouldUseFontSmoothing || !canCreateCGFontWithLOGFONT && (graphicsContext->textDrawingMode() & cTextStroke)) {
- drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
- return;
- }
+ if (font->platformData().useGDI() && !shouldUseFontSmoothing) {
+ drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+ return;
}
uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext, shouldUseFontSmoothing);
diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp
index 8869a90..d050243 100644
--- a/WebCore/platform/graphics/win/FontCacheWin.cpp
+++ b/WebCore/platform/graphics/win/FontCacheWin.cpp
@@ -301,22 +301,68 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
return 0;
}
+static SimpleFontData* fontDataFromDescriptionAndLogFont(FontCache* fontCache, const FontDescription& fontDescription, const LOGFONT& font, AtomicString& outFontFamilyName)
+{
+ AtomicString familyName = String(font.lfFaceName, wcsnlen(font.lfFaceName, LF_FACESIZE));
+ SimpleFontData* fontData = fontCache->getCachedFontData(fontDescription, familyName);
+ if (fontData)
+ outFontFamilyName = familyName;
+ return fontData;
+}
+
SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
{
+ DEFINE_STATIC_LOCAL(AtomicString, fallbackFontName, ());
+ if (!fallbackFontName.isEmpty())
+ return getCachedFontData(fontDescription, fallbackFontName);
+
// 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");
- if (SimpleFontData* simpleFont = getCachedFontData(fontDescription, timesStr))
- return simpleFont;
- 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));
+ // Search all typical Windows-installed full Unicode fonts.
+ // Sorted by most to least glyphs according to http://en.wikipedia.org/wiki/Unicode_typefaces
+ // Start with Times New Roman also since it is the default if the user doesn't change prefs.
+ static AtomicString fallbackFonts[] = {
+ AtomicString("Times New Roman"),
+ AtomicString("Microsoft Sans Serif"),
+ AtomicString("Tahoma"),
+ AtomicString("Lucida Sans Unicode"),
+ AtomicString("Arial")
+ };
+ SimpleFontData* simpleFont;
+ for (int i = 0; i < ARRAYSIZE(fallbackFonts); ++i) {
+ if (simpleFont = getCachedFontData(fontDescription, fallbackFonts[i])) {
+ fallbackFontName = fallbackFonts[i];
+ return simpleFont;
+ }
}
- return getCachedFontData(fontDescription, defaultGUIFontFamily);
+
+ // Fall back to the DEFAULT_GUI_FONT if no known Unicode fonts are available.
+ if (HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))) {
+ LOGFONT defaultGUILogFont;
+ GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont);
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, defaultGUILogFont, fallbackFontName))
+ return simpleFont;
+ }
+
+ // Fall back to Non-client metrics fonts.
+ NONCLIENTMETRICS nonClientMetrics = {0};
+ nonClientMetrics.cbSize = sizeof(nonClientMetrics);
+ if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) {
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfMessageFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfMenuFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfStatusFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfCaptionFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfSmCaptionFont, fallbackFontName))
+ return simpleFont;
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
}
static LONG toGDIFontWeight(FontWeight fontWeight)
@@ -517,14 +563,9 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
// This masks rounding errors related to the HFONT metrics being different from the CGFont metrics.
// FIXME: We will eventually want subpixel precision for GDI mode, but the scaled rendering doesn't
// look as nice. That may be solvable though.
-#if PLATFORM(CG)
- bool canCreateCGFontWithLOGFONT = wkCanCreateCGFontWithLOGFONT();
-#else
- bool canCreateCGFontWithLOGFONT = true;
-#endif
LONG weight = adjustedGDIFontWeight(toGDIFontWeight(fontDescription.weight()), family);
HFONT hfont = createGDIFont(family, weight, fontDescription.italic(),
- fontDescription.computedPixelSize() * (useGDI ? 1 : 32), useGDI && canCreateCGFontWithLOGFONT);
+ fontDescription.computedPixelSize() * (useGDI ? 1 : 32), useGDI);
if (!hfont)
return 0;
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
index b2d1b32..e9f83ab 100644
--- a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
@@ -48,7 +48,6 @@ SOFT_LINK(T2embed, TTDeleteEmbeddedFont, LONG, __stdcall, (HANDLE hFontReference
FontCustomPlatformData::~FontCustomPlatformData()
{
- CGFontRelease(m_cgFont);
if (m_fontReference) {
if (m_name.isNull()) {
ASSERT(T2embedLibrary());
@@ -61,7 +60,6 @@ FontCustomPlatformData::~FontCustomPlatformData()
FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontRenderingMode renderingMode)
{
- ASSERT(wkCanCreateCGFontWithLOGFONT() || m_cgFont);
ASSERT(m_fontReference);
ASSERT(T2embedLibrary());
@@ -88,35 +86,8 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
HFONT hfont = CreateFontIndirect(&logFont);
- if (wkCanCreateCGFontWithLOGFONT()) {
- RetainPtr<CGFontRef> cgFont(AdoptCF, CGFontCreateWithPlatformFont(&logFont));
- return FontPlatformData(hfont, cgFont.get(), size, bold, italic, renderingMode == AlternateRenderingMode);
- }
-
- wkSetFontPlatformInfo(m_cgFont, &logFont, free);
- return FontPlatformData(hfont, m_cgFont, size, bold, italic, renderingMode == AlternateRenderingMode);
-}
-
-const void* getData(void* info)
-{
- SharedBuffer* buffer = static_cast<SharedBuffer*>(info);
- buffer->ref();
- return (void*)buffer->data();
-}
-
-void releaseData(void* info, const void* data)
-{
- static_cast<SharedBuffer*>(info)->deref();
-}
-
-size_t getBytesWithOffset(void *info, void* buffer, size_t offset, size_t count)
-{
- SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
- size_t availBytes = count;
- if (offset + count > sharedBuffer->size())
- availBytes -= (offset + count) - sharedBuffer->size();
- memcpy(buffer, sharedBuffer->data() + offset, availBytes);
- return availBytes;
+ RetainPtr<CGFontRef> cgFont(AdoptCF, CGFontCreateWithPlatformFont(&logFont));
+ return FontPlatformData(hfont, cgFont.get(), size, bold, italic, renderingMode == AlternateRenderingMode);
}
// Streams the concatenation of a header and font data.
@@ -196,16 +167,6 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
ASSERT_ARG(buffer, buffer);
ASSERT(T2embedLibrary());
- RetainPtr<CGFontRef> cgFont;
- if (!wkCanCreateCGFontWithLOGFONT()) {
- // Get CG to create the font.
- CGDataProviderDirectAccessCallbacks callbacks = { &getData, &releaseData, &getBytesWithOffset, NULL };
- RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirectAccess(buffer, buffer->size(), &callbacks));
- cgFont.adoptCF(CGFontCreateWithDataProvider(dataProvider.get()));
- if (!cgFont)
- return 0;
- }
-
// Introduce the font to GDI. AddFontMemResourceEx cannot be used, because it will pollute the process's
// font namespace (Windows has no API for creating an HFONT from data without exposing the font to the
// entire process first). TTLoadEmbeddedFont lets us override the font family name, so using a unique name
@@ -236,7 +197,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
return 0;
}
- return new FontCustomPlatformData(cgFont.releaseRef(), fontReference, fontName);
+ return new FontCustomPlatformData(fontReference, fontName);
}
}
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformData.h b/WebCore/platform/graphics/win/FontCustomPlatformData.h
index 34a9851..f75f12a 100644
--- a/WebCore/platform/graphics/win/FontCustomPlatformData.h
+++ b/WebCore/platform/graphics/win/FontCustomPlatformData.h
@@ -33,9 +33,8 @@ class FontPlatformData;
class SharedBuffer;
struct FontCustomPlatformData : Noncopyable {
- FontCustomPlatformData(CGFontRef cgFont, HANDLE fontReference, const String& name)
- : m_cgFont(cgFont)
- , m_fontReference(fontReference)
+ FontCustomPlatformData(HANDLE fontReference, const String& name)
+ : m_fontReference(fontReference)
, m_name(name)
{
}
@@ -44,7 +43,6 @@ struct FontCustomPlatformData : Noncopyable {
FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode);
- CGFontRef m_cgFont;
HANDLE m_fontReference;
String m_name;
};
diff --git a/WebCore/platform/graphics/win/FontDatabase.cpp b/WebCore/platform/graphics/win/FontDatabase.cpp
deleted file mode 100644
index 22ad4a6..0000000
--- a/WebCore/platform/graphics/win/FontDatabase.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * 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
- * 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 "FontDatabase.h"
-
-#include "CString.h"
-#include "FileSystem.h"
-#include "PlatformString.h"
-#include <WebKitSystemInterface/WebKitSystemInterface.h>
-#include <shlobj.h>
-#include <wtf/RetainPtr.h>
-
-namespace WebCore {
-
-static String systemFontsDirectory()
-{
- static bool initialized;
- static String directory;
-
- if (!initialized) {
- initialized = true;
-
- Vector<UChar> buffer(MAX_PATH);
- if (FAILED(SHGetFolderPath(0, CSIDL_FONTS | CSIDL_FLAG_CREATE, 0, 0, buffer.data())))
- return directory;
- buffer.resize(wcslen(buffer.data()));
-
- directory = String::adopt(buffer);
- }
-
- return directory;
-}
-
-static String fontsPlistPath()
-{
- static String path = pathByAppendingComponent(localUserSpecificStorageDirectory(), "FontsList.plist");
- return path;
-}
-
-static bool systemHasFontsNewerThanFontsPlist()
-{
- WIN32_FILE_ATTRIBUTE_DATA plistAttributes = {0};
- if (!GetFileAttributesEx(fontsPlistPath().charactersWithNullTermination(), GetFileExInfoStandard, &plistAttributes))
- return true;
-
- WIN32_FILE_ATTRIBUTE_DATA fontsDirectoryAttributes = {0};
- if (!GetFileAttributesEx(systemFontsDirectory().charactersWithNullTermination(), GetFileExInfoStandard, &fontsDirectoryAttributes))
- return true;
-
- return CompareFileTime(&plistAttributes.ftLastWriteTime, &fontsDirectoryAttributes.ftLastWriteTime) < 0;
-}
-
-static RetainPtr<CFPropertyListRef> readFontPlist()
-{
- CString plistPath = fontsPlistPath().utf8();
-
- RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateFromFileSystemRepresentation(0, reinterpret_cast<const UInt8*>(plistPath.data()), plistPath.length(), false));
- if (!url)
- return 0;
-
- RetainPtr<CFReadStreamRef> stream(AdoptCF, CFReadStreamCreateWithFile(0, url.get()));
- if (!stream)
- return 0;
-
- if (!CFReadStreamOpen(stream.get()))
- return 0;
-
- CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0 | kCFPropertyListXMLFormat_v1_0;
- RetainPtr<CFPropertyListRef> plist(AdoptCF, CFPropertyListCreateFromStream(0, stream.get(), 0, kCFPropertyListMutableContainersAndLeaves, &format, 0));
-
- CFReadStreamClose(stream.get());
-
- return plist;
-}
-
-static bool populateFontDatabaseFromPlist(CFPropertyListRef plist)
-{
- if (!plist)
- return false;
-
- wkAddFontsFromPlist(plist);
- return true;
-}
-
-static bool populateFontDatabaseFromFileSystem()
-{
- RetainPtr<CFStringRef> directory(AdoptCF, systemFontsDirectory().createCFString());
- if (!directory)
- return false;
-
- wkAddFontsInDirectory(directory.get());
- return true;
-}
-
-static CFStringRef fontFilenamesFromRegistryKey()
-{
- static CFStringRef key = CFSTR("WebKitFontFilenamesFromRegistry");
- return key;
-}
-
-static void writeFontDatabaseToPlist(CFPropertyListRef cgFontDBPropertyList, CFPropertyListRef filenamesFromRegistry)
-{
- 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;
- if (initialized)
- return;
- initialized = true;
-
- if (wkCanCreateCGFontWithLOGFONT())
- return;
-
- 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()) {
- wkAddFontsFromRegistry();
- RetainPtr<CFPropertyListRef> cgFontDBPropertyList(AdoptCF, wkCreateFontsPlist());
- writeFontDatabaseToPlist(cgFontDBPropertyList.get(), currentFilenamesFromRegistry.get());
- }
-}
-
-} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
index d605cf9..ed9073f 100644
--- a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
@@ -1,5 +1,5 @@
/*
- * This file is part of the internal font implementation. It should not be included by anyone other than
+ * This file is part of the internal font implementation. It should not be included by anyone other than
* FontMac.cpp, FontWin.cpp and Font.cpp.
*
* Copyright (C) 2006, 2007, 2008, 2009 Apple Inc.
@@ -109,29 +109,9 @@ static CFStringRef getPostScriptName(CFStringRef faceName, HDC dc)
void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName)
{
- if (wkCanCreateCGFontWithLOGFONT()) {
- LOGFONT logfont;
- GetObject(font, sizeof(logfont), &logfont);
- m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&logfont));
- return;
- }
-
- // Try the face name first. Windows may end up localizing this name, and CG doesn't know about
- // the localization. If the create fails, we'll try the PostScript name.
- RetainPtr<CFStringRef> fullName(AdoptCF, CFStringCreateWithCharacters(NULL, (const UniChar*)faceName, wcslen(faceName)));
- m_cgFont.adoptCF(CGFontCreateWithFontName(fullName.get()));
- if (!m_cgFont) {
- CFStringRef postScriptName = getPostScriptName(fullName.get(), hdc);
- if (postScriptName) {
- m_cgFont.adoptCF(CGFontCreateWithFontName(postScriptName));
- ASSERT(m_cgFont);
- }
- }
- if (m_useGDI) {
- LOGFONT* logfont = static_cast<LOGFONT*>(malloc(sizeof(LOGFONT)));
- GetObject(font, sizeof(*logfont), logfont);
- wkSetFontPlatformInfo(m_cgFont.get(), logfont, free);
- }
+ LOGFONT logfont;
+ GetObject(font, sizeof(logfont), &logfont);
+ m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&logfont));
}
FontPlatformData::FontPlatformData(HFONT hfont, CGFontRef font, float size, bool bold, bool oblique, bool useGDI)
diff --git a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
index 9fce68a..9b916bd 100644
--- a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
+++ b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
@@ -4,7 +4,7 @@
*
* Copyright (C) 2006, 2007, 2008 Apple Inc.
* Copyright (C) 2007 Alp Toker
- * Copyright (C) 2008 Brent Fulgham
+ * Copyright (C) 2008, 2010 Brent Fulgham
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -34,7 +34,7 @@
#include <cairo-win32.h>
-using std::min;
+using namespace std;
namespace WebCore {
@@ -47,8 +47,7 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR*
cairo_matrix_init_scale(&sizeMatrix, size, size);
static cairo_font_options_t* fontOptions = 0;
- if (!fontOptions)
- {
+ if (!fontOptions) {
fontOptions = cairo_font_options_create();
cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_SUBPIXEL);
}
@@ -130,4 +129,15 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
return *this;
}
+bool FontPlatformData::operator==(const FontPlatformData& other) const
+{
+ return m_font == other.m_font
+ && m_fontFace == other.m_fontFace
+ && m_scaledFont == other.m_scaledFont
+ && m_size == other.m_size
+ && m_syntheticBold == other.m_syntheticBold
+ && m_syntheticOblique == other.m_syntheticOblique
+ && m_useGDI == other.m_useGDI;
+}
+
}
diff --git a/WebCore/platform/graphics/win/FontWin.cpp b/WebCore/platform/graphics/win/FontWin.cpp
index 27d8dee..717171f 100644
--- a/WebCore/platform/graphics/win/FontWin.cpp
+++ b/WebCore/platform/graphics/win/FontWin.cpp
@@ -34,6 +34,8 @@
#include "UniscribeController.h"
#include <wtf/MathExtras.h>
+using namespace std;
+
namespace WebCore {
bool Font::canReturnFallbackFontsForComplexText()
@@ -89,10 +91,16 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
drawGlyphBuffer(context, glyphBuffer, run, startPoint);
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
UniscribeController controller(this, run, fallbackFonts);
controller.advance(run.length());
+ if (glyphOverflow) {
+ glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - ascent());
+ glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - descent());
+ glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX()));
+ glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.runWidthSoFar()));
+ }
return controller.runWidthSoFar();
}
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
index 49b5af3..0065191 100644
--- a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
@@ -29,21 +29,132 @@
#include "GraphicsLayerCACF.h"
-#include "CString.h"
#include "FloatConversion.h"
#include "FloatRect.h"
+#include "Font.h"
+#include "FontSelector.h"
#include "Image.h"
#include "PlatformString.h"
#include "SystemTime.h"
#include "WKCACFLayer.h"
-#include <QuartzCoreInterface/QuartzCoreInterface.h>
#include <wtf/CurrentTime.h>
#include <wtf/StringExtras.h>
+#include <wtf/text/CString.h>
using namespace std;
namespace WebCore {
+class WebLayer : public WKCACFLayer {
+public:
+ static PassRefPtr<WKCACFLayer> create(LayerType layerType, GraphicsLayerCACF* owner)
+ {
+ return adoptRef(new WebLayer(layerType, owner));
+ }
+
+ virtual void setNeedsDisplay(const CGRect* dirtyRect)
+ {
+ if (m_owner) {
+ if (m_owner->showRepaintCounter()) {
+ CGRect layerBounds = bounds();
+ CGRect repaintCounterRect = layerBounds;
+ // We assume a maximum of 4 digits and a font size of 22.
+ repaintCounterRect.size.width = 48;
+ repaintCounterRect.size.height = 25;
+ if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown)
+ repaintCounterRect.origin.y = layerBounds.size.height - (layerBounds.origin.y + repaintCounterRect.size.height);
+ WKCACFLayer::setNeedsDisplay(&repaintCounterRect);
+ }
+ if (dirtyRect && m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
+ CGRect flippedDirtyRect = *dirtyRect;
+ flippedDirtyRect.origin.y = bounds().size.height - (flippedDirtyRect.origin.y + flippedDirtyRect.size.height);
+ WKCACFLayer::setNeedsDisplay(&flippedDirtyRect);
+ return;
+ }
+ }
+ WKCACFLayer::setNeedsDisplay(dirtyRect);
+ }
+
+ virtual void drawInContext(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()) {
+ String text = String::format("%d", m_owner->incrementRepaintCount());;
+
+ CGContextSaveGState(context);
+ CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f);
+
+ CGRect aBounds = layerBounds;
+
+ aBounds.size.width = 10 + 12 * text.length();
+ aBounds.size.height = 25;
+ CGContextFillRect(context, aBounds);
+
+ FontDescription desc;
+
+ NONCLIENTMETRICS metrics;
+ metrics.cbSize = sizeof(metrics);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
+ FontFamily family;
+ family.setFamily(metrics.lfSmCaptionFont.lfFaceName);
+ desc.setFamily(family);
+
+ desc.setComputedSize(22);
+
+ Font font = Font(desc, 0, 0);
+ font.update(0);
+
+ GraphicsContext cg(context);
+ cg.setFillColor(Color::black, DeviceColorSpace);
+ cg.drawText(font, TextRun(text), IntPoint(aBounds.origin.x + 3, aBounds.origin.y + 20));
+
+ CGContextRestoreGState(context);
+ }
+
+ CGContextRestoreGState(context);
+ }
+
+protected:
+ WebLayer(LayerType layerType, GraphicsLayerCACF* owner)
+ : WKCACFLayer(layerType)
+ , m_owner(owner)
+ {
+ }
+
+private:
+ GraphicsLayer* m_owner;
+};
+
static inline void copyTransform(CATransform3D& toT3D, const TransformationMatrix& t)
{
toT3D.m11 = narrowPrecisionToFloat(t.m11());
@@ -124,7 +235,7 @@ GraphicsLayerCACF::GraphicsLayerCACF(GraphicsLayerClient* client)
, m_contentsLayerPurpose(NoContentsLayer)
, m_contentsLayerHasBackgroundColor(false)
{
- m_layer = WKCACFLayer::create(WKCACFLayer::Layer, this);
+ m_layer = WebLayer::create(WKCACFLayer::Layer, this);
updateDebugIndicators();
}
@@ -142,12 +253,12 @@ GraphicsLayerCACF::~GraphicsLayerCACF()
m_transformLayer->removeFromSuperlayer();
}
-void GraphicsLayerCACF::setName(const String& inName)
+void GraphicsLayerCACF::setName(const String& name)
{
- String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
- GraphicsLayer::setName(name);
+ String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name;
+ GraphicsLayer::setName(longName);
- m_layer->setName(inName);
+ m_layer->setName(longName);
}
NativeLayer GraphicsLayerCACF::nativeLayer() const
@@ -331,8 +442,10 @@ void GraphicsLayerCACF::setNeedsDisplay()
void GraphicsLayerCACF::setNeedsDisplayInRect(const FloatRect& rect)
{
- if (drawsContent())
- m_layer->setNeedsDisplay(rect);
+ if (drawsContent()) {
+ CGRect cgRect = rect;
+ m_layer->setNeedsDisplay(&cgRect);
+ }
}
void GraphicsLayerCACF::setContentsRect(const IntRect& rect)
@@ -537,7 +650,7 @@ void GraphicsLayerCACF::updateLayerPreserves3D()
{
if (m_preserves3D && !m_transformLayer) {
// Create the transform layer.
- m_transformLayer = WKCACFLayer::create(WKCACFLayer::TransformLayer, this);
+ m_transformLayer = WebLayer::create(WKCACFLayer::TransformLayer, this);
#ifndef NDEBUG
m_transformLayer->setName(String().format("Transform Layer CATransformLayer(%p) GraphicsLayer(%p)", m_transformLayer.get(), this));
@@ -553,7 +666,7 @@ void GraphicsLayerCACF::updateLayerPreserves3D()
m_layer->setPosition(point);
m_layer->setAnchorPoint(CGPointMake(0.5f, 0.5f));
- m_layer->setTransform(wkqcCATransform3DIdentity());
+ 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);
@@ -610,7 +723,7 @@ void GraphicsLayerCACF::updateContentsImage()
{
if (m_pendingContentsImage) {
if (!m_contentsLayer.get()) {
- RefPtr<WKCACFLayer> imageLayer = WKCACFLayer::create(WKCACFLayer::Layer, this);
+ RefPtr<WKCACFLayer> imageLayer = WebLayer::create(WKCACFLayer::Layer, this);
#ifndef NDEBUG
imageLayer->setName("Image Layer");
#endif
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.h b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
index 0a52764..8c3f848 100644
--- a/WebCore/platform/graphics/win/GraphicsLayerCACF.h
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
@@ -91,8 +91,6 @@ public:
virtual void setGeometryOrientation(CompositingCoordinatesOrientation);
- void notifySyncRequired() { if (m_client) m_client->notifySyncRequired(this); }
-
private:
void updateOpacityOnLayer();
diff --git a/WebCore/platform/graphics/win/ImageCGWin.cpp b/WebCore/platform/graphics/win/ImageCGWin.cpp
index 2c6d41d..a0fbba7 100644
--- a/WebCore/platform/graphics/win/ImageCGWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCGWin.cpp
@@ -25,13 +25,14 @@
#include "config.h"
#include "Image.h"
+
#include "BitmapImage.h"
#include "BitmapInfo.h"
#include "GraphicsContext.h"
+#include "PlatformString.h"
#include <ApplicationServices/ApplicationServices.h>
-
#include <windows.h>
-#include "PlatformString.h"
+#include <wtf/RetainPtr.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index 1df73a7..c848eb3 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -28,13 +28,20 @@
#if ENABLE(VIDEO)
#include "MediaPlayerPrivateQuickTimeWin.h"
+#include "Cookie.h"
+#include "CookieJar.h"
+#include "Frame.h"
+#include "FrameView.h"
#include "GraphicsContext.h"
#include "KURL.h"
#include "QTMovieWin.h"
#include "ScrollView.h"
+#include "SoftLinking.h"
+#include "StringBuilder.h"
#include "StringHash.h"
#include "TimeRanges.h"
#include "Timer.h"
+#include <Wininet.h>
#include <wtf/CurrentTime.h>
#include <wtf/HashSet.h>
#include <wtf/MathExtras.h>
@@ -59,6 +66,9 @@ using namespace std;
namespace WebCore {
+SOFT_LINK_LIBRARY(Wininet)
+SOFT_LINK(Wininet, InternetSetCookieExW, DWORD, WINAPI, (LPCWSTR lpszUrl, LPCWSTR lpszCookieName, LPCWSTR lpszCookieData, DWORD dwFlags, DWORD_PTR dwReserved), (lpszUrl, lpszCookieName, lpszCookieData, dwFlags, dwReserved))
+
MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player)
{
return new MediaPlayerPrivate(player);
@@ -111,7 +121,7 @@ PlatformMedia MediaPlayerPrivate::platformMedia() const
#if USE(ACCELERATED_COMPOSITING)
PlatformLayer* MediaPlayerPrivate::platformLayer() const
{
- return m_qtVideoLayer->platformLayer();
+ return m_qtVideoLayer ? m_qtVideoLayer->platformLayer() : 0;
}
#endif
@@ -159,6 +169,97 @@ void TaskTimer::fired()
QTMovieWin::taskTimerFired();
}
+String MediaPlayerPrivate::rfc2616DateStringFromTime(CFAbsoluteTime time)
+{
+ static const char* const dayStrings[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+ static const char* const monthStrings[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ static const CFStringRef dateFormatString = CFSTR("%s, %02d %s %04d %02d:%02d:%02d GMT");
+ static CFTimeZoneRef gmtTimeZone;
+ if (!gmtTimeZone)
+ gmtTimeZone = CFTimeZoneCopyDefault();
+
+ CFGregorianDate dateValue = CFAbsoluteTimeGetGregorianDate(time, gmtTimeZone);
+ if (!CFGregorianDateIsValid(dateValue, kCFGregorianAllUnits))
+ return String();
+
+ time = CFGregorianDateGetAbsoluteTime(dateValue, gmtTimeZone);
+ SInt32 day = CFAbsoluteTimeGetDayOfWeek(time, 0);
+
+ RetainPtr<CFStringRef> dateCFString(AdoptCF, CFStringCreateWithFormat(0, 0, dateFormatString, dayStrings[day - 1], dateValue.day,
+ monthStrings[dateValue.month - 1], dateValue.year, dateValue.hour, dateValue.minute, (int)dateValue.second));
+ return dateCFString.get();
+}
+
+static void addCookieParam(StringBuilder& cookieBuilder, const String& name, const String& value)
+{
+ if (name.isEmpty())
+ return;
+
+ // If this isn't the first parameter added, terminate the previous one.
+ if (cookieBuilder.length())
+ cookieBuilder.append("; ");
+
+ // Add parameter name, and value if there is one.
+ cookieBuilder.append(name);
+ if (!value.isEmpty()) {
+ cookieBuilder.append("=");
+ cookieBuilder.append(value);
+ }
+}
+
+
+void MediaPlayerPrivate::setUpCookiesForQuickTime(const String& url)
+{
+ // WebCore loaded the page with the movie URL with CFNetwork but QuickTime will
+ // use WinINet to download the movie, so we need to copy any cookies needed to
+ // download the movie into WinInet before asking QuickTime to open it.
+ Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0;
+ if (!frame || !frame->page() || !frame->page()->cookieEnabled())
+ return;
+
+ KURL movieURL = KURL(KURL(), url);
+ Vector<Cookie> documentCookies;
+ if (!getRawCookies(frame->document(), movieURL, documentCookies))
+ return;
+
+ for (size_t ndx = 0; ndx < documentCookies.size(); ndx++) {
+ const Cookie& cookie = documentCookies[ndx];
+
+ if (cookie.name.isEmpty())
+ continue;
+
+ // Build up the cookie string with as much information as we can get so WinINet
+ // knows what to do with it.
+ StringBuilder cookieBuilder;
+ addCookieParam(cookieBuilder, cookie.name, cookie.value);
+ addCookieParam(cookieBuilder, "path", cookie.path);
+ if (cookie.expires)
+ addCookieParam(cookieBuilder, "expires", rfc2616DateStringFromTime(cookie.expires));
+ if (cookie.httpOnly)
+ addCookieParam(cookieBuilder, "httpOnly", String());
+ cookieBuilder.append(";");
+
+ String cookieURL;
+ if (!cookie.domain.isEmpty()) {
+ StringBuilder urlBuilder;
+
+ urlBuilder.append(movieURL.protocol());
+ urlBuilder.append("://");
+ if (cookie.domain[0] == '.')
+ urlBuilder.append(cookie.domain.substring(1));
+ else
+ urlBuilder.append(cookie.domain);
+ if (cookie.path.length() > 1)
+ urlBuilder.append(cookie.path);
+
+ cookieURL = urlBuilder.toString();
+ } else
+ cookieURL = movieURL;
+
+ InternetSetCookieExW(cookieURL.charactersWithNullTermination(), 0, cookieBuilder.toString().charactersWithNullTermination(), 0, 0);
+ }
+}
+
void MediaPlayerPrivate::load(const String& url)
{
if (!QTMovieWin::initializeQuickTime()) {
@@ -181,6 +282,8 @@ void MediaPlayerPrivate::load(const String& url)
}
cancelSeek();
+ setUpCookiesForQuickTime(url);
+
m_qtMovie.set(new QTMovieWin(this));
m_qtMovie->load(url.characters(), url.length(), m_player->preservesPitch());
m_qtMovie->setVolume(m_player->volume());
@@ -861,14 +964,6 @@ void MediaPlayerPrivate::acceleratedRenderingStateChanged()
setUpVideoRendering();
}
-void MediaPlayerPrivate::notifySyncRequired(const GraphicsLayer*)
-{
- GraphicsLayerCACF* videoGraphicsLayer = static_cast<GraphicsLayerCACF*>(m_qtVideoLayer.get());
- if (videoGraphicsLayer)
- videoGraphicsLayer->notifySyncRequired();
- }
-
-
#endif
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
index 029a520..9de5894 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
@@ -67,7 +67,7 @@ private:
// GraphicsLayerClient methods
virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip);
virtual void notifyAnimationStarted(const GraphicsLayer*, double time) { }
- virtual void notifySyncRequired(const GraphicsLayer*);
+ virtual void notifySyncRequired(const GraphicsLayer*) { }
virtual bool showDebugBorders() const { return false; }
virtual bool showRepaintCounter() const { return false; }
#endif
@@ -158,6 +158,9 @@ private:
void createLayerForMovie();
void destroyLayerForMovie();
+ void setUpCookiesForQuickTime(const String& url);
+ String rfc2616DateStringFromTime(CFAbsoluteTime);
+
MediaPlayer* m_player;
OwnPtr<QTMovieWin> m_qtMovie;
#if USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/RefCountedHFONT.h b/WebCore/platform/graphics/win/RefCountedHFONT.h
new file mode 100755
index 0000000..b1b691b
--- /dev/null
+++ b/WebCore/platform/graphics/win/RefCountedHFONT.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef RefCountedHFONT_h
+#define RefCountedHFONT_h
+
+#include "StringImpl.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class RefCountedHFONT : public RefCounted<RefCountedHFONT> {
+public:
+ static PassRefPtr<RefCountedHFONT> create(HFONT hfont) { return adoptRef(new RefCountedHFONT(hfont)); }
+ static PassRefPtr<RefCountedHFONT> createDeleted() { return adoptRef(new RefCountedHFONT(reinterpret_cast<HFONT>(-1))); }
+
+ ~RefCountedHFONT()
+ {
+ if (m_hfont != reinterpret_cast<HFONT>(-1))
+ DeleteObject(m_hfont);
+ }
+
+ HFONT hfont() const { return m_hfont; }
+ unsigned hash() const
+ {
+ return StringImpl::computeHash(reinterpret_cast<const UChar*>(&m_hfont), sizeof(HFONT) / sizeof(UChar));
+ }
+
+private:
+ RefCountedHFONT(HFONT hfont)
+ : m_hfont(hfont)
+ {
+ }
+
+ HFONT m_hfont;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
index 6b3a96e..ee3a980 100644
--- a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
+++ b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
@@ -126,10 +126,10 @@ void SimpleFontData::platformCharWidthInit()
}
}
-float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const
{
if (m_platformData.useGDI())
- return widthForGDIGlyph(glyph);
+ return metricsForGDIGlyph(glyph);
CGFontRef font = m_platformData.cgFont();
float pointSize = m_platformData.size();
@@ -139,8 +139,18 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
// FIXME: Need to add real support for printer fonts.
bool isPrinterFont = false;
wkGetGlyphAdvances(font, m, m_isSystemFont, isPrinterFont, glyph, advance);
-
- return advance.width + m_syntheticBoldOffset;
+ GlyphMetrics metrics;
+ metrics.horizontalAdvance = advance.width + m_syntheticBoldOffset;
+
+ if (metricsMode == GlyphBoundingBox) {
+ CGRect boundingBox;
+ CGFontGetGlyphBBoxes(font, &glyph, 1, &boundingBox);
+ CGFloat scale = pointSize / unitsPerEm();
+ metrics.boundingBox = CGRectApplyAffineTransform(boundingBox, CGAffineTransformMakeScale(scale, -scale));
+ if (m_syntheticBoldOffset)
+ metrics.boundingBox.setWidth(metrics.boundingBox.width() + m_syntheticBoldOffset);
+ }
+ return metrics;
}
}
diff --git a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
index 5a3244c..f85f9ba 100644
--- a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
+++ b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
@@ -179,16 +179,25 @@ void SimpleFontData::determinePitch()
ReleaseDC(0, dc);
}
-float SimpleFontData::widthForGDIGlyph(Glyph glyph) const
+GlyphMetrics SimpleFontData::metricsForGDIGlyph(Glyph glyph) const
{
HDC hdc = GetDC(0);
SetGraphicsMode(hdc, GM_ADVANCED);
HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
- int width;
- GetCharWidthI(hdc, glyph, 1, 0, &width);
+
+ GLYPHMETRICS gdiMetrics;
+ static const MAT2 identity = { 0, 1, 0, 0, 0, 0, 0, 1 };
+ GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity);
+
SelectObject(hdc, oldFont);
ReleaseDC(0, hdc);
- return width + m_syntheticBoldOffset;
+
+ GlyphMetrics glyphMetrics;
+ glyphMetrics.horizontalAdvance = gdiMetrics.gmCellIncX + m_syntheticBoldOffset;
+ glyphMetrics.boundingBox = FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y,
+ gdiMetrics.gmBlackBoxX + m_syntheticBoldOffset, gdiMetrics.gmBlackBoxY);
+
+ return glyphMetrics;
}
SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const
diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp
index f382857..cfa15a2 100644
--- a/WebCore/platform/graphics/win/UniscribeController.cpp
+++ b/WebCore/platform/graphics/win/UniscribeController.cpp
@@ -32,6 +32,8 @@
#include "SimpleFontData.h"
#include <wtf/MathExtras.h>
+using namespace std;
+
namespace WebCore {
// FIXME: Rearchitect this to be more like WidthIterator in Font.cpp. Have an advance() method
@@ -39,16 +41,20 @@ namespace WebCore {
// take the GlyphBuffer as an arg so that we don't have to populate the glyph buffer when
// measuring.
UniscribeController::UniscribeController(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts)
-: m_font(*font)
-, m_run(run)
-, m_fallbackFonts(fallbackFonts)
-, m_end(run.length())
-, m_currentCharacter(0)
-, m_runWidthSoFar(0)
-, m_computingOffsetPosition(false)
-, m_includePartialGlyphs(false)
-, m_offsetX(0)
-, m_offsetPosition(0)
+ : m_font(*font)
+ , m_run(run)
+ , m_fallbackFonts(fallbackFonts)
+ , m_minGlyphBoundingBoxX(numeric_limits<float>::max())
+ , m_maxGlyphBoundingBoxX(numeric_limits<float>::min())
+ , m_minGlyphBoundingBoxY(numeric_limits<float>::max())
+ , m_maxGlyphBoundingBoxY(numeric_limits<float>::min())
+ , m_end(run.length())
+ , m_currentCharacter(0)
+ , m_runWidthSoFar(0)
+ , m_computingOffsetPosition(false)
+ , m_includePartialGlyphs(false)
+ , m_offsetX(0)
+ , m_offsetPosition(0)
{
m_padding = m_run.padding();
if (!m_padding)
@@ -374,6 +380,14 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S
glyphBuffer->add(glyph, fontData, advance, &size);
}
+ GlyphMetrics glyphMetrics = fontData->metricsForGlyph(glyph);
+ glyphMetrics.boundingBox.move(m_glyphOrigin.x(), m_glyphOrigin.y());
+ m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphMetrics.boundingBox.x());
+ m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphMetrics.boundingBox.right());
+ m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphMetrics.boundingBox.y());
+ m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphMetrics.boundingBox.bottom());
+ m_glyphOrigin.move(advance + offsetX, -offsetY);
+
// Mutate the glyph array to contain our altered advances.
if (m_computingOffsetPosition)
advances[k] = advance;
diff --git a/WebCore/platform/graphics/win/UniscribeController.h b/WebCore/platform/graphics/win/UniscribeController.h
index 23b8108..09203b5 100644
--- a/WebCore/platform/graphics/win/UniscribeController.h
+++ b/WebCore/platform/graphics/win/UniscribeController.h
@@ -49,6 +49,11 @@ public:
// Returns the width of everything we've consumed so far.
float runWidthSoFar() const { return m_runWidthSoFar; }
+ float minGlyphBoundingBoxX() const { return m_minGlyphBoundingBoxX; }
+ float maxGlyphBoundingBoxX() const { return m_maxGlyphBoundingBoxX; }
+ float minGlyphBoundingBoxY() const { return m_minGlyphBoundingBoxY; }
+ float maxGlyphBoundingBoxY() const { return m_maxGlyphBoundingBoxY; }
+
private:
void resetControlAndState();
@@ -61,6 +66,11 @@ private:
const Font& m_font;
const TextRun& m_run;
HashSet<const SimpleFontData*>* m_fallbackFonts;
+ FloatPoint m_glyphOrigin;
+ float m_minGlyphBoundingBoxX;
+ float m_maxGlyphBoundingBoxX;
+ float m_minGlyphBoundingBoxY;
+ float m_maxGlyphBoundingBoxY;
SCRIPT_CONTROL m_control;
SCRIPT_STATE m_state;
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp
index e5b184d..4a0461d 100644
--- a/WebCore/platform/graphics/win/WKCACFLayer.cpp
+++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp
@@ -29,68 +29,33 @@
#include "WKCACFLayer.h"
-#include "CString.h"
#include "WKCACFContextFlusher.h"
#include "WKCACFLayerRenderer.h"
+#include <wtf/text/CString.h>
#include <stdio.h>
#include <QuartzCore/CACFContext.h>
#include <QuartzCore/CARender.h>
-#include <QuartzCoreInterface/QuartzCoreInterface.h>
#ifndef NDEBUG
#include <wtf/CurrentTime.h>
#endif
-#ifdef DEBUG_ALL
-#pragma comment(lib, "QuartzCore_debug")
-#pragma comment(lib, "QuartzCoreInterface_debug")
-#else
-#pragma comment(lib, "QuartzCore")
-#pragma comment(lib, "QuartzCoreInterface")
-#endif
-
namespace WebCore {
using namespace std;
-static void displayInContext(CACFLayerRef layer, CGContextRef context)
+static void displayCallback(CACFLayerRef layer, CGContextRef context)
{
ASSERT_ARG(layer, WKCACFLayer::layer(layer));
- WKCACFLayer::layer(layer)->display(context);
+ WKCACFLayer::layer(layer)->drawInContext(context);
}
-#define STATIC_CACF_STRING(name) \
- static CFStringRef name() \
- { \
- static CFStringRef name = wkqcCFStringRef(wkqc##name); \
- return name; \
- }
-
-STATIC_CACF_STRING(kCACFLayer)
-STATIC_CACF_STRING(kCACFTransformLayer)
-STATIC_CACF_STRING(kCACFGravityCenter)
-STATIC_CACF_STRING(kCACFGravityTop)
-STATIC_CACF_STRING(kCACFGravityBottom)
-STATIC_CACF_STRING(kCACFGravityLeft)
-STATIC_CACF_STRING(kCACFGravityRight)
-STATIC_CACF_STRING(kCACFGravityTopLeft)
-STATIC_CACF_STRING(kCACFGravityTopRight)
-STATIC_CACF_STRING(kCACFGravityBottomLeft)
-STATIC_CACF_STRING(kCACFGravityBottomRight)
-STATIC_CACF_STRING(kCACFGravityResize)
-STATIC_CACF_STRING(kCACFGravityResizeAspect)
-STATIC_CACF_STRING(kCACFGravityResizeAspectFill)
-STATIC_CACF_STRING(kCACFFilterLinear)
-STATIC_CACF_STRING(kCACFFilterNearest)
-STATIC_CACF_STRING(kCACFFilterTrilinear)
-STATIC_CACF_STRING(kCACFFilterLanczos)
-
static CFStringRef toCACFLayerType(WKCACFLayer::LayerType type)
{
switch (type) {
- case WKCACFLayer::Layer: return kCACFLayer();
- case WKCACFLayer::TransformLayer: return kCACFTransformLayer();
+ case WKCACFLayer::Layer: return kCACFLayer;
+ case WKCACFLayer::TransformLayer: return kCACFTransformLayer;
default: return 0;
}
}
@@ -98,55 +63,55 @@ static CFStringRef toCACFLayerType(WKCACFLayer::LayerType type)
static CFStringRef toCACFContentsGravityType(WKCACFLayer::ContentsGravityType type)
{
switch (type) {
- case WKCACFLayer::Center: return kCACFGravityCenter();
- case WKCACFLayer::Top: return kCACFGravityTop();
- case WKCACFLayer::Bottom: return kCACFGravityBottom();
- case WKCACFLayer::Left: return kCACFGravityLeft();
- case WKCACFLayer::Right: return kCACFGravityRight();
- case WKCACFLayer::TopLeft: return kCACFGravityTopLeft();
- case WKCACFLayer::TopRight: return kCACFGravityTopRight();
- case WKCACFLayer::BottomLeft: return kCACFGravityBottomLeft();
- case WKCACFLayer::BottomRight: return kCACFGravityBottomRight();
- case WKCACFLayer::Resize: return kCACFGravityResize();
- case WKCACFLayer::ResizeAspect: return kCACFGravityResizeAspect();
- case WKCACFLayer::ResizeAspectFill: return kCACFGravityResizeAspectFill();
+ case WKCACFLayer::Center: return kCACFGravityCenter;
+ case WKCACFLayer::Top: return kCACFGravityTop;
+ case WKCACFLayer::Bottom: return kCACFGravityBottom;
+ case WKCACFLayer::Left: return kCACFGravityLeft;
+ case WKCACFLayer::Right: return kCACFGravityRight;
+ case WKCACFLayer::TopLeft: return kCACFGravityTopLeft;
+ case WKCACFLayer::TopRight: return kCACFGravityTopRight;
+ case WKCACFLayer::BottomLeft: return kCACFGravityBottomLeft;
+ case WKCACFLayer::BottomRight: return kCACFGravityBottomRight;
+ case WKCACFLayer::Resize: return kCACFGravityResize;
+ case WKCACFLayer::ResizeAspect: return kCACFGravityResizeAspect;
+ case WKCACFLayer::ResizeAspectFill: return kCACFGravityResizeAspectFill;
default: return 0;
}
}
static WKCACFLayer::ContentsGravityType fromCACFContentsGravityType(CFStringRef string)
{
- if (CFEqual(string, kCACFGravityTop()))
+ if (CFEqual(string, kCACFGravityTop))
return WKCACFLayer::Top;
- if (CFEqual(string, kCACFGravityBottom()))
+ if (CFEqual(string, kCACFGravityBottom))
return WKCACFLayer::Bottom;
- if (CFEqual(string, kCACFGravityLeft()))
+ if (CFEqual(string, kCACFGravityLeft))
return WKCACFLayer::Left;
- if (CFEqual(string, kCACFGravityRight()))
+ if (CFEqual(string, kCACFGravityRight))
return WKCACFLayer::Right;
- if (CFEqual(string, kCACFGravityTopLeft()))
+ if (CFEqual(string, kCACFGravityTopLeft))
return WKCACFLayer::TopLeft;
- if (CFEqual(string, kCACFGravityTopRight()))
+ if (CFEqual(string, kCACFGravityTopRight))
return WKCACFLayer::TopRight;
- if (CFEqual(string, kCACFGravityBottomLeft()))
+ if (CFEqual(string, kCACFGravityBottomLeft))
return WKCACFLayer::BottomLeft;
- if (CFEqual(string, kCACFGravityBottomRight()))
+ if (CFEqual(string, kCACFGravityBottomRight))
return WKCACFLayer::BottomRight;
- if (CFEqual(string, kCACFGravityResize()))
+ if (CFEqual(string, kCACFGravityResize))
return WKCACFLayer::Resize;
- if (CFEqual(string, kCACFGravityResizeAspect()))
+ if (CFEqual(string, kCACFGravityResizeAspect))
return WKCACFLayer::ResizeAspect;
- if (CFEqual(string, kCACFGravityResizeAspectFill()))
+ if (CFEqual(string, kCACFGravityResizeAspectFill))
return WKCACFLayer::ResizeAspectFill;
return WKCACFLayer::Center;
@@ -155,45 +120,44 @@ static WKCACFLayer::ContentsGravityType fromCACFContentsGravityType(CFStringRef
static CFStringRef toCACFFilterType(WKCACFLayer::FilterType type)
{
switch (type) {
- case WKCACFLayer::Linear: return kCACFFilterLinear();
- case WKCACFLayer::Nearest: return kCACFFilterNearest();
- case WKCACFLayer::Trilinear: return kCACFFilterTrilinear();
- case WKCACFLayer::Lanczos: return kCACFFilterLanczos();
+ case WKCACFLayer::Linear: return kCACFFilterLinear;
+ case WKCACFLayer::Nearest: return kCACFFilterNearest;
+ case WKCACFLayer::Trilinear: return kCACFFilterTrilinear;
+ case WKCACFLayer::Lanczos: return kCACFFilterLanczos;
default: return 0;
}
}
static WKCACFLayer::FilterType fromCACFFilterType(CFStringRef string)
{
- if (CFEqual(string, kCACFFilterNearest()))
+ if (CFEqual(string, kCACFFilterNearest))
return WKCACFLayer::Nearest;
- if (CFEqual(string, kCACFFilterTrilinear()))
+ if (CFEqual(string, kCACFFilterTrilinear))
return WKCACFLayer::Trilinear;
- if (CFEqual(string, kCACFFilterLanczos()))
+ if (CFEqual(string, kCACFFilterLanczos))
return WKCACFLayer::Lanczos;
return WKCACFLayer::Linear;
}
-PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type, GraphicsLayerCACF* owner)
+PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type)
{
if (!WKCACFLayerRenderer::acceleratedCompositingAvailable())
return 0;
- return adoptRef(new WKCACFLayer(type, owner));
+ return adoptRef(new WKCACFLayer(type));
}
// 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(LayerType type, GraphicsLayerCACF* owner)
+WKCACFLayer::WKCACFLayer(LayerType type)
: m_layer(AdoptCF, CACFLayerCreate(toCACFLayerType(type)))
, m_needsDisplayOnBoundsChange(false)
- , m_owner(owner)
{
CACFLayerSetUserData(layer(), this);
- CACFLayerSetDisplayCallback(layer(), displayInContext);
+ CACFLayerSetDisplayCallback(layer(), displayCallback);
}
WKCACFLayer::~WKCACFLayer()
@@ -205,64 +169,6 @@ WKCACFLayer::~WKCACFLayer()
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());
@@ -271,7 +177,9 @@ void WKCACFLayer::becomeRootLayerForContext(CACFContextRef context)
void WKCACFLayer::setNeedsCommit()
{
- CACFContextRef context = CACFLayerGetContext(rootLayer()->layer());
+ WKCACFLayer* root = rootLayer();
+
+ CACFContextRef context = CACFLayerGetContext(root->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
@@ -280,16 +188,14 @@ void WKCACFLayer::setNeedsCommit()
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();
+ // Call setNeedsRender on the root layer, which will cause a render to
+ // happen in WKCACFLayerRenderer
+ root->setNeedsRender();
}
bool WKCACFLayer::isTransformLayer() const
{
- return CACFLayerGetClass(layer()) == kCACFTransformLayer();
+ return CACFLayerGetClass(layer()) == kCACFTransformLayer;
}
void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
@@ -300,6 +206,7 @@ void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
void WKCACFLayer::insertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
{
index = min(index, numSublayers());
+ sublayer->removeFromSuperlayer();
CACFLayerInsertSublayer(layer(), sublayer->layer(), index);
setNeedsCommit();
}
@@ -344,21 +251,17 @@ void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer
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);
+
+ if (newLayer) {
+ newLayer->removeFromSuperlayer();
+ insertSublayer(newLayer, referenceIndex);
+ }
}
void WKCACFLayer::removeFromSuperlayer()
@@ -367,21 +270,10 @@ void WKCACFLayer::removeFromSuperlayer()
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();
-}
-
const WKCACFLayer* WKCACFLayer::sublayerAtIndex(int index) const
{
CFArrayRef sublayers = CACFLayerGetSublayers(layer());
@@ -490,29 +382,18 @@ void WKCACFLayer::removeAllSublayers()
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();
-}
+ // Remove all the current sublayers and add the passed layers
+ CACFLayerSetSublayers(layer(), 0);
-void WKCACFLayer::moveSublayers(WKCACFLayer* fromLayer, WKCACFLayer* toLayer)
-{
- if (!fromLayer || !toLayer)
- return;
+ // Perform removeFromSuperLayer in a separate pass. CACF requires superlayer to
+ // be null or CACFLayerInsertSublayer silently fails.
+ for (size_t i = 0; i < sublayers.size(); i++)
+ CACFLayerRemoveFromSuperlayer(sublayers[i]->layer());
+
+ for (size_t i = 0; i < sublayers.size(); i++)
+ CACFLayerInsertSublayer(layer(), sublayers[i]->layer(), i);
- CACFLayerSetSublayers(toLayer->layer(), CACFLayerGetSublayers(fromLayer->layer()));
- fromLayer->setNeedsCommit();
- toLayer->setNeedsCommit();
+ setNeedsCommit();
}
WKCACFLayer* WKCACFLayer::superlayer() const
@@ -523,18 +404,15 @@ WKCACFLayer* WKCACFLayer::superlayer() const
return WKCACFLayer::layer(super);
}
-void WKCACFLayer::setNeedsDisplay(const CGRect& dirtyRect)
+void WKCACFLayer::setNeedsDisplay(const CGRect* dirtyRect)
{
- if (m_owner)
- CACFLayerSetNeedsDisplay(layer(), &dirtyRect);
+ CACFLayerSetNeedsDisplay(layer(), dirtyRect);
setNeedsCommit();
}
void WKCACFLayer::setNeedsDisplay()
{
- if (m_owner)
- CACFLayerSetNeedsDisplay(layer(), 0);
- setNeedsCommit();
+ setNeedsDisplay(0);
}
#ifndef NDEBUG
@@ -570,11 +448,11 @@ void WKCACFLayer::printLayer(int indent) const
CGPoint layerAnchorPoint = anchorPoint();
CGRect layerBounds = bounds();
printIndent(indent);
- fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g]\n",
+ fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g] superlayer=%p\n",
isTransformLayer() ? "transform-layer" : "layer",
layerPosition.x, layerPosition.y, zPosition(),
layerBounds.origin.x, layerBounds.origin.y, layerBounds.size.width, layerBounds.size.height,
- layerAnchorPoint.x, layerAnchorPoint.y, anchorPointZ());
+ layerAnchorPoint.x, layerAnchorPoint.y, anchorPointZ(), superlayer());
// Print name if needed
String layerName = name();
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h
index e5568c9..f1b2613 100644
--- a/WebCore/platform/graphics/win/WKCACFLayer.h
+++ b/WebCore/platform/graphics/win/WKCACFLayer.h
@@ -39,7 +39,6 @@
#include <wtf/Vector.h>
#include "GraphicsContext.h"
-#include "GraphicsLayerCACF.h"
#include "PlatformString.h"
#include "TransformationMatrix.h"
@@ -55,10 +54,15 @@ public:
enum ContentsGravityType { Center, Top, Bottom, Left, Right, TopLeft, TopRight,
BottomLeft, BottomRight, Resize, ResizeAspect, ResizeAspectFill };
- static PassRefPtr<WKCACFLayer> create(LayerType, GraphicsLayerCACF* owner = 0);
+ static PassRefPtr<WKCACFLayer> create(LayerType);
static WKCACFLayer* layer(CACFLayerRef layer) { return static_cast<WKCACFLayer*>(CACFLayerGetUserData(layer)); }
- ~WKCACFLayer();
+ virtual ~WKCACFLayer();
+
+ virtual void setNeedsRender() { }
+ virtual void drawInContext(PlatformGraphicsContext*) { }
+ virtual void setNeedsDisplay(const CGRect* dirtyRect);
+ void setNeedsDisplay();
// Makes this layer the root when the passed context is rendered
void becomeRootLayerForContext(CACFContextRef);
@@ -106,8 +110,6 @@ public:
return RetainPtr<CFTypeRef>(AdoptCF, CGColorCreateGenericRGB(color.red(), color.green(), color.blue(), color.alpha()));
}
- void display(PlatformGraphicsContext*);
-
bool isTransformLayer() const;
void addSublayer(PassRefPtr<WKCACFLayer> sublayer);
@@ -116,7 +118,6 @@ public:
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;
@@ -180,9 +181,6 @@ public:
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(); }
@@ -228,10 +226,12 @@ public:
void printTree() const;
#endif
-private:
- WKCACFLayer(LayerType, GraphicsLayerCACF* owner);
+protected:
+ WKCACFLayer(LayerType);
void setNeedsCommit();
+
+private:
CACFLayerRef layer() const { return m_layer.get(); }
size_t numSublayers() const
{
@@ -255,7 +255,6 @@ private:
RetainPtr<CACFLayerRef> m_layer;
bool m_needsDisplayOnBoundsChange;
- GraphicsLayerCACF* m_owner;
};
}
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
index 78ebb9d..1b14846 100644
--- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
@@ -27,16 +27,22 @@
#if USE(ACCELERATED_COMPOSITING)
+#ifndef NDEBUG
+#define D3D_DEBUG_INFO
+#endif
+
#include "WKCACFLayerRenderer.h"
#include "WKCACFContextFlusher.h"
#include "WKCACFLayer.h"
+#include "WebCoreInstanceHandle.h"
#include <CoreGraphics/CGSRegion.h>
#include <QuartzCore/CACFContext.h>
#include <QuartzCore/CARenderOGL.h>
-#include <QuartzCoreInterface/QuartzCoreInterface.h>
#include <wtf/HashMap.h>
#include <wtf/OwnArrayPtr.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/StdLibExtras.h>
#include <d3d9.h>
#include <d3dx9.h>
@@ -75,6 +81,33 @@ inline static CGRect winRectToCGRect(RECT rc, RECT relativeToRect)
namespace WebCore {
+// Subclass of WKCACFLayer to allow the root layer to have a back pointer to the layer renderer
+// to fire off a draw
+class WKCACFRootLayer : public WKCACFLayer {
+public:
+ WKCACFRootLayer(WKCACFLayerRenderer* renderer)
+ : WKCACFLayer(WKCACFLayer::Layer)
+ {
+ m_renderer = renderer;
+ }
+
+ static PassRefPtr<WKCACFRootLayer> create(WKCACFLayerRenderer* renderer)
+ {
+ if (!WKCACFLayerRenderer::acceleratedCompositingAvailable())
+ return 0;
+ return adoptRef(new WKCACFRootLayer(renderer));
+ }
+
+ virtual void setNeedsRender() { m_renderer->renderSoon(); }
+
+ // Overload this to avoid calling setNeedsDisplay on the layer, which would override the contents
+ // we have placed on the root layer.
+ virtual void setNeedsDisplay(const CGRect* dirtyRect) { setNeedsCommit(); }
+
+private:
+ WKCACFLayerRenderer* m_renderer;
+};
+
typedef HashMap<CACFContextRef, WKCACFLayerRenderer*> ContextToWindowMap;
static ContextToWindowMap& windowsForContexts()
@@ -95,6 +128,28 @@ static D3DPRESENT_PARAMETERS initialPresentationParameters()
return parameters;
}
+// FIXME: <rdar://6507851> Share this code with CoreAnimation.
+static bool hardwareCapabilitiesIndicateCoreAnimationSupport(const D3DCAPS9& caps)
+{
+ // CoreAnimation needs two or more texture units.
+ if (caps.MaxTextureBlendStages < 2)
+ return false;
+
+ // CoreAnimation needs non-power-of-two textures.
+ if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
+ return false;
+
+ // CoreAnimation needs vertex shader 2.0 or greater.
+ if (D3DSHADER_VERSION_MAJOR(caps.VertexShaderVersion) < 2)
+ return false;
+
+ // CoreAnimation needs pixel shader 2.0 or greater.
+ if (D3DSHADER_VERSION_MAJOR(caps.PixelShaderVersion) < 2)
+ return false;
+
+ return true;
+}
+
bool WKCACFLayerRenderer::acceleratedCompositingAvailable()
{
static bool available;
@@ -104,17 +159,50 @@ bool WKCACFLayerRenderer::acceleratedCompositingAvailable()
return available;
tested = true;
+
+ // Initialize available to true since this function will be called from a
+ // propagation within createRenderer(). We want to be able to return true
+ // when that happens so that the test can continue.
+ available = true;
+
HMODULE library = LoadLibrary(TEXT("d3d9.dll"));
- if (!library)
- return false;
+ if (!library) {
+ available = false;
+ return available;
+ }
FreeLibrary(library);
+#ifdef DEBUG_ALL
+ library = LoadLibrary(TEXT("QuartzCore_debug.dll"));
+#else
library = LoadLibrary(TEXT("QuartzCore.dll"));
- if (!library)
- return false;
+#endif
+ if (!library) {
+ available = false;
+ return available;
+ }
FreeLibrary(library);
- available = true;
+
+ // Make a dummy HWND.
+ WNDCLASSEX wcex = { 0 };
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.lpfnWndProc = DefWindowProc;
+ wcex.hInstance = WebCore::instanceHandle();
+ wcex.lpszClassName = L"CoreAnimationTesterWindowClass";
+ ::RegisterClassEx(&wcex);
+ HWND testWindow = ::CreateWindow(L"CoreAnimationTesterWindowClass", L"CoreAnimationTesterWindow", WS_POPUP, -500, -500, 0, 0, 0, 0, 0, 0);
+
+ if (!testWindow) {
+ available = false;
+ return available;
+ }
+
+ OwnPtr<WKCACFLayerRenderer> testLayerRenderer = WKCACFLayerRenderer::create();
+ testLayerRenderer->setHostWindow(testWindow);
+ available = testLayerRenderer->createRenderer();
+ ::DestroyWindow(testWindow);
+
return available;
}
@@ -140,7 +228,9 @@ WKCACFLayerRenderer::WKCACFLayerRenderer()
, m_renderer(0)
, m_hostWindow(0)
, m_renderTimer(this, &WKCACFLayerRenderer::renderTimerFired)
- , m_scrollFrame(0, 0, 1, 1) // Default to 1 to avoid 0 size frames
+ , m_scrollPosition(0, 0)
+ , m_scrollSize(1, 1)
+ , m_backingStoreDirty(false)
{
#ifndef NDEBUG
char* printTreeFlag = getenv("CA_PRINT_TREE");
@@ -153,15 +243,29 @@ WKCACFLayerRenderer::~WKCACFLayerRenderer()
destroyRenderer();
}
-void WKCACFLayerRenderer::setScrollFrame(const IntRect& scrollFrame)
+WKCACFLayer* WKCACFLayerRenderer::rootLayer() const
{
- m_scrollFrame = scrollFrame;
- CGRect frameBounds = bounds();
- m_scrollLayer->setBounds(CGRectMake(0, 0, m_scrollFrame.width(), m_scrollFrame.height()));
- m_scrollLayer->setPosition(CGPointMake(0, frameBounds.size.height));
+ return m_rootLayer.get();
+}
- if (m_rootChildLayer)
- m_rootChildLayer->setPosition(CGPointMake(-m_scrollFrame.x(), m_scrollFrame.height() + m_scrollFrame.y()));
+void WKCACFLayerRenderer::setScrollFrame(const IntPoint& position, const IntSize& size)
+{
+ m_scrollSize = size;
+ m_scrollPosition = position;
+
+ updateScrollFrame();
+}
+
+void WKCACFLayerRenderer::updateScrollFrame()
+{
+ CGRect frameBounds = bounds();
+ m_clipLayer->setBounds(CGRectMake(0, 0, m_scrollSize.width(), m_scrollSize.height()));
+ m_clipLayer->setPosition(CGPointMake(0, frameBounds.size.height));
+ if (m_rootChildLayer) {
+ CGRect rootBounds = m_rootChildLayer->bounds();
+ m_scrollLayer->setBounds(rootBounds);
+ }
+ m_scrollLayer->setPosition(CGPointMake(-m_scrollPosition.x(), m_scrollPosition.y() + m_scrollSize.height()));
}
void WKCACFLayerRenderer::setRootContents(CGImageRef image)
@@ -171,7 +275,7 @@ void WKCACFLayerRenderer::setRootContents(CGImageRef image)
renderSoon();
}
-void WKCACFLayerRenderer::setRootChildLayer(WebCore::PlatformLayer* layer)
+void WKCACFLayerRenderer::setRootChildLayer(WKCACFLayer* layer)
{
if (!m_scrollLayer)
return;
@@ -180,30 +284,28 @@ void WKCACFLayerRenderer::setRootChildLayer(WebCore::PlatformLayer* layer)
m_rootChildLayer = layer;
if (layer) {
m_scrollLayer->addSublayer(layer);
-
- // Set the frame
- layer->setAnchorPoint(CGPointMake(0, 1));
- setScrollFrame(m_scrollFrame);
+ // Adjust the scroll frame accordingly
+ updateScrollFrame();
}
}
void WKCACFLayerRenderer::setNeedsDisplay()
{
ASSERT(m_rootLayer);
- m_rootLayer->setNeedsDisplay();
+ m_rootLayer->setNeedsDisplay(0);
renderSoon();
}
-void WKCACFLayerRenderer::createRenderer()
+bool WKCACFLayerRenderer::createRenderer()
{
if (m_triedToCreateD3DRenderer)
- return;
+ return m_d3dDevice;
m_triedToCreateD3DRenderer = true;
D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
if (!d3d() || !::IsWindow(m_hostWindow))
- return;
+ return false;
// D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the
// passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero
@@ -216,8 +318,23 @@ void WKCACFLayerRenderer::createRenderer()
parameters.BackBufferHeight = 1;
}
- if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &parameters, &m_d3dDevice)))
- return;
+ COMPtr<IDirect3DDevice9> device;
+ if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &parameters, &device)))
+ return false;
+
+ // Now that we've created the IDirect3DDevice9 based on the capabilities we
+ // got from the IDirect3D9 global object, we requery the device for its
+ // actual capabilities. The capabilities returned by the device can
+ // sometimes be more complete, for example when using software vertex
+ // processing.
+ D3DCAPS9 deviceCaps;
+ if (FAILED(device->GetDeviceCaps(&deviceCaps)))
+ return false;
+
+ if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps))
+ return false;
+
+ m_d3dDevice = device;
D3DXMATRIXA16 projection;
D3DXMatrixOrthoOffCenterRH(&projection, rect.left, rect.right, rect.top, rect.bottom, -1.0f, 1.0f);
@@ -228,17 +345,32 @@ void WKCACFLayerRenderer::createRenderer()
windowsForContexts().set(m_context.get(), this);
m_renderContext = static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get()));
- m_renderer = CARenderOGLNew(wkqcCARenderOGLCallbacks(wkqckCARenderDX9Callbacks), m_d3dDevice.get(), 0);
-
- // Create the root hierarchy
- m_rootLayer = WKCACFLayer::create(WKCACFLayer::Layer);
+ m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0);
+
+ // Create the root hierarchy.
+ // Under the root layer, we have a clipping layer to clip the content,
+ // that contains a scroll layer that we use for scrolling the content.
+ // The root layer is the size of the client area of the window.
+ // The clipping layer is the size of the WebView client area (window less the scrollbars).
+ // The scroll layer is the size of the root child layer.
+ // Resizing the window will change the bounds of the rootLayer and the clip layer and will not
+ // cause any repositioning.
+ // Scrolling will affect only the position of the scroll layer without affecting the bounds.
+
+ m_rootLayer = WKCACFRootLayer::create(this);
m_rootLayer->setName("WKCACFLayerRenderer rootLayer");
+
+ m_clipLayer = WKCACFLayer::create(WKCACFLayer::Layer);
+ m_clipLayer->setName("WKCACFLayerRenderer clipLayer");
+
m_scrollLayer = WKCACFLayer::create(WKCACFLayer::Layer);
m_scrollLayer->setName("WKCACFLayerRenderer scrollLayer");
- m_rootLayer->addSublayer(m_scrollLayer);
- m_scrollLayer->setMasksToBounds(true);
+ m_rootLayer->addSublayer(m_clipLayer);
+ m_clipLayer->addSublayer(m_scrollLayer);
+ m_clipLayer->setMasksToBounds(true);
m_scrollLayer->setAnchorPoint(CGPointMake(0, 1));
+ m_clipLayer->setAnchorPoint(CGPointMake(0, 1));
#ifndef NDEBUG
CGColorRef debugColor = createCGColor(Color(255, 0, 0, 204));
@@ -251,6 +383,8 @@ void WKCACFLayerRenderer::createRenderer()
if (m_context)
m_rootLayer->becomeRootLayerForContext(m_context.get());
+
+ return true;
}
void WKCACFLayerRenderer::destroyRenderer()
@@ -269,6 +403,7 @@ void WKCACFLayerRenderer::destroyRenderer()
s_d3d = 0;
m_rootLayer = 0;
+ m_clipLayer = 0;
m_scrollLayer = 0;
m_rootChildLayer = 0;
@@ -285,7 +420,7 @@ void WKCACFLayerRenderer::resize()
if (m_rootLayer) {
m_rootLayer->setFrame(bounds());
WKCACFContextFlusher::shared().flushAllContexts();
- setScrollFrame(m_scrollFrame);
+ updateScrollFrame();
}
}
@@ -331,6 +466,15 @@ void WKCACFLayerRenderer::paint()
if (!m_d3dDevice)
return;
+ if (m_backingStoreDirty) {
+ // If the backing store is still dirty when we are about to draw the
+ // composited content, we need to force the window to paint into the
+ // backing store. The paint will only paint the dirty region that
+ // if being tracked in WebView.
+ UpdateWindow(m_hostWindow);
+ return;
+ }
+
Vector<CGRect> dirtyRects;
getDirtyRects(m_hostWindow, dirtyRects);
render(dirtyRects);
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
index 4e76f55..ea710b6 100644
--- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
@@ -47,6 +47,8 @@ typedef struct _CARenderOGLContext CARenderOGLContext;
namespace WebCore {
+class WKCACFRootLayer;
+
// 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)
@@ -58,19 +60,20 @@ public:
static bool acceleratedCompositingAvailable();
static void didFlushContext(CACFContextRef);
- void setScrollFrame(const IntRect&);
+ void setScrollFrame(const IntPoint&, const IntSize&);
void setRootContents(CGImageRef);
- void setRootChildLayer(WebCore::PlatformLayer* layer);
+ void setRootChildLayer(WKCACFLayer* layer);
void setNeedsDisplay();
- void setHostWindow(HWND window) { m_hostWindow = window; createRenderer(); }
-
- void createRenderer();
+ void setHostWindow(HWND window) { m_hostWindow = window; }
+ void setBackingStoreDirty(bool dirty) { m_backingStoreDirty = dirty; }
+ bool createRenderer();
void destroyRenderer();
void resize();
void renderSoon();
+ void updateScrollFrame();
protected:
- WKCACFLayer* rootLayer() const { return m_rootLayer.get(); }
+ WKCACFLayer* rootLayer() const;
private:
WKCACFLayerRenderer();
@@ -87,17 +90,19 @@ private:
bool m_triedToCreateD3DRenderer;
COMPtr<IDirect3DDevice9> m_d3dDevice;
- RefPtr<WKCACFLayer> m_rootLayer;
+ RefPtr<WKCACFRootLayer> m_rootLayer;
RefPtr<WKCACFLayer> m_viewLayer;
RefPtr<WKCACFLayer> m_scrollLayer;
RefPtr<WKCACFLayer> m_rootChildLayer;
+ RefPtr<WKCACFLayer> m_clipLayer;
RetainPtr<CACFContextRef> m_context;
CARenderContext* m_renderContext;
CARenderOGLContext* m_renderer;
HWND m_hostWindow;
Timer<WKCACFLayerRenderer> m_renderTimer;
- IntRect m_scrollFrame;
-
+ IntPoint m_scrollPosition;
+ IntSize m_scrollSize;
+ bool m_backingStoreDirty;
#ifndef NDEBUG
bool m_printTree;
#endif
diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
index 699ff25..d5f8a5a 100644
--- a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
@@ -25,6 +25,7 @@
#include "Base64.h"
#include "CachedFont.h"
#include "FontPlatformData.h"
+#include "SharedBuffer.h"
#include <wtf/RandomNumber.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/wince/FontPlatformData.cpp b/WebCore/platform/graphics/wince/FontPlatformData.cpp
index f0db2ff..74cadc2 100644
--- a/WebCore/platform/graphics/wince/FontPlatformData.cpp
+++ b/WebCore/platform/graphics/wince/FontPlatformData.cpp
@@ -26,8 +26,10 @@
#include "FontData.h"
#include "PlatformString.h"
#include "SimpleFontData.h"
+#include "StringHash.h"
#include "UnicodeRange.h"
#include "wtf/OwnPtr.h"
+#include <wtf/StdLibExtras.h>
#include <windows.h>
#include <mlang.h>
diff --git a/WebCore/platform/graphics/wince/FontWince.cpp b/WebCore/platform/graphics/wince/FontWince.cpp
index 6c03712..f8b1886 100644
--- a/WebCore/platform/graphics/wince/FontWince.cpp
+++ b/WebCore/platform/graphics/wince/FontWince.cpp
@@ -235,7 +235,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
}
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
TextRunComponents components;
int w = generateComponents(&components, *this, run);
diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
index 42e94a4..a7bb695 100644
--- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
+++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
@@ -23,6 +23,7 @@
#include "AffineTransform.h"
#include "CharacterNames.h"
+#include "Font.h"
#include "GlyphBuffer.h"
#include "Gradient.h"
#include "GraphicsContextPrivate.h"
diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp
index 9624e26..ac3a630 100644
--- a/WebCore/platform/graphics/wince/ImageBufferWince.cpp
+++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp
@@ -27,6 +27,7 @@
#include "JPEGEncoder.h"
#include "PNGEncoder.h"
#include "SharedBitmap.h"
+#include <wtf/UnusedParam.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.h b/WebCore/platform/graphics/wince/PlatformPathWince.h
index e614cec..614e8c5 100644
--- a/WebCore/platform/graphics/wince/PlatformPathWince.h
+++ b/WebCore/platform/graphics/wince/PlatformPathWince.h
@@ -20,6 +20,11 @@
#ifndef PlatformPathWince_h
#define PlatformPathWince_h
+#include "FloatPoint.h"
+#include "FloatRect.h"
+#include "Path.h"
+#include <wtf/Vector.h>
+
namespace WebCore {
class GraphicsContext;
diff --git a/WebCore/platform/graphics/wx/FontPlatformData.h b/WebCore/platform/graphics/wx/FontPlatformData.h
index be00edc..ecb957e 100644
--- a/WebCore/platform/graphics/wx/FontPlatformData.h
+++ b/WebCore/platform/graphics/wx/FontPlatformData.h
@@ -31,9 +31,9 @@
#include "FontDescription.h"
#include "AtomicString.h"
-#include "CString.h"
#include "StringImpl.h"
#include <wtf/RefPtr.h>
+#include <wtf/text/CString.h>
#include <wx/defs.h>
#include <wx/font.h>
@@ -65,21 +65,25 @@ public:
FontPlatformData(WTF::HashTableDeletedValueType)
: m_fontState(DELETED),
- m_font(0)
+ m_font(0),
+ m_size(0)
{ }
~FontPlatformData();
FontPlatformData(const FontDescription&, const AtomicString&);
+
FontPlatformData(float size, bool bold, bool italic)
: m_fontState(UNINITIALIZED)
, m_font(0)
+ , m_size(size)
{
}
FontPlatformData()
: m_fontState(UNINITIALIZED)
, m_font(0)
+ , m_size(0)
{
}
@@ -99,6 +103,8 @@ public:
}
unsigned computeHash() const;
+
+ float size() const { return m_size; }
bool operator==(const FontPlatformData& other) const
{
@@ -127,6 +133,7 @@ public:
private:
WTF::RefPtr<FontHolder> m_font;
FontState m_fontState;
+ float m_size;
};
}
diff --git a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
index c9646d7..a75d244 100644
--- a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
+++ b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
@@ -100,6 +100,7 @@ FontPlatformData::FontPlatformData(const FontDescription& desc, const AtomicStri
);
#endif
m_fontState = VALID;
+ m_size = desc.computedPixelSize();
}
diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp
index 98b5a0a..dce3841 100644
--- a/WebCore/platform/graphics/wx/FontWx.cpp
+++ b/WebCore/platform/graphics/wx/FontWx.cpp
@@ -121,7 +121,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const
{
#if OS(WINDOWS)
UniscribeController controller(this, run, fallbackFonts);
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 8e1a391..2298d6a 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -91,6 +91,7 @@ public:
#if USE(WXGC)
wxGCDC* context;
+ wxGraphicsPath currentPath;
#else
wxWindowDC* context;
#endif
@@ -124,6 +125,9 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
}
#if USE(WXGC)
m_data->context = (wxGCDC*)context;
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ if (gc)
+ m_data->currentPath = gc->CreatePath();
#else
m_data->context = (wxWindowDC*)context;
#endif
@@ -323,6 +327,11 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect&)
notImplemented();
}
+void GraphicsContext::clipPath(WindRule)
+{
+ notImplemented();
+}
+
void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
{
if (paintingDisabled())
@@ -361,7 +370,15 @@ void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
AffineTransform GraphicsContext::getCTM() const
{
- notImplemented();
+#if USE(WXGC)
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ if (gc) {
+ wxGraphicsMatrix matrix = gc->GetTransform();
+ double a, b, c, d, e, f;
+ matrix.Get(&a, &b, &c, &d, &e, &f);
+ return AffineTransform(a, b, c, d, e, f);
+ }
+#endif
return AffineTransform();
}
@@ -435,12 +452,19 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op)
void GraphicsContext::beginPath()
{
- notImplemented();
+#if USE(WXGC)
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ if (gc)
+ m_data->currentPath = gc->CreatePath();
+#endif
}
void GraphicsContext::addPath(const Path& path)
{
- notImplemented();
+#if USE(WXGC)
+ if (path.platformPath())
+ m_data->currentPath.AddPath(*path.platformPath());
+#endif
}
void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
@@ -476,7 +500,11 @@ void GraphicsContext::concatCTM(const AffineTransform& transform)
if (paintingDisabled())
return;
- notImplemented();
+#if USE(WXGC)
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ if (gc)
+ gc->ConcatTransform(transform);
+#endif
return;
}
@@ -498,10 +526,20 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const
void GraphicsContext::fillPath()
{
+#if USE(WXGC)
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ if (gc)
+ gc->FillPath(m_data->currentPath);
+#endif
}
void GraphicsContext::strokePath()
{
+#if USE(WXGC)
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ if (gc)
+ gc->StrokePath(m_data->currentPath);
+#endif
}
void GraphicsContext::drawPath()
@@ -551,6 +589,11 @@ void GraphicsContext::setLineCap(LineCap)
notImplemented();
}
+void GraphicsContext::setLineDash(const DashArray&, float dashOffset)
+{
+ notImplemented();
+}
+
void GraphicsContext::setLineJoin(LineJoin)
{
notImplemented();
diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
index 49f3f3b..6cc611e 100644
--- a/WebCore/platform/graphics/wx/ImageBufferWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
@@ -87,4 +87,9 @@ Image* ImageBuffer::image() const
return 0;
}
+void ImageBuffer::platformTransformColorSpace(const Vector<int>&)
+{
+ notImplemented();
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/graphics/wx/ImageWx.cpp b/WebCore/platform/graphics/wx/ImageWx.cpp
index c246ec1..b51bde8 100644
--- a/WebCore/platform/graphics/wx/ImageWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageWx.cpp
@@ -33,6 +33,7 @@
#include "GraphicsContext.h"
#include "ImageObserver.h"
#include "NotImplemented.h"
+#include "SharedBuffer.h"
#include <math.h>
#include <stdio.h>
diff --git a/WebCore/platform/graphics/wx/PathWx.cpp b/WebCore/platform/graphics/wx/PathWx.cpp
index 6c115ac..2305be0 100644
--- a/WebCore/platform/graphics/wx/PathWx.cpp
+++ b/WebCore/platform/graphics/wx/PathWx.cpp
@@ -30,6 +30,7 @@
#include "FloatPoint.h"
#include "FloatRect.h"
#include "NotImplemented.h"
+#include "PlatformString.h"
#include "StrokeStyleApplier.h"
#include <stdio.h>
@@ -110,10 +111,22 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
return FloatRect();
}
-Path& Path::operator=(const Path&)
+bool Path::strokeContains(StrokeStyleApplier*, const FloatPoint&) const
+{
+ notImplemented();
+ return false;
+}
+
+String Path::debugString() const
+{
+ notImplemented();
+ return String();
+}
+
+Path& Path::operator=(const Path& path)
{
- notImplemented();
- return*this;
+ *m_path = *path.platformPath();
+ return *this;
}
void Path::clear()
@@ -219,8 +232,8 @@ bool Path::isEmpty() const
{
#if USE(WXGC)
if (m_path) {
- wxDouble width, height;
- m_path->GetBox(NULL, NULL, &width, &height);
+ wxDouble x, y, width, height;
+ m_path->GetBox(&x, &y, &width, &height);
return (width == 0 && height == 0);
}
#endif
diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
index d9fd2b3..3c8a1da 100644
--- a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
+++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
@@ -112,17 +112,19 @@ void SimpleFontData::determinePitch()
m_treatAsFixedPitch = false;
}
-float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const
{
+ GlyphMetrics metrics;
#if __WXMSW__
// under Windows / wxMSW we currently always use GDI fonts.
- return widthForGDIGlyph(glyph);
+ metrics.horizontalAdvance = widthForGDIGlyph(glyph);
#else
// TODO: fix this! Make GetTextExtents a method of wxFont in 2.9
int width = 10;
GetTextExtent(*m_platformData.font(), (wxChar)glyph, &width, NULL);
- return width;
+ metrics.horizontalAdvance = width;
#endif
+ return metrics;
}
#if OS(WINDOWS)