summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics')
-rw-r--r--WebCore/platform/graphics/ANGLEWebKitBridge.cpp2
-rw-r--r--WebCore/platform/graphics/Color.cpp6
-rw-r--r--WebCore/platform/graphics/Color.h5
-rw-r--r--WebCore/platform/graphics/ColorSpace.h6
-rw-r--r--WebCore/platform/graphics/ContextShadow.cpp21
-rw-r--r--WebCore/platform/graphics/ContextShadow.h9
-rw-r--r--WebCore/platform/graphics/FloatRect.h9
-rw-r--r--WebCore/platform/graphics/GraphicsContext.cpp16
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h11
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.cpp241
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.h43
-rw-r--r--WebCore/platform/graphics/GraphicsContextPrivate.h4
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.cpp3
-rw-r--r--WebCore/platform/graphics/ImageBuffer.cpp10
-rw-r--r--WebCore/platform/graphics/ImageBuffer.h14
-rw-r--r--WebCore/platform/graphics/IntRect.h5
-rw-r--r--WebCore/platform/graphics/Path.cpp203
-rw-r--r--WebCore/platform/graphics/Path.h11
-rw-r--r--WebCore/platform/graphics/brew/ImageBrew.cpp4
-rw-r--r--WebCore/platform/graphics/cairo/CairoUtilities.cpp101
-rw-r--r--WebCore/platform/graphics/cairo/CairoUtilities.h14
-rw-r--r--WebCore/platform/graphics/cairo/ContextShadowCairo.cpp229
-rw-r--r--WebCore/platform/graphics/cairo/FloatRectCairo.cpp45
-rw-r--r--WebCore/platform/graphics/cairo/FontCacheFreeType.cpp79
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp152
-rw-r--r--WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp131
-rw-r--r--WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h5
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp480
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h5
-rw-r--r--WebCore/platform/graphics/cairo/ImageBufferCairo.cpp2
-rw-r--r--WebCore/platform/graphics/cairo/ImageCairo.cpp70
-rw-r--r--WebCore/platform/graphics/cairo/PathCairo.cpp36
-rw-r--r--WebCore/platform/graphics/cg/ColorCG.cpp93
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp112
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp93
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.h41
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h6
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp54
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferData.h3
-rw-r--r--WebCore/platform/graphics/cg/ImageCG.cpp17
-rw-r--r--WebCore/platform/graphics/cg/PathCG.cpp52
-rw-r--r--WebCore/platform/graphics/chromium/ContentLayerChromium.cpp129
-rw-r--r--WebCore/platform/graphics/chromium/ContentLayerChromium.h8
-rw-r--r--WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp23
-rw-r--r--WebCore/platform/graphics/chromium/FontLinux.cpp779
-rw-r--r--WebCore/platform/graphics/chromium/GLES2Canvas.cpp4
-rw-r--r--WebCore/platform/graphics/chromium/ImageLayerChromium.cpp14
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.cpp14
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.h7
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.cpp41
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.h16
-rw-r--r--WebCore/platform/graphics/chromium/TransparencyWin.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/VideoFrameChromium.h6
-rw-r--r--WebCore/platform/graphics/chromium/VideoFrameProvider.h2
-rw-r--r--WebCore/platform/graphics/chromium/VideoLayerChromium.cpp56
-rw-r--r--WebCore/platform/graphics/chromium/VideoLayerChromium.h16
-rw-r--r--WebCore/platform/graphics/efl/ImageEfl.cpp3
-rw-r--r--WebCore/platform/graphics/efl/IntRectEfl.cpp (renamed from WebCore/platform/graphics/filters/ImageBufferFilter.cpp)25
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.cpp6
-rw-r--r--WebCore/platform/graphics/filters/FEColorMatrix.cpp4
-rw-r--r--WebCore/platform/graphics/filters/FEComponentTransfer.cpp4
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.cpp48
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.h2
-rw-r--r--WebCore/platform/graphics/filters/FEConvolveMatrix.cpp4
-rw-r--r--WebCore/platform/graphics/filters/FEConvolveMatrix.h2
-rw-r--r--WebCore/platform/graphics/filters/FEDisplacementMap.cpp15
-rw-r--r--WebCore/platform/graphics/filters/FEDisplacementMap.h2
-rw-r--r--WebCore/platform/graphics/filters/FEFlood.cpp6
-rw-r--r--WebCore/platform/graphics/filters/FEFlood.h2
-rw-r--r--WebCore/platform/graphics/filters/FEGaussianBlur.cpp51
-rw-r--r--WebCore/platform/graphics/filters/FEGaussianBlur.h3
-rw-r--r--WebCore/platform/graphics/filters/FELighting.cpp9
-rw-r--r--WebCore/platform/graphics/filters/FELighting.h2
-rw-r--r--WebCore/platform/graphics/filters/FEMerge.cpp4
-rw-r--r--WebCore/platform/graphics/filters/FEMorphology.cpp22
-rw-r--r--WebCore/platform/graphics/filters/FEMorphology.h2
-rw-r--r--WebCore/platform/graphics/filters/FEOffset.cpp30
-rw-r--r--WebCore/platform/graphics/filters/FEOffset.h2
-rw-r--r--WebCore/platform/graphics/filters/FETile.cpp40
-rw-r--r--WebCore/platform/graphics/filters/FETile.h2
-rw-r--r--WebCore/platform/graphics/filters/FETurbulence.cpp8
-rw-r--r--WebCore/platform/graphics/filters/FETurbulence.h2
-rw-r--r--WebCore/platform/graphics/filters/Filter.h7
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.cpp33
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.h33
-rw-r--r--WebCore/platform/graphics/filters/ImageBufferFilter.h57
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.cpp22
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.h6
-rw-r--r--WebCore/platform/graphics/filters/SourceGraphic.cpp20
-rw-r--r--WebCore/platform/graphics/filters/SourceGraphic.h6
-rw-r--r--WebCore/platform/graphics/gpu/DrawingBuffer.cpp37
-rw-r--r--WebCore/platform/graphics/gpu/DrawingBuffer.h40
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnClassifier.cpp4
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.cpp4
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp7
-rw-r--r--WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.cpp4
-rw-r--r--WebCore/platform/graphics/gpu/PODInterval.h26
-rw-r--r--WebCore/platform/graphics/gpu/PODIntervalTree.h17
-rw-r--r--WebCore/platform/graphics/gpu/PODRedBlackTree.h17
-rw-r--r--WebCore/platform/graphics/gpu/Shader.cpp5
-rw-r--r--WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp34
-rw-r--r--WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h9
-rw-r--r--WebCore/platform/graphics/gpu/SolidFillShader.cpp5
-rw-r--r--WebCore/platform/graphics/gpu/TexShader.cpp5
-rw-r--r--WebCore/platform/graphics/gpu/Texture.cpp4
-rw-r--r--WebCore/platform/graphics/gpu/Texture.h4
-rw-r--r--WebCore/platform/graphics/gpu/TilingData.cpp5
-rw-r--r--WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm84
-rw-r--r--WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp4
-rw-r--r--WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp2
-rw-r--r--WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h4
-rw-r--r--WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp4
-rw-r--r--WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp5
-rw-r--r--WebCore/platform/graphics/gtk/FontGtk.cpp50
-rw-r--r--WebCore/platform/graphics/gtk/ImageBufferGtk.cpp3
-rw-r--r--WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp4
-rw-r--r--WebCore/platform/graphics/haiku/PathHaiku.cpp6
-rw-r--r--WebCore/platform/graphics/mac/ColorMac.mm24
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.mm4
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContextMac.mm24
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm12
-rw-r--r--WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp21
-rw-r--r--WebCore/platform/graphics/openvg/PathOpenVG.cpp12
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp5
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp44
-rw-r--r--WebCore/platform/graphics/qt/GraphicsLayerQt.cpp36
-rw-r--r--WebCore/platform/graphics/qt/GraphicsLayerQt.h1
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp14
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp86
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h12
-rw-r--r--WebCore/platform/graphics/qt/PathQt.cpp37
-rw-r--r--WebCore/platform/graphics/qt/TextureMapperQt.cpp225
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp7
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp17
-rw-r--r--WebCore/platform/graphics/skia/PathSkia.cpp56
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.cpp19
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.h9
-rw-r--r--WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp1444
-rw-r--r--WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h96
-rw-r--r--WebCore/platform/graphics/texmap/TextureMapper.h120
-rw-r--r--WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h70
-rw-r--r--WebCore/platform/graphics/transforms/AffineTransform.cpp14
-rw-r--r--WebCore/platform/graphics/transforms/AffineTransform.h5
-rw-r--r--WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h2
-rw-r--r--WebCore/platform/graphics/transforms/MatrixTransformOperation.h2
-rw-r--r--WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h2
-rw-r--r--WebCore/platform/graphics/transforms/RotateTransformOperation.h3
-rw-r--r--WebCore/platform/graphics/transforms/SkewTransformOperation.h3
-rw-r--r--WebCore/platform/graphics/transforms/TranslateTransformOperation.h4
-rw-r--r--WebCore/platform/graphics/win/FontCGWin.cpp6
-rw-r--r--WebCore/platform/graphics/win/GDIExtras.cpp43
-rw-r--r--WebCore/platform/graphics/win/GDIExtras.h65
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCGWin.cpp12
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.cpp8
-rw-r--r--WebCore/platform/graphics/win/ImageCGWin.cpp4
-rw-r--r--WebCore/platform/graphics/win/ImageCairoWin.cpp8
-rw-r--r--[-rwxr-xr-x]WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp0
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp41
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h8
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp6
-rw-r--r--WebCore/platform/graphics/win/WKCACFContextFlusher.cpp23
-rw-r--r--WebCore/platform/graphics/win/WKCACFContextFlusher.h8
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.cpp13
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.h4
-rw-r--r--[-rwxr-xr-x]WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp70
-rw-r--r--[-rwxr-xr-x]WebCore/platform/graphics/win/WKCACFLayerRenderer.h10
-rw-r--r--WebCore/platform/graphics/win/WebLayer.cpp4
-rw-r--r--WebCore/platform/graphics/win/WebTiledLayer.cpp2
-rw-r--r--WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp161
-rw-r--r--WebCore/platform/graphics/wince/ImageWinCE.cpp4
-rw-r--r--WebCore/platform/graphics/wince/PathWinCE.cpp5
-rw-r--r--WebCore/platform/graphics/wince/PlatformPathWinCE.cpp37
-rw-r--r--WebCore/platform/graphics/wince/PlatformPathWinCE.h1
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp4
-rw-r--r--WebCore/platform/graphics/wx/PathWx.cpp6
176 files changed, 5046 insertions, 2376 deletions
diff --git a/WebCore/platform/graphics/ANGLEWebKitBridge.cpp b/WebCore/platform/graphics/ANGLEWebKitBridge.cpp
index 9a14820..64f19c4 100644
--- a/WebCore/platform/graphics/ANGLEWebKitBridge.cpp
+++ b/WebCore/platform/graphics/ANGLEWebKitBridge.cpp
@@ -44,8 +44,6 @@ ANGLEWebKitBridge::~ANGLEWebKitBridge()
ShDestruct(m_fragmentCompiler);
ShDestruct(m_vertexCompiler);
}
-
- ShFinalize();
}
bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog)
diff --git a/WebCore/platform/graphics/Color.cpp b/WebCore/platform/graphics/Color.cpp
index f28d51c..fa7346e 100644
--- a/WebCore/platform/graphics/Color.cpp
+++ b/WebCore/platform/graphics/Color.cpp
@@ -175,8 +175,7 @@ Color::Color(const char* name)
m_valid = parseHexColor(&name[1], m_color);
else {
const NamedColor* foundColor = findColor(name, strlen(name));
- m_color = foundColor ? foundColor->RGBValue : 0;
- m_color |= 0xFF000000;
+ m_color = foundColor ? foundColor->ARGBValue : 0;
m_valid = foundColor;
}
}
@@ -219,8 +218,7 @@ static inline const NamedColor* findNamedColor(const String& name)
void Color::setNamedColor(const String& name)
{
const NamedColor* foundColor = findNamedColor(name);
- m_color = foundColor ? foundColor->RGBValue : 0;
- m_color |= 0xFF000000;
+ m_color = foundColor ? foundColor->ARGBValue : 0;
m_valid = foundColor;
}
diff --git a/WebCore/platform/graphics/Color.h b/WebCore/platform/graphics/Color.h
index 22a8a8f..276e69f 100644
--- a/WebCore/platform/graphics/Color.h
+++ b/WebCore/platform/graphics/Color.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-6 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,6 +31,7 @@
#include <wtf/unicode/Unicode.h>
#if PLATFORM(CG)
+#include "ColorSpace.h"
typedef struct CGColor* CGColorRef;
#endif
@@ -180,7 +181,7 @@ Color colorFromPremultipliedARGB(unsigned);
unsigned premultipliedARGBFromColor(const Color&);
#if PLATFORM(CG)
-CGColorRef createCGColor(const Color&);
+CGColorRef cachedCGColor(const Color&, ColorSpace);
#endif
} // namespace WebCore
diff --git a/WebCore/platform/graphics/ColorSpace.h b/WebCore/platform/graphics/ColorSpace.h
index 1bad58c..7622c47 100644
--- a/WebCore/platform/graphics/ColorSpace.h
+++ b/WebCore/platform/graphics/ColorSpace.h
@@ -28,7 +28,11 @@
namespace WebCore {
- enum ColorSpace { DeviceColorSpace, sRGBColorSpace };
+enum ColorSpace {
+ ColorSpaceDeviceRGB,
+ ColorSpaceSRGB,
+ ColorSpaceLinearRGB
+};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/ContextShadow.cpp b/WebCore/platform/graphics/ContextShadow.cpp
index 1007962..87a1c5c 100644
--- a/WebCore/platform/graphics/ContextShadow.cpp
+++ b/WebCore/platform/graphics/ContextShadow.cpp
@@ -39,18 +39,20 @@ namespace WebCore {
ContextShadow::ContextShadow()
: m_type(NoShadow)
- , m_blurRadius(0)
+ , m_blurDistance(0)
+ , m_layerContext(0)
{
}
ContextShadow::ContextShadow(const Color& color, float radius, const FloatSize& offset)
: m_color(color)
- , m_blurRadius(round(radius))
+ , m_blurDistance(round(radius))
, m_offset(offset)
+ , m_layerContext(0)
{
// See comments in http://webkit.org/b/40793, it seems sensible
// to follow Skia's limit of 128 pixels of blur radius
- m_blurRadius = min(m_blurRadius, 128);
+ m_blurDistance = min(m_blurDistance, 128);
// The type of shadow is decided by the blur radius, shadow offset, and shadow color.
if (!m_color.isValid() || !color.alpha()) {
@@ -71,7 +73,7 @@ void ContextShadow::clear()
{
m_type = NoShadow;
m_color = Color();
- m_blurRadius = 0;
+ m_blurDistance = 0;
m_offset = FloatSize();
}
@@ -85,8 +87,9 @@ static const int BlurSumShift = 15;
void ContextShadow::blurLayerImage(unsigned char* imageData, const IntSize& size, int rowStride)
{
int channels[4] = { 3, 0, 1, 3 };
- int dmax = m_blurRadius >> 1;
- int dmin = dmax - 1 + (m_blurRadius & 1);
+ int d = max(2, static_cast<int>(floorf((2 / 3.f) * m_blurDistance)));
+ int dmax = d >> 1;
+ int dmin = dmax - 1 + (d & 1);
if (dmin < 0)
dmin = 0;
@@ -153,8 +156,8 @@ void ContextShadow::calculateLayerBoundingRect(const FloatRect& layerArea, const
destinationRect.move(m_offset);
m_layerRect = enclosingIntRect(destinationRect);
- // We expand the area by the blur radius * 2 to give extra space for the blur transition.
- m_layerRect.inflate((m_type == BlurShadow) ? ceil(m_blurRadius * 2) : 0);
+ // We expand the area by the blur radius to give extra space for the blur transition.
+ m_layerRect.inflate(m_type == BlurShadow ? m_blurDistance : 0);
if (!clipRect.contains(m_layerRect)) {
// No need to have the buffer larger than the clip.
@@ -167,7 +170,7 @@ void ContextShadow::calculateLayerBoundingRect(const FloatRect& layerArea, const
// We adjust again because the pixels at the borders are still
// potentially affected by the pixels outside the buffer.
if (m_type == BlurShadow)
- m_layerRect.inflate((m_type == BlurShadow) ? ceil(m_blurRadius * 2) : 0);
+ m_layerRect.inflate(m_type == BlurShadow ? m_blurDistance : 0);
}
}
diff --git a/WebCore/platform/graphics/ContextShadow.h b/WebCore/platform/graphics/ContextShadow.h
index ede9336..0160f8a 100644
--- a/WebCore/platform/graphics/ContextShadow.h
+++ b/WebCore/platform/graphics/ContextShadow.h
@@ -31,6 +31,7 @@
#include "Color.h"
#include "FloatRect.h"
+#include "GraphicsContext.h"
#include "IntRect.h"
#include "RefCounted.h"
@@ -65,7 +66,7 @@ public:
} m_type;
Color m_color;
- int m_blurRadius;
+ int m_blurDistance;
FloatSize m_offset;
ContextShadow();
@@ -98,6 +99,9 @@ public:
PlatformContext beginShadowLayer(PlatformContext, const FloatRect& layerArea);
void endShadowLayer(PlatformContext);
static void purgeScratchBuffer();
+#if PLATFORM(CAIRO)
+ void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius = IntSize(), const IntSize& topRightRadius = IntSize(), const IntSize& bottomLeftRadius = IntSize(), const IntSize& bottomRightRadius = IntSize());
+#endif
#if PLATFORM(QT)
QPointF offset() { return QPointF(m_offset.width(), m_offset.height()); }
@@ -111,6 +115,9 @@ private:
void blurLayerImage(unsigned char*, const IntSize& imageSize, int stride);
void calculateLayerBoundingRect(const FloatRect& layerArea, const IntRect& clipRect);
+#if PLATFORM(CAIRO)
+ void drawRectShadowWithoutTiling(PlatformContext context, const IntRect& shadowRect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius, float alpha);
+#endif
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h
index e387927..10ad838 100644
--- a/WebCore/platform/graphics/FloatRect.h
+++ b/WebCore/platform/graphics/FloatRect.h
@@ -59,6 +59,10 @@ class BRect;
struct SkRect;
#endif
+#if PLATFORM(CAIRO)
+typedef struct _cairo_rectangle cairo_rectangle_t;
+#endif
+
namespace WebCore {
#if PLATFORM(OPENVG)
@@ -172,6 +176,11 @@ public:
operator VGRect() const;
#endif
+#if PLATFORM(CAIRO)
+ FloatRect(const cairo_rectangle_t&);
+ operator cairo_rectangle_t() const;
+#endif
+
private:
FloatPoint m_location;
FloatSize m_size;
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index 3dfdb20..ec15d26 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -219,7 +219,7 @@ void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
{
ASSERT(pattern);
if (!pattern) {
- setStrokeColor(Color::black, DeviceColorSpace);
+ setStrokeColor(Color::black, ColorSpaceDeviceRGB);
return;
}
m_common->state.strokeGradient.clear();
@@ -231,7 +231,7 @@ void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
{
ASSERT(pattern);
if (!pattern) {
- setFillColor(Color::black, DeviceColorSpace);
+ setFillColor(Color::black, ColorSpaceDeviceRGB);
return;
}
m_common->state.fillGradient.clear();
@@ -243,7 +243,7 @@ void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
{
ASSERT(gradient);
if (!gradient) {
- setStrokeColor(Color::black, DeviceColorSpace);
+ setStrokeColor(Color::black, ColorSpaceDeviceRGB);
return;
}
m_common->state.strokeGradient = gradient;
@@ -255,7 +255,7 @@ void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
{
ASSERT(gradient);
if (!gradient) {
- setFillColor(Color::black, DeviceColorSpace);
+ setFillColor(Color::black, ColorSpaceDeviceRGB);
return;
}
m_common->state.fillGradient = gradient;
@@ -500,7 +500,9 @@ void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& top
if (paintingDisabled())
return;
- clip(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
+ Path path;
+ path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
+ clip(path);
}
void GraphicsContext::clipOutRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
@@ -509,7 +511,9 @@ void GraphicsContext::clipOutRoundedRect(const IntRect& rect, const IntSize& top
if (paintingDisabled())
return;
- clipOut(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
+ Path path;
+ path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
+ clipOut(path);
}
void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& rect)
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index fd3bf2c..b1fa48a 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -41,6 +41,9 @@
typedef struct CGContext PlatformGraphicsContext;
#elif PLATFORM(CAIRO)
#include "PlatformRefPtrCairo.h"
+namespace WebCore {
+class ContextShadow;
+}
typedef struct _cairo PlatformGraphicsContext;
#elif PLATFORM(OPENVG)
namespace WebCore {
@@ -333,11 +336,6 @@ namespace WebCore {
void setAlpha(float);
#if PLATFORM(CAIRO)
float getAlpha();
- void applyPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float radius);
- PlatformRefPtr<cairo_surface_t> createShadowMask(PassOwnPtr<ImageBuffer>, const FloatRect&, float radius);
-
- static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowOffset, float shadowBlur);
- void drawTiledShadow(const IntRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, ColorSpace colorSpace);
#endif
void setCompositeOperation(CompositeOperator);
@@ -438,6 +436,9 @@ namespace WebCore {
void pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask);
QPen pen();
static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op);
+#endif
+
+#if PLATFORM(QT) || PLATFORM(CAIRO)
ContextShadow* contextShadow();
#endif
diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp
index 86e9569..d2e9057 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.cpp
+++ b/WebCore/platform/graphics/GraphicsContext3D.cpp
@@ -31,11 +31,27 @@
#include "GraphicsContext3D.h"
#include "ArrayBufferView.h"
+#include "DrawingBuffer.h"
#include "Image.h"
#include "ImageData.h"
namespace WebCore {
+static uint8_t convertColor16LittleTo8(uint16_t value)
+{
+ return value >> 8;
+}
+
+static uint8_t convertColor16BigTo8(uint16_t value)
+{
+ return static_cast<uint8_t>(value & 0x00FF);
+}
+
+PassRefPtr<DrawingBuffer> GraphicsContext3D::createDrawingBuffer(const IntSize& size)
+{
+ return DrawingBuffer::create(this, size);
+}
+
bool GraphicsContext3D::computeFormatAndTypeParameters(unsigned int format,
unsigned int type,
unsigned long* componentsPerPixel,
@@ -247,6 +263,22 @@ void unpackRGBA8ToRGBA8(const uint8_t* source, uint8_t* destination)
destination[3] = source[3];
}
+void unpackRGBA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16LittleTo8(source[0]);
+ destination[1] = convertColor16LittleTo8(source[1]);
+ destination[2] = convertColor16LittleTo8(source[2]);
+ destination[3] = convertColor16LittleTo8(source[3]);
+}
+
+void unpackRGBA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16BigTo8(source[0]);
+ destination[1] = convertColor16BigTo8(source[1]);
+ destination[2] = convertColor16BigTo8(source[2]);
+ destination[3] = convertColor16BigTo8(source[3]);
+}
+
void unpackRGB8ToRGBA8(const uint8_t* source, uint8_t* destination)
{
destination[0] = source[0];
@@ -255,6 +287,22 @@ void unpackRGB8ToRGBA8(const uint8_t* source, uint8_t* destination)
destination[3] = 0xFF;
}
+void unpackRGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16LittleTo8(source[0]);
+ destination[1] = convertColor16LittleTo8(source[1]);
+ destination[2] = convertColor16LittleTo8(source[2]);
+ destination[3] = 0xFF;
+}
+
+void unpackRGB16BigToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16BigTo8(source[0]);
+ destination[1] = convertColor16BigTo8(source[1]);
+ destination[2] = convertColor16BigTo8(source[2]);
+ destination[3] = 0xFF;
+}
+
void unpackARGB8ToRGBA8(const uint8_t* source, uint8_t* destination)
{
destination[0] = source[1];
@@ -263,6 +311,22 @@ void unpackARGB8ToRGBA8(const uint8_t* source, uint8_t* destination)
destination[3] = source[0];
}
+void unpackARGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16LittleTo8(source[1]);
+ destination[1] = convertColor16LittleTo8(source[2]);
+ destination[2] = convertColor16LittleTo8(source[3]);
+ destination[3] = convertColor16LittleTo8(source[0]);
+}
+
+void unpackARGB16BigToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16BigTo8(source[1]);
+ destination[1] = convertColor16BigTo8(source[2]);
+ destination[2] = convertColor16BigTo8(source[3]);
+ destination[3] = convertColor16BigTo8(source[0]);
+}
+
void unpackBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination)
{
destination[0] = source[2];
@@ -271,6 +335,22 @@ void unpackBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination)
destination[3] = source[3];
}
+void unpackBGRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16LittleTo8(source[2]);
+ destination[1] = convertColor16LittleTo8(source[1]);
+ destination[2] = convertColor16LittleTo8(source[0]);
+ destination[3] = convertColor16LittleTo8(source[3]);
+}
+
+void unpackBGRA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16BigTo8(source[2]);
+ destination[1] = convertColor16BigTo8(source[1]);
+ destination[2] = convertColor16BigTo8(source[0]);
+ destination[3] = convertColor16BigTo8(source[3]);
+}
+
void unpackRGBA5551ToRGBA8(const uint16_t* source, uint8_t* destination)
{
uint16_t packedValue = source[0];
@@ -316,6 +396,22 @@ void unpackR8ToRGBA8(const uint8_t* source, uint8_t* destination)
destination[3] = 0xFF;
}
+void unpackR16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16LittleTo8(source[0]);
+ destination[1] = convertColor16LittleTo8(source[0]);
+ destination[2] = convertColor16LittleTo8(source[0]);
+ destination[3] = 0xFF;
+}
+
+void unpackR16BigToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16BigTo8(source[0]);
+ destination[1] = convertColor16BigTo8(source[0]);
+ destination[2] = convertColor16BigTo8(source[0]);
+ destination[3] = 0xFF;
+}
+
void unpackRA8ToRGBA8(const uint8_t* source, uint8_t* destination)
{
destination[0] = source[0];
@@ -324,6 +420,22 @@ void unpackRA8ToRGBA8(const uint8_t* source, uint8_t* destination)
destination[3] = source[1];
}
+void unpackRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16LittleTo8(source[0]);
+ destination[1] = convertColor16LittleTo8(source[0]);
+ destination[2] = convertColor16LittleTo8(source[0]);
+ destination[3] = convertColor16LittleTo8(source[1]);
+}
+
+void unpackRA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16BigTo8(source[0]);
+ destination[1] = convertColor16BigTo8(source[0]);
+ destination[2] = convertColor16BigTo8(source[0]);
+ destination[3] = convertColor16BigTo8(source[1]);
+}
+
void unpackAR8ToRGBA8(const uint8_t* source, uint8_t* destination)
{
destination[0] = source[1];
@@ -332,6 +444,22 @@ void unpackAR8ToRGBA8(const uint8_t* source, uint8_t* destination)
destination[3] = source[0];
}
+void unpackAR16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16LittleTo8(source[1]);
+ destination[1] = convertColor16LittleTo8(source[1]);
+ destination[2] = convertColor16LittleTo8(source[1]);
+ destination[3] = convertColor16LittleTo8(source[0]);
+}
+
+void unpackAR16BigToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = convertColor16BigTo8(source[1]);
+ destination[1] = convertColor16BigTo8(source[1]);
+ destination[2] = convertColor16BigTo8(source[1]);
+ destination[3] = convertColor16BigTo8(source[0]);
+}
+
void unpackA8ToRGBA8(const uint8_t* source, uint8_t* destination)
{
destination[0] = 0x0;
@@ -340,6 +468,22 @@ void unpackA8ToRGBA8(const uint8_t* source, uint8_t* destination)
destination[3] = source[0];
}
+void unpackA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = 0x0;
+ destination[1] = 0x0;
+ destination[2] = 0x0;
+ destination[3] = convertColor16LittleTo8(source[0]);
+}
+
+void unpackA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
+{
+ destination[0] = 0x0;
+ destination[1] = 0x0;
+ destination[2] = 0x0;
+ destination[3] = convertColor16BigTo8(source[0]);
+}
+
//----------------------------------------------------------------------
// Pixel packing routines.
//
@@ -602,6 +746,7 @@ static void computeIncrementParameters(unsigned int width,
{
unsigned int elementSizeInBytes = sizeof(SourceType);
ASSERT(elementSizeInBytes <= bytesPerPixel);
+ ASSERT(!(bytesPerPixel % elementSizeInBytes));
unsigned int validRowBytes = width * bytesPerPixel;
unsigned int totalRowBytes = validRowBytes;
if (unpackAlignment) {
@@ -644,24 +789,72 @@ static void doPacking(const void* sourceData,
}
break;
}
+ case GraphicsContext3D::kSourceFormatRGBA16Little: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackRGBA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::kSourceFormatRGBA16Big: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackRGBA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
case GraphicsContext3D::kSourceFormatRGB8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
doUnpackingAndPacking<uint8_t, DestType, unpackRGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
+ case GraphicsContext3D::kSourceFormatRGB16Little: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 6, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackRGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::kSourceFormatRGB16Big: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 6, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackRGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
case GraphicsContext3D::kSourceFormatARGB8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
doUnpackingAndPacking<uint8_t, DestType, unpackARGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
+ case GraphicsContext3D::kSourceFormatARGB16Little: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackARGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::kSourceFormatARGB16Big: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackARGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
case GraphicsContext3D::kSourceFormatBGRA8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
doUnpackingAndPacking<uint8_t, DestType, unpackBGRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
+ case GraphicsContext3D::kSourceFormatBGRA16Little: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackBGRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::kSourceFormatBGRA16Big: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackBGRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
case GraphicsContext3D::kSourceFormatRGBA5551: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
@@ -686,24 +879,72 @@ static void doPacking(const void* sourceData,
doUnpackingAndPacking<uint8_t, DestType, unpackR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
+ case GraphicsContext3D::kSourceFormatR16Little: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::kSourceFormatR16Big: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
case GraphicsContext3D::kSourceFormatRA8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
doUnpackingAndPacking<uint8_t, DestType, unpackRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
+ case GraphicsContext3D::kSourceFormatRA16Little: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::kSourceFormatRA16Big: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
case GraphicsContext3D::kSourceFormatAR8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
doUnpackingAndPacking<uint8_t, DestType, unpackAR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
+ case GraphicsContext3D::kSourceFormatAR16Little: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackAR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::kSourceFormatAR16Big: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackAR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
case GraphicsContext3D::kSourceFormatA8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
doUnpackingAndPacking<uint8_t, DestType, unpackA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
+ case GraphicsContext3D::kSourceFormatA16Little: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::kSourceFormatA16Big: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<uint16_t, DestType, unpackA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
}
}
diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h
index a12b1c4..d74c97c 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/WebCore/platform/graphics/GraphicsContext3D.h
@@ -26,16 +26,12 @@
#ifndef GraphicsContext3D_h
#define GraphicsContext3D_h
-#if PLATFORM(MAC)
-#include "ANGLEWebKitBridge.h"
-#endif
#include "GraphicsLayer.h"
#include "PlatformString.h"
#include <wtf/HashMap.h>
#include <wtf/ListHashSet.h>
#include <wtf/Noncopyable.h>
-#include <wtf/PassOwnPtr.h>
// FIXME: Find a better way to avoid the name confliction for NO_ERROR.
#if ((PLATFORM(CHROMIUM) && OS(WINDOWS)) || PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)))
@@ -43,6 +39,7 @@
#endif
#if PLATFORM(MAC)
+#include "ANGLEWebKitBridge.h"
#include <OpenGL/OpenGL.h>
#include <wtf/RetainPtr.h>
@@ -78,6 +75,7 @@ const Platform3DObject NullPlatform3DObject = 0;
namespace WebCore {
class CanvasRenderingContext;
+class DrawingBuffer;
class HostWindow;
class Image;
class ImageData;
@@ -94,7 +92,7 @@ struct ActiveInfo {
class GraphicsContext3DInternal;
#endif
-class GraphicsContext3D : public Noncopyable {
+class GraphicsContext3D : public RefCounted<GraphicsContext3D> {
public:
enum WebGLEnumType {
DEPTH_BUFFER_BIT = 0x00000100,
@@ -409,7 +407,13 @@ public:
// GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object)
READ_ONLY = 0x88B8,
- WRITE_ONLY = 0x88B9
+ WRITE_ONLY = 0x88B9,
+
+ // GL_ARB_robustness enums
+ GUILTY_CONTEXT_RESET_ARB = 0x8253,
+ INNOCENT_CONTEXT_RESET_ARB = 0x8254,
+ UNKNOWN_CONTEXT_RESET_ARB = 0x8255
+
};
// Context creation attributes.
@@ -435,8 +439,8 @@ public:
RenderDirectlyToHostWindow
};
- static PassOwnPtr<GraphicsContext3D> create(Attributes attrs, HostWindow* hostWindow, RenderStyle renderStyle = RenderOffscreen);
- virtual ~GraphicsContext3D();
+ static PassRefPtr<GraphicsContext3D> create(Attributes, HostWindow*, RenderStyle = RenderOffscreen);
+ ~GraphicsContext3D();
#if PLATFORM(MAC)
PlatformGraphicsContext3D platformGraphicsContext3D() const { return m_contextObj; }
@@ -463,6 +467,8 @@ public:
#endif
void makeContextCurrent();
+ PassRefPtr<DrawingBuffer> createDrawingBuffer(const IntSize& = IntSize());
+
#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
// With multisampling on, blit from multisampleFBO to regular FBO.
void prepareTexture();
@@ -535,16 +541,32 @@ public:
// by non-member functions.
enum SourceDataFormat {
kSourceFormatRGBA8,
+ kSourceFormatRGBA16Little,
+ kSourceFormatRGBA16Big,
kSourceFormatRGB8,
+ kSourceFormatRGB16Little,
+ kSourceFormatRGB16Big,
kSourceFormatBGRA8,
+ kSourceFormatBGRA16Little,
+ kSourceFormatBGRA16Big,
kSourceFormatARGB8,
+ kSourceFormatARGB16Little,
+ kSourceFormatARGB16Big,
kSourceFormatRGBA5551,
kSourceFormatRGBA4444,
kSourceFormatRGB565,
kSourceFormatR8,
+ kSourceFormatR16Little,
+ kSourceFormatR16Big,
kSourceFormatRA8,
+ kSourceFormatRA16Little,
+ kSourceFormatRA16Big,
kSourceFormatAR8,
- kSourceFormatA8
+ kSourceFormatAR16Little,
+ kSourceFormatAR16Big,
+ kSourceFormatA8,
+ kSourceFormatA16Little,
+ kSourceFormatA16Big
};
//----------------------------------------------------------------------
@@ -777,6 +799,9 @@ public:
bool supportsCopyTextureToParentTextureCHROMIUM();
void copyTextureToParentTextureCHROMIUM(unsigned texture, unsigned parentTexture);
+ // GL_ARB_robustness
+ int getGraphicsResetStatusARB();
+
private:
GraphicsContext3D(Attributes attrs, HostWindow* hostWindow, bool renderDirectlyToHostWindow);
diff --git a/WebCore/platform/graphics/GraphicsContextPrivate.h b/WebCore/platform/graphics/GraphicsContextPrivate.h
index 903c7e3..985cad9 100644
--- a/WebCore/platform/graphics/GraphicsContextPrivate.h
+++ b/WebCore/platform/graphics/GraphicsContextPrivate.h
@@ -39,10 +39,10 @@ namespace WebCore {
, strokeStyle(SolidStroke)
, strokeThickness(0)
, strokeColor(Color::black)
- , strokeColorSpace(DeviceColorSpace)
+ , strokeColorSpace(ColorSpaceDeviceRGB)
, fillRule(RULE_NONZERO)
, fillColor(Color::black)
- , fillColorSpace(DeviceColorSpace)
+ , fillColorSpace(ColorSpaceDeviceRGB)
, shouldAntialias(true)
, paintingDisabled(false)
, shadowBlur(0)
diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp
index 412f06d..08b79ab 100644
--- a/WebCore/platform/graphics/GraphicsLayer.cpp
+++ b/WebCore/platform/graphics/GraphicsLayer.cpp
@@ -33,6 +33,7 @@
#include "RotateTransformOperation.h"
#include "TextStream.h"
#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
#ifndef NDEBUG
#include <stdio.h>
@@ -249,7 +250,7 @@ void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const I
String GraphicsLayer::animationNameForTransition(AnimatedPropertyID property)
{
// | is not a valid identifier character in CSS, so this can never conflict with a keyframe identifier.
- return String::format("-|transition%c-", property);
+ return makeString("-|transition", static_cast<char>(property), '-');
}
void GraphicsLayer::suspendAnimations(double)
diff --git a/WebCore/platform/graphics/ImageBuffer.cpp b/WebCore/platform/graphics/ImageBuffer.cpp
index 71b8189..4a76be4 100644
--- a/WebCore/platform/graphics/ImageBuffer.cpp
+++ b/WebCore/platform/graphics/ImageBuffer.cpp
@@ -32,17 +32,17 @@
namespace WebCore {
-void ImageBuffer::transformColorSpace(ImageColorSpace srcColorSpace, ImageColorSpace dstColorSpace)
+void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace)
{
if (srcColorSpace == dstColorSpace)
return;
// only sRGB <-> linearRGB are supported at the moment
- if ((srcColorSpace != LinearRGB && srcColorSpace != DeviceRGB) ||
- (dstColorSpace != LinearRGB && dstColorSpace != DeviceRGB))
+ if ((srcColorSpace != ColorSpaceLinearRGB && srcColorSpace != ColorSpaceDeviceRGB)
+ || (dstColorSpace != ColorSpaceLinearRGB && dstColorSpace != ColorSpaceDeviceRGB))
return;
- if (dstColorSpace == LinearRGB) {
+ if (dstColorSpace == ColorSpaceLinearRGB) {
if (m_linearRgbLUT.isEmpty()) {
for (unsigned i = 0; i < 256; i++) {
float color = i / 255.0f;
@@ -53,7 +53,7 @@ void ImageBuffer::transformColorSpace(ImageColorSpace srcColorSpace, ImageColorS
}
}
platformTransformColorSpace(m_linearRgbLUT);
- } else if (dstColorSpace == DeviceRGB) {
+ } else if (dstColorSpace == ColorSpaceDeviceRGB) {
if (m_deviceRgbLUT.isEmpty()) {
for (unsigned i = 0; i < 256; i++) {
float color = i / 255.0f;
diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h
index 3c0508e..822a0ff 100644
--- a/WebCore/platform/graphics/ImageBuffer.h
+++ b/WebCore/platform/graphics/ImageBuffer.h
@@ -29,6 +29,7 @@
#define ImageBuffer_h
#include "AffineTransform.h"
+#include "ColorSpace.h"
#include "FloatRect.h"
#include "Image.h"
#include "IntSize.h"
@@ -44,13 +45,6 @@ namespace WebCore {
class ImageData;
class IntPoint;
class IntRect;
-
- enum ImageColorSpace {
- Unknown,
- DeviceRGB, // like sRGB
- GrayScale,
- LinearRGB
- };
enum Multiply {
Premultiplied,
@@ -60,7 +54,7 @@ namespace WebCore {
class ImageBuffer : public Noncopyable {
public:
// Will return a null pointer on allocation failure.
- static PassOwnPtr<ImageBuffer> create(const IntSize& size, ImageColorSpace colorSpace = DeviceRGB)
+ static PassOwnPtr<ImageBuffer> create(const IntSize& size, ColorSpace colorSpace = ColorSpaceDeviceRGB)
{
bool success = false;
OwnPtr<ImageBuffer> buf(new ImageBuffer(size, colorSpace, success));
@@ -89,7 +83,7 @@ namespace WebCore {
String toDataURL(const String& mimeType, const double* quality = 0) const;
#if !PLATFORM(CG)
AffineTransform baseTransform() const { return AffineTransform(); }
- void transformColorSpace(ImageColorSpace srcColorSpace, ImageColorSpace dstColorSpace);
+ void transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace);
void platformTransformColorSpace(const Vector<int>&);
#else
AffineTransform baseTransform() const { return AffineTransform(1, 0, 0, -1, 0, m_size.height()); }
@@ -119,7 +113,7 @@ namespace WebCore {
// This constructor will place its success into the given out-variable
// so that create() knows when it should return failure.
- ImageBuffer(const IntSize&, ImageColorSpace colorSpace, bool& success);
+ ImageBuffer(const IntSize&, ColorSpace colorSpace, bool& success);
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h
index c5990ef..c8d7c71 100644
--- a/WebCore/platform/graphics/IntRect.h
+++ b/WebCore/platform/graphics/IntRect.h
@@ -56,6 +56,8 @@ typedef cairo_rectangle_int_t GdkRectangle;
#endif
#elif PLATFORM(HAIKU)
class BRect;
+#elif PLATFORM(EFL)
+typedef struct _Eina_Rectangle Eina_Rectangle;
#endif
#if PLATFORM(WX)
@@ -158,6 +160,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/Path.cpp b/WebCore/platform/graphics/Path.cpp
index 4e2de53..55760b1 100644
--- a/WebCore/platform/graphics/Path.cpp
+++ b/WebCore/platform/graphics/Path.cpp
@@ -35,8 +35,9 @@
#include <math.h>
#include <wtf/MathExtras.h>
-static const float QUARTER = 0.552f; // approximation of control point positions on a bezier
- // to simulate a quarter of a circle.
+// Approximation of control point positions on a bezier to simulate a quarter of a circle.
+static const float gCircleControlPoint = 0.448f;
+
namespace WebCore {
#if !PLATFORM(OPENVG) && !PLATFORM(QT)
@@ -47,7 +48,7 @@ static void pathLengthApplierFunction(void* info, const PathElement* element)
return;
traversalState.m_previous = traversalState.m_current;
FloatPoint* points = element->points;
- float segmentLength = 0.0f;
+ float segmentLength = 0;
switch (element->type) {
case PathElementMoveToPoint:
segmentLength = traversalState.moveTo(points[0]);
@@ -75,10 +76,8 @@ static void pathLengthApplierFunction(void* info, const PathElement* element)
if (traversalState.m_action == PathTraversalState::TraversalPointAtLength) {
float offset = traversalState.m_desiredLength - traversalState.m_totalLength;
traversalState.m_current.move(offset * cosf(slope), offset * sinf(slope));
- } else {
- static const float rad2deg = 180.0f / piFloat;
- traversalState.m_normalAngle = slope * rad2deg;
- }
+ } else
+ traversalState.m_normalAngle = rad2deg(slope);
traversalState.m_success = true;
}
@@ -110,167 +109,83 @@ float Path::normalAngleAtLength(float length, bool& ok)
}
#endif
-Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& roundingRadii)
+void Path::addRoundedRect(const FloatRect& rect, const FloatSize& roundingRadii)
{
- Path path;
- float x = rectangle.x();
- float y = rectangle.y();
- float width = rectangle.width();
- float height = rectangle.height();
- float rx = roundingRadii.width();
- float ry = roundingRadii.height();
- if (width <= 0.0f || height <= 0.0f)
- return path;
+ if (rect.isEmpty())
+ return;
+
+ FloatSize radius(roundingRadii);
+ FloatSize halfSize(rect.width() / 2, rect.height() / 2);
- float dx = rx, dy = ry;
// If rx is greater than half of the width of the rectangle
// then set rx to half of the width (required in SVG spec)
- if (dx > width * 0.5f)
- dx = width * 0.5f;
+ if (radius.width() > halfSize.width())
+ radius.setWidth(halfSize.width());
// If ry is greater than half of the height of the rectangle
// then set ry to half of the height (required in SVG spec)
- if (dy > height * 0.5f)
- dy = height * 0.5f;
+ if (radius.height() > halfSize.height())
+ radius.setHeight(halfSize.height());
- path.moveTo(FloatPoint(x + dx, y));
+ moveTo(FloatPoint(rect.x() + radius.width(), rect.y()));
- if (dx < width * 0.5f)
- path.addLineTo(FloatPoint(x + width - rx, y));
+ if (radius.width() < halfSize.width())
+ addLineTo(FloatPoint(rect.x() + rect.width() - roundingRadii.width(), rect.y()));
- path.addBezierCurveTo(FloatPoint(x + width - dx * (1 - QUARTER), y), FloatPoint(x + width, y + dy * (1 - QUARTER)), FloatPoint(x + width, y + dy));
+ addBezierCurveTo(FloatPoint(rect.x() + rect.width() - radius.width() * gCircleControlPoint, rect.y()), FloatPoint(rect.x() + rect.width(), rect.y() + radius.height() * gCircleControlPoint), FloatPoint(rect.x() + rect.width(), rect.y() + radius.height()));
- if (dy < height * 0.5)
- path.addLineTo(FloatPoint(x + width, y + height - dy));
+ if (radius.height() < halfSize.height())
+ addLineTo(FloatPoint(rect.x() + rect.width(), rect.y() + rect.height() - radius.height()));
- path.addBezierCurveTo(FloatPoint(x + width, y + height - dy * (1 - QUARTER)), FloatPoint(x + width - dx * (1 - QUARTER), y + height), FloatPoint(x + width - dx, y + height));
+ addBezierCurveTo(FloatPoint(rect.x() + rect.width(), rect.y() + rect.height() - radius.height() * gCircleControlPoint), FloatPoint(rect.x() + rect.width() - radius.width() * gCircleControlPoint, rect.y() + rect.height()), FloatPoint(rect.x() + rect.width() - radius.width(), rect.y() + rect.height()));
- if (dx < width * 0.5)
- path.addLineTo(FloatPoint(x + dx, y + height));
+ if (radius.width() < halfSize.width())
+ addLineTo(FloatPoint(rect.x() + radius.width(), rect.y() + rect.height()));
- path.addBezierCurveTo(FloatPoint(x + dx * (1 - QUARTER), y + height), FloatPoint(x, y + height - dy * (1 - QUARTER)), FloatPoint(x, y + height - dy));
+ addBezierCurveTo(FloatPoint(rect.x() + radius.width() * gCircleControlPoint, rect.y() + rect.height()), FloatPoint(rect.x(), rect.y() + rect.height() - radius.height() * gCircleControlPoint), FloatPoint(rect.x(), rect.y() + rect.height() - radius.height()));
- if (dy < height * 0.5)
- path.addLineTo(FloatPoint(x, y + dy));
+ if (radius.height() < halfSize.height())
+ addLineTo(FloatPoint(rect.x(), rect.y() + radius.height()));
- path.addBezierCurveTo(FloatPoint(x, y + dy * (1 - QUARTER)), FloatPoint(x + dx * (1 - QUARTER), y), FloatPoint(x + dx, y));
+ addBezierCurveTo(FloatPoint(rect.x(), rect.y() + radius.height() * gCircleControlPoint), FloatPoint(rect.x() + radius.width() * gCircleControlPoint, rect.y()), FloatPoint(rect.x() + radius.width(), rect.y()));
- path.closeSubpath();
-
- return path;
+ closeSubpath();
}
-Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
+void Path::addRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
{
- Path path;
-
- float width = rectangle.width();
- float height = rectangle.height();
- if (width <= 0.0 || height <= 0.0)
- return path;
+ if (rect.isEmpty())
+ return;
- if (width < topLeftRadius.width() + topRightRadius.width()
- || width < bottomLeftRadius.width() + bottomRightRadius.width()
- || height < topLeftRadius.height() + bottomLeftRadius.height()
- || height < topRightRadius.height() + bottomRightRadius.height())
+ if (rect.width() < topLeftRadius.width() + topRightRadius.width()
+ || rect.width() < bottomLeftRadius.width() + bottomRightRadius.width()
+ || rect.height() < topLeftRadius.height() + bottomLeftRadius.height()
+ || rect.height() < topRightRadius.height() + bottomRightRadius.height()) {
// If all the radii cannot be accommodated, return a rect.
- return createRectangle(rectangle);
-
- float x = rectangle.x();
- float y = rectangle.y();
-
- path.moveTo(FloatPoint(x + topLeftRadius.width(), y));
-
- path.addLineTo(FloatPoint(x + width - topRightRadius.width(), y));
-
- path.addBezierCurveTo(FloatPoint(x + width - topRightRadius.width() * (1 - QUARTER), y), FloatPoint(x + width, y + topRightRadius.height() * (1 - QUARTER)), FloatPoint(x + width, y + topRightRadius.height()));
-
- path.addLineTo(FloatPoint(x + width, y + height - bottomRightRadius.height()));
-
- path.addBezierCurveTo(FloatPoint(x + width, y + height - bottomRightRadius.height() * (1 - QUARTER)), FloatPoint(x + width - bottomRightRadius.width() * (1 - QUARTER), y + height), FloatPoint(x + width - bottomRightRadius.width(), y + height));
-
- path.addLineTo(FloatPoint(x + bottomLeftRadius.width(), y + height));
-
- path.addBezierCurveTo(FloatPoint(x + bottomLeftRadius.width() * (1 - QUARTER), y + height), FloatPoint(x, y + height - bottomLeftRadius.height() * (1 - QUARTER)), FloatPoint(x, y + height - bottomLeftRadius.height()));
-
- path.addLineTo(FloatPoint(x, y + topLeftRadius.height()));
-
- path.addBezierCurveTo(FloatPoint(x, y + topLeftRadius.height() * (1 - QUARTER)), FloatPoint(x + topLeftRadius.width() * (1 - QUARTER), y), FloatPoint(x + topLeftRadius.width(), y));
-
- path.closeSubpath();
-
- return path;
-}
-
-Path Path::createRectangle(const FloatRect& rectangle)
-{
- Path path;
- float x = rectangle.x();
- float y = rectangle.y();
- float width = rectangle.width();
- float height = rectangle.height();
- if (width <= 0.0f || height <= 0.0f)
- return path;
-
- path.moveTo(FloatPoint(x, y));
- path.addLineTo(FloatPoint(x + width, y));
- path.addLineTo(FloatPoint(x + width, y + height));
- path.addLineTo(FloatPoint(x, y + height));
- path.closeSubpath();
-
- return path;
-}
-
-Path Path::createEllipse(const FloatPoint& center, float rx, float ry)
-{
- float cx = center.x();
- float cy = center.y();
- Path path;
- if (rx <= 0.0f || ry <= 0.0f)
- return path;
-
- float x = cx;
- float y = cy;
-
- unsigned step = 0, num = 100;
- bool running = true;
- while (running)
- {
- if (step == num)
- {
- running = false;
- break;
- }
-
- float angle = static_cast<float>(step) / static_cast<float>(num) * 2.0f * piFloat;
- x = cx + cosf(angle) * rx;
- y = cy + sinf(angle) * ry;
-
- step++;
- if (step == 1)
- path.moveTo(FloatPoint(x, y));
- else
- path.addLineTo(FloatPoint(x, y));
+ addRect(rect);
+ return;
}
- path.closeSubpath();
-
- return path;
-}
-
-Path Path::createCircle(const FloatPoint& center, float r)
-{
- return createEllipse(center, r, r);
-}
-
-Path Path::createLine(const FloatPoint& start, const FloatPoint& end)
-{
- Path path;
-
- path.moveTo(start);
- path.addLineTo(end);
-
- return path;
+ moveTo(FloatPoint(rect.x() + topLeftRadius.width(), rect.y()));
+
+ addLineTo(FloatPoint(rect.x() + rect.width() - topRightRadius.width(), rect.y()));
+ addBezierCurveTo(FloatPoint(rect.x() + rect.width() - topRightRadius.width() * gCircleControlPoint, rect.y()),
+ FloatPoint(rect.x() + rect.width(), rect.y() + topRightRadius.height() * gCircleControlPoint),
+ FloatPoint(rect.x() + rect.width(), rect.y() + topRightRadius.height()));
+ addLineTo(FloatPoint(rect.x() + rect.width(), rect.y() + rect.height() - bottomRightRadius.height()));
+ addBezierCurveTo(FloatPoint(rect.x() + rect.width(), rect.y() + rect.height() - bottomRightRadius.height() * gCircleControlPoint),
+ FloatPoint(rect.x() + rect.width() - bottomRightRadius.width() * gCircleControlPoint, rect.y() + rect.height()),
+ FloatPoint(rect.x() + rect.width() - bottomRightRadius.width(), rect.y() + rect.height()));
+ addLineTo(FloatPoint(rect.x() + bottomLeftRadius.width(), rect.y() + rect.height()));
+ addBezierCurveTo(FloatPoint(rect.x() + bottomLeftRadius.width() * gCircleControlPoint, rect.y() + rect.height()),
+ FloatPoint(rect.x(), rect.y() + rect.height() - bottomLeftRadius.height() * gCircleControlPoint),
+ FloatPoint(rect.x(), rect.y() + rect.height() - bottomLeftRadius.height()));
+ addLineTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height()));
+ addBezierCurveTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height() * gCircleControlPoint),
+ FloatPoint(rect.x() + topLeftRadius.width() * gCircleControlPoint, rect.y()),
+ FloatPoint(rect.x() + topLeftRadius.width(), rect.y()));
+
+ closeSubpath();
}
}
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
index 43ba889..86ba831 100644
--- a/WebCore/platform/graphics/Path.h
+++ b/WebCore/platform/graphics/Path.h
@@ -137,20 +137,13 @@ namespace WebCore {
void addArc(const FloatPoint&, float radius, float startAngle, float endAngle, bool anticlockwise);
void addRect(const FloatRect&);
void addEllipse(const FloatRect&);
+ void addRoundedRect(const FloatRect&, const FloatSize& roundingRadii);
+ void addRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
void translate(const FloatSize&);
- String debugString() const;
-
PlatformPathPtr platformPath() const { return m_path; }
- static Path createRoundedRectangle(const FloatRect&, const FloatSize& roundingRadii);
- static Path createRoundedRectangle(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
- static Path createRectangle(const FloatRect&);
- static Path createEllipse(const FloatPoint& center, float rx, float ry);
- static Path createCircle(const FloatPoint& center, float r);
- static Path createLine(const FloatPoint&, const FloatPoint&);
-
void apply(void* info, PathApplierFunction) const;
void transform(const AffineTransform&);
diff --git a/WebCore/platform/graphics/brew/ImageBrew.cpp b/WebCore/platform/graphics/brew/ImageBrew.cpp
index f5c855d..b574b0a 100644
--- a/WebCore/platform/graphics/brew/ImageBrew.cpp
+++ b/WebCore/platform/graphics/brew/ImageBrew.cpp
@@ -36,13 +36,13 @@
#include "SharedBuffer.h"
#include <wtf/text/CString.h>
-#include <wtf/text/WTFString.h>
+#include <wtf/text/StringConcatenate.h>
namespace WebCore {
PassRefPtr<Image> Image::loadPlatformResource(const char *name)
{
- String resourcePath = homeDirectoryPath() + String::format("res/%s.png", name);
+ String resourcePath = makeString(homeDirectoryPath(), "res/", name, ".png");
RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(resourcePath.utf8().data());
if (!buffer)
diff --git a/WebCore/platform/graphics/cairo/CairoUtilities.cpp b/WebCore/platform/graphics/cairo/CairoUtilities.cpp
index 8c2049f..7af5577 100644
--- a/WebCore/platform/graphics/cairo/CairoUtilities.cpp
+++ b/WebCore/platform/graphics/cairo/CairoUtilities.cpp
@@ -26,8 +26,15 @@
#include "config.h"
#include "CairoUtilities.h"
+#include "AffineTransform.h"
+#include "CairoPath.h"
#include "Color.h"
-#include <cairo.h>
+#include "FloatPoint.h"
+#include "FloatRect.h"
+#include "IntRect.h"
+#include "OwnPtrCairo.h"
+#include "Path.h"
+#include "PlatformRefPtrCairo.h"
#include <wtf/Vector.h>
namespace WebCore {
@@ -56,4 +63,96 @@ void setSourceRGBAFromColor(cairo_t* context, const Color& color)
cairo_set_source_rgba(context, red, green, blue, alpha);
}
+void appendPathToCairoContext(cairo_t* to, cairo_t* from)
+{
+ OwnPtr<cairo_path_t> cairoPath(cairo_copy_path(from));
+ cairo_append_path(to, cairoPath.get());
+}
+
+void setPathOnCairoContext(cairo_t* to, cairo_t* from)
+{
+ cairo_new_path(to);
+ appendPathToCairoContext(to, from);
+}
+
+void appendWebCorePathToCairoContext(cairo_t* context, const Path& path)
+{
+ appendPathToCairoContext(context, path.platformPath()->context());
+}
+
+cairo_operator_t toCairoOperator(CompositeOperator op)
+{
+ switch (op) {
+ case CompositeClear:
+ return CAIRO_OPERATOR_CLEAR;
+ case CompositeCopy:
+ return CAIRO_OPERATOR_SOURCE;
+ case CompositeSourceOver:
+ return CAIRO_OPERATOR_OVER;
+ case CompositeSourceIn:
+ return CAIRO_OPERATOR_IN;
+ case CompositeSourceOut:
+ return CAIRO_OPERATOR_OUT;
+ case CompositeSourceAtop:
+ return CAIRO_OPERATOR_ATOP;
+ case CompositeDestinationOver:
+ return CAIRO_OPERATOR_DEST_OVER;
+ case CompositeDestinationIn:
+ return CAIRO_OPERATOR_DEST_IN;
+ case CompositeDestinationOut:
+ return CAIRO_OPERATOR_DEST_OUT;
+ case CompositeDestinationAtop:
+ return CAIRO_OPERATOR_DEST_ATOP;
+ case CompositeXOR:
+ return CAIRO_OPERATOR_XOR;
+ case CompositePlusDarker:
+ return CAIRO_OPERATOR_SATURATE;
+ case CompositeHighlight:
+ // There is no Cairo equivalent for CompositeHighlight.
+ return CAIRO_OPERATOR_OVER;
+ case CompositePlusLighter:
+ return CAIRO_OPERATOR_ADD;
+ default:
+ return CAIRO_OPERATOR_SOURCE;
+ }
+}
+
+void drawPatternToCairoContext(cairo_t* cr, cairo_surface_t* image, const IntSize& imageSize, const FloatRect& tileRect,
+ const AffineTransform& patternTransform, const FloatPoint& phase, cairo_operator_t op, const FloatRect& destRect)
+{
+ // Avoid NaN
+ if (!isfinite(phase.x()) || !isfinite(phase.y()))
+ return;
+
+ cairo_save(cr);
+
+ PlatformRefPtr<cairo_surface_t> clippedImageSurface = 0;
+ if (tileRect.size() != imageSize) {
+ IntRect imageRect = enclosingIntRect(tileRect);
+ clippedImageSurface = adoptPlatformRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, imageRect.width(), imageRect.height()));
+ PlatformRefPtr<cairo_t> clippedImageContext(cairo_create(clippedImageSurface.get()));
+ cairo_set_source_surface(clippedImageContext.get(), image, -tileRect.x(), -tileRect.y());
+ cairo_paint(clippedImageContext.get());
+ image = clippedImageSurface.get();
+ }
+
+ cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+
+ cairo_matrix_t patternMatrix = cairo_matrix_t(patternTransform);
+ cairo_matrix_t phaseMatrix = {1, 0, 0, 1, phase.x() + tileRect.x() * patternTransform.a(), phase.y() + tileRect.y() * patternTransform.d()};
+ cairo_matrix_t combined;
+ cairo_matrix_multiply(&combined, &patternMatrix, &phaseMatrix);
+ cairo_matrix_invert(&combined);
+ cairo_pattern_set_matrix(pattern, &combined);
+
+ cairo_set_operator(cr, op);
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
+ cairo_rectangle(cr, destRect.x(), destRect.y(), destRect.width(), destRect.height());
+ cairo_fill(cr);
+
+ cairo_restore(cr);
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/graphics/cairo/CairoUtilities.h b/WebCore/platform/graphics/cairo/CairoUtilities.h
index 0675b90..d8fff8d 100644
--- a/WebCore/platform/graphics/cairo/CairoUtilities.h
+++ b/WebCore/platform/graphics/cairo/CairoUtilities.h
@@ -26,13 +26,25 @@
#ifndef CairoUtilities_h
#define CairoUtilities_h
-typedef struct _cairo cairo_t;
+#include <GraphicsTypes.h>
+#include <cairo.h>
namespace WebCore {
+class AffineTransform;
class Color;
+class FloatRect;
+class FloatPoint;
+class IntSize;
+class Path;
void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr);
void setSourceRGBAFromColor(cairo_t*, const Color&);
+void appendPathToCairoContext(cairo_t* to, cairo_t* from);
+void setPathOnCairoContext(cairo_t* to, cairo_t* from);
+void appendWebCorePathToCairoContext(cairo_t* context, const Path& path);
+cairo_operator_t toCairoOperator(CompositeOperator op);
+void drawPatternToCairoContext(cairo_t* cr, cairo_surface_t* image, const IntSize& imageSize, const FloatRect& tileRect,
+ const AffineTransform& patternTransform, const FloatPoint& phase, cairo_operator_t op, const FloatRect& destRect);
} // namespace WebCore
diff --git a/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp b/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
index 4b94cb3..8299b6a 100644
--- a/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
@@ -29,10 +29,15 @@
#include "config.h"
#include "ContextShadow.h"
+#include "AffineTransform.h"
#include "CairoUtilities.h"
+#include "OwnPtrCairo.h"
+#include "Path.h"
#include "Timer.h"
#include <cairo.h>
+using WTF::max;
+
namespace WebCore {
static cairo_surface_t* scratchBuffer = 0;
@@ -105,10 +110,13 @@ void ContextShadow::endShadowLayer(cairo_t* cr)
cairo_destroy(m_layerContext);
m_layerContext = 0;
- if (m_type == BlurShadow)
+ if (m_type == BlurShadow) {
+ cairo_surface_flush(m_layerImage);
blurLayerImage(cairo_image_surface_get_data(m_layerImage),
IntSize(cairo_image_surface_get_width(m_layerImage), cairo_image_surface_get_height(m_layerImage)),
cairo_image_surface_get_stride(m_layerImage));
+ cairo_surface_mark_dirty(m_layerImage);
+ }
cairo_save(cr);
setSourceRGBAFromColor(cr, m_color);
@@ -119,4 +127,223 @@ void ContextShadow::endShadowLayer(cairo_t* cr)
scheduleScratchBufferPurge();
}
+void ContextShadow::drawRectShadowWithoutTiling(PlatformContext context, const IntRect& shadowRect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius, float alpha)
+{
+ beginShadowLayer(context, shadowRect);
+
+ if (!m_layerContext)
+ return;
+
+ Path path;
+ path.addRoundedRect(shadowRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+
+ appendWebCorePathToCairoContext(m_layerContext, path);
+ cairo_set_source_rgba(m_layerContext, 0, 0, 0, alpha);
+ cairo_fill(m_layerContext);
+
+ endShadowLayer(context);
+}
+
+static inline FloatPoint getPhase(const FloatRect& dest, const FloatRect& tile)
+{
+ FloatPoint phase = dest.location();
+ phase.move(-tile.x(), -tile.y());
+
+ return phase;
+}
+
+/*
+ This function uses tiling to improve the performance of the shadow
+ drawing of rounded rectangles. The code basically does the following
+ steps:
+
+ 1. Calculate the size of the shadow template, a rectangle that
+ contains all the necessary tiles to draw the complete shadow.
+
+ 2. If that size is smaller than the real rectangle render the new
+ template rectangle and its shadow in a new surface, in other case
+ render the shadow of the real rectangle in the destination
+ surface.
+
+ 3. Calculate the sizes and positions of the tiles and their
+ destinations and use drawPattern to render the final shadow. The
+ code divides the rendering in 8 tiles:
+
+ 1 | 2 | 3
+ -----------
+ 4 | | 5
+ -----------
+ 6 | 7 | 8
+
+ The corners are directly copied from the template rectangle to the
+ real one and the side tiles are 1 pixel width, we use them as
+
+ tiles to cover the destination side. The corner tiles are bigger
+ than just the side of the rounded corner, we need to increase it
+ because the modifications caused by the corner over the blur
+ effect. We fill the central part with solid color to complete the
+ shadow.
+ */
+void ContextShadow::drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius)
+{
+
+ // drawShadowedRect still does not work with rotations.
+ // https://bugs.webkit.org/show_bug.cgi?id=45042
+ float radiusTwice = m_blurDistance * 2;
+ cairo_t* cr = context->platformContext();
+ if ((!context->getCTM().isIdentityOrTranslationOrFlipped()) || (radiusTwice > rect.width())
+ || (radiusTwice > rect.height()) || (m_type != BlurShadow)) {
+ drawRectShadowWithoutTiling(cr, rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, context->getAlpha());
+ return;
+ }
+
+ // Calculate size of the template shadow buffer.
+ IntSize shadowBufferSize = IntSize(rect.width() + radiusTwice, rect.height() + radiusTwice);
+
+ // Determine dimensions of shadow rect.
+ FloatRect shadowRect = FloatRect(rect.location(), shadowBufferSize);
+ shadowRect.move(- m_blurDistance, - m_blurDistance);
+
+ // Size of the tiling side.
+ int sideTileWidth = 1;
+
+ // Find the extra space needed from the curve of the corners.
+ int extraWidthFromCornerRadii = radiusTwice + max(topLeftRadius.width(), bottomLeftRadius.width()) +
+ radiusTwice + max(topRightRadius.width(), bottomRightRadius.width());
+ int extraHeightFromCornerRadii = radiusTwice + max(topLeftRadius.height(), topRightRadius.height()) +
+ radiusTwice + max(bottomLeftRadius.height(), bottomRightRadius.height());
+
+ // The length of a side of the buffer is the enough space for four blur radii,
+ // the radii of the corners, and then 1 pixel to draw the side tiles.
+ IntSize shadowTemplateSize = IntSize(sideTileWidth + extraWidthFromCornerRadii,
+ sideTileWidth + extraHeightFromCornerRadii);
+
+ // Reduce the size of what we have to draw with the clip area.
+ double x1, x2, y1, y2;
+ cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
+ calculateLayerBoundingRect(shadowRect, IntRect(x1, y1, x2 - x1, y2 - y1));
+
+ if ((shadowTemplateSize.width() * shadowTemplateSize.height() > m_layerRect.width() * m_layerRect.height())) {
+ drawRectShadowWithoutTiling(cr, rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, context->getAlpha());
+ return;
+ }
+
+ shadowRect.move(m_offset.width(), m_offset.height());
+
+ m_layerImage = getScratchBuffer(shadowTemplateSize);
+
+ // Draw shadow into a new ImageBuffer.
+ m_layerContext = cairo_create(m_layerImage);
+
+ // Clear the surface first.
+ cairo_set_operator(m_layerContext, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(m_layerContext);
+ cairo_set_operator(m_layerContext, CAIRO_OPERATOR_OVER);
+
+ // Draw the rectangle.
+ IntRect templateRect = IntRect(m_blurDistance, m_blurDistance, shadowTemplateSize.width() - radiusTwice, shadowTemplateSize.height() - radiusTwice);
+ Path path;
+ path.addRoundedRect(templateRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+ appendWebCorePathToCairoContext(m_layerContext, path);
+
+ cairo_set_source_rgba(m_layerContext, 0, 0, 0, context->getAlpha());
+ cairo_fill(m_layerContext);
+
+ // Blur the image.
+ cairo_surface_flush(m_layerImage);
+ blurLayerImage(cairo_image_surface_get_data(m_layerImage), shadowTemplateSize, cairo_image_surface_get_stride(m_layerImage));
+ cairo_surface_mark_dirty(m_layerImage);
+
+ // Mask the image with the shadow color.
+ cairo_set_operator(m_layerContext, CAIRO_OPERATOR_IN);
+ setSourceRGBAFromColor(m_layerContext, m_color);
+ cairo_paint(m_layerContext);
+
+ cairo_destroy(m_layerContext);
+ m_layerContext = 0;
+
+ // Fill the internal part of the shadow.
+ shadowRect.inflate(-radiusTwice);
+ if (!shadowRect.isEmpty()) {
+ cairo_save(cr);
+ path.clear();
+ path.addRoundedRect(shadowRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+ appendWebCorePathToCairoContext(cr, path);
+ setSourceRGBAFromColor(cr, m_color);
+ cairo_fill(cr);
+ cairo_restore(cr);
+ }
+ shadowRect.inflate(radiusTwice);
+
+ // Draw top side.
+ FloatRect tileRect = FloatRect(radiusTwice + topLeftRadius.width(), 0, sideTileWidth, radiusTwice);
+ FloatRect destRect = tileRect;
+ destRect.move(shadowRect.x(), shadowRect.y());
+ destRect.setWidth(shadowRect.width() - topLeftRadius.width() - topRightRadius.width() - m_blurDistance * 4);
+ FloatPoint phase = getPhase(destRect, tileRect);
+ AffineTransform patternTransform;
+ patternTransform.makeIdentity();
+ drawPatternToCairoContext(cr, m_layerImage, shadowTemplateSize, tileRect, patternTransform, phase, CAIRO_OPERATOR_OVER, destRect);
+
+ // Draw the bottom side.
+ tileRect = FloatRect(radiusTwice + bottomLeftRadius.width(), shadowTemplateSize.height() - radiusTwice, sideTileWidth, radiusTwice);
+ destRect = tileRect;
+ destRect.move(shadowRect.x(), shadowRect.y() + radiusTwice + rect.height() - shadowTemplateSize.height());
+ destRect.setWidth(shadowRect.width() - bottomLeftRadius.width() - bottomRightRadius.width() - m_blurDistance * 4);
+ phase = getPhase(destRect, tileRect);
+ drawPatternToCairoContext(cr, m_layerImage, shadowTemplateSize, tileRect, patternTransform, phase, CAIRO_OPERATOR_OVER, destRect);
+
+ // Draw the right side.
+ tileRect = FloatRect(shadowTemplateSize.width() - radiusTwice, radiusTwice + topRightRadius.height(), radiusTwice, sideTileWidth);
+ destRect = tileRect;
+ destRect.move(shadowRect.x() + radiusTwice + rect.width() - shadowTemplateSize.width(), shadowRect.y());
+ destRect.setHeight(shadowRect.height() - topRightRadius.height() - bottomRightRadius.height() - m_blurDistance * 4);
+ phase = getPhase(destRect, tileRect);
+ drawPatternToCairoContext(cr, m_layerImage, shadowTemplateSize, tileRect, patternTransform, phase, CAIRO_OPERATOR_OVER, destRect);
+
+ // Draw the left side.
+ tileRect = FloatRect(0, radiusTwice + topLeftRadius.height(), radiusTwice, sideTileWidth);
+ destRect = tileRect;
+ destRect.move(shadowRect.x(), shadowRect.y());
+ destRect.setHeight(shadowRect.height() - topLeftRadius.height() - bottomLeftRadius.height() - m_blurDistance * 4);
+ phase = FloatPoint(destRect.x() - tileRect.x(), destRect.y() - tileRect.y());
+ drawPatternToCairoContext(cr, m_layerImage, shadowTemplateSize, tileRect, patternTransform, phase, CAIRO_OPERATOR_OVER, destRect);
+
+ // Draw the top left corner.
+ tileRect = FloatRect(0, 0, radiusTwice + topLeftRadius.width(), radiusTwice + topLeftRadius.height());
+ destRect = tileRect;
+ destRect.move(shadowRect.x(), shadowRect.y());
+ phase = getPhase(destRect, tileRect);
+ drawPatternToCairoContext(cr, m_layerImage, shadowTemplateSize, tileRect, patternTransform, phase, CAIRO_OPERATOR_OVER, destRect);
+
+ // Draw the top right corner.
+ tileRect = FloatRect(shadowTemplateSize.width() - radiusTwice - topRightRadius.width(), 0, radiusTwice + topRightRadius.width(),
+ radiusTwice + topRightRadius.height());
+ destRect = tileRect;
+ destRect.move(shadowRect.x() + rect.width() - shadowTemplateSize.width() + radiusTwice, shadowRect.y());
+ phase = getPhase(destRect, tileRect);
+ drawPatternToCairoContext(cr, m_layerImage, shadowTemplateSize, tileRect, patternTransform, phase, CAIRO_OPERATOR_OVER, destRect);
+
+ // Draw the bottom right corner.
+ tileRect = FloatRect(shadowTemplateSize.width() - radiusTwice - bottomRightRadius.width(),
+ shadowTemplateSize.height() - radiusTwice - bottomRightRadius.height(),
+ radiusTwice + bottomRightRadius.width(), radiusTwice + bottomRightRadius.height());
+ destRect = tileRect;
+ destRect.move(shadowRect.x() + rect.width() - shadowTemplateSize.width() + radiusTwice,
+ shadowRect.y() + rect.height() - shadowTemplateSize.height() + radiusTwice);
+ phase = getPhase(destRect, tileRect);
+ drawPatternToCairoContext(cr, m_layerImage, shadowTemplateSize, tileRect, patternTransform, phase, CAIRO_OPERATOR_OVER, destRect);
+
+ // Draw the bottom left corner.
+ tileRect = FloatRect(0, shadowTemplateSize.height() - radiusTwice - bottomLeftRadius.height(),
+ radiusTwice + bottomLeftRadius.width(), radiusTwice + bottomLeftRadius.height());
+ destRect = tileRect;
+ destRect.move(shadowRect.x(), shadowRect.y() + rect.height() - shadowTemplateSize.height() + radiusTwice);
+ phase = getPhase(destRect, tileRect);
+ drawPatternToCairoContext(cr, m_layerImage, shadowTemplateSize, tileRect, patternTransform, phase, CAIRO_OPERATOR_OVER, destRect);
+
+ // Schedule a purge of the scratch buffer.
+ scheduleScratchBufferPurge();
+}
+
}
diff --git a/WebCore/platform/graphics/cairo/FloatRectCairo.cpp b/WebCore/platform/graphics/cairo/FloatRectCairo.cpp
new file mode 100644
index 0000000..9f86f74
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/FloatRectCairo.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FloatRect.h"
+
+#include <cairo.h>
+
+namespace WebCore {
+
+FloatRect::FloatRect(const cairo_rectangle_t& r)
+ : m_location(r.x, r.y)
+ , m_size(r.width, r.height)
+{
+}
+
+FloatRect::operator cairo_rectangle_t() const
+{
+ cairo_rectangle_t r = { x(), y(), width(), height() };
+ return r;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp
index febad12..5dca010 100644
--- a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp
+++ b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp
@@ -87,12 +87,12 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne
{
}
-static CString getFamilyNameStringFromFontDescriptionAndFamily(const FontDescription& fontDescription, const AtomicString& family)
+static String getFamilyNameStringFromFontDescriptionAndFamily(const FontDescription& fontDescription, const AtomicString& family)
{
// 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-"))
- return family.string().utf8();
+ return family.string();
switch (fontDescription.genericFamily()) {
case FontDescription::StandardFamily:
@@ -112,23 +112,14 @@ static CString getFamilyNameStringFromFontDescriptionAndFamily(const FontDescrip
}
}
-
-static bool isFallbackFontAllowed(const CString& familyName)
-{
- return !strcasecmp(familyName.data(), "sans")
- || !strcasecmp(familyName.data(), "sans-serif")
- || !strcasecmp(familyName.data(), "serif")
- || !strcasecmp(familyName.data(), "monospace");
-}
-
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
{
// The CSS font matching algorithm (http://www.w3.org/TR/css3-fonts/#font-matching-algorithm)
// says that we must find an exact match for font family, slant (italic or oblique can be used)
// and font weight (we only match bold/non-bold here).
PlatformRefPtr<FcPattern> pattern = adoptPlatformRef(FcPatternCreate());
- CString familyNameString = getFamilyNameStringFromFontDescriptionAndFamily(fontDescription, family);
- if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(familyNameString.data())))
+ String familyNameString(getFamilyNameStringFromFontDescriptionAndFamily(fontDescription, family));
+ if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(familyNameString.utf8().data())))
return 0;
bool italic = fontDescription.italic();
@@ -140,53 +131,39 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
if (!FcPatternAddDouble(pattern.get(), FC_PIXEL_SIZE, fontDescription.computedPixelSize()))
return 0;
- // The following comment and strategy are originally from Skia (src/ports/SkFontHost_fontconfig.cpp):
- // Font matching:
- // CSS often specifies a fallback list of families:
- // font-family: a, b, c, serif;
- // However, fontconfig will always do its best to find *a* font when asked
- // for something so we need a way to tell if the match which it has found is
- // "good enough" for us. Otherwise, we can return null which gets piped up
- // and lets WebKit know to try the next CSS family name. However, fontconfig
- // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
- // wish to support that.
- //
- // Thus, if a specific family is requested we set @family_requested. Then we
- // record two strings: the family name after config processing and the
- // family name after resolving. If the two are equal, it's a good match.
- //
- // So consider the case where a user has mapped Arial to Helvetica in their
- // config.
- // requested family: "Arial"
- // post_config_family: "Helvetica"
- // post_match_family: "Helvetica"
- // -> good match
- //
- // and for a missing font:
- // requested family: "Monaco"
- // post_config_family: "Monaco"
- // post_match_family: "Times New Roman"
- // -> BAD match
- //
+ // The strategy is originally from Skia (src/ports/SkFontHost_fontconfig.cpp):
+
+ // Allow Fontconfig to do pre-match substitution. Unless we are accessing a "fallback"
+ // family like "sans," this is the only time we allow Fontconfig to substitute one
+ // family name for another (i.e. if the fonts are aliased to each other).
FcConfigSubstitute(0, pattern.get(), FcMatchPattern);
FcDefaultSubstitute(pattern.get());
- FcChar8* familyNameAfterConfiguration;
- FcPatternGetString(pattern.get(), FC_FAMILY, 0, &familyNameAfterConfiguration);
+ FcChar8* fontConfigFamilyNameAfterConfiguration;
+ FcPatternGetString(pattern.get(), FC_FAMILY, 0, &fontConfigFamilyNameAfterConfiguration);
+ String familyNameAfterConfiguration = String::fromUTF8(reinterpret_cast<char*>(fontConfigFamilyNameAfterConfiguration));
FcResult fontConfigResult;
PlatformRefPtr<FcPattern> resultPattern = adoptPlatformRef(FcFontMatch(0, pattern.get(), &fontConfigResult));
if (!resultPattern) // No match.
return 0;
- // Properly handle the situation where Fontconfig gives us a font that has a different family than we requested.
- FcChar8* familyNameAfterMatching;
- FcPatternGetString(resultPattern.get(), FC_FAMILY, 0, &familyNameAfterMatching);
- if (strcasecmp(reinterpret_cast<char*>(familyNameAfterConfiguration),
- reinterpret_cast<char*>(familyNameAfterMatching)) && !isFallbackFontAllowed(familyNameString))
- return 0;
-
- return new FontPlatformData(resultPattern.get(), fontDescription);
+ FcChar8* fontConfigFamilyNameAfterMatching;
+ FcPatternGetString(resultPattern.get(), FC_FAMILY, 0, &fontConfigFamilyNameAfterMatching);
+ String familyNameAfterMatching = String::fromUTF8(reinterpret_cast<char*>(fontConfigFamilyNameAfterMatching));
+ if (equalIgnoringCase(familyNameAfterConfiguration, familyNameAfterMatching))
+ return new FontPlatformData(resultPattern.get(), fontDescription);
+
+ // If Fontconfig gave use a different font family than the one we requested, we should ignore it
+ // and allow WebCore to give us the next font on the CSS fallback list. The only exception is if
+ // this family name is a commonly used generic family.
+ if (equalIgnoringCase(familyNameString, "sans") || equalIgnoringCase(familyNameString, "sans-serif")
+ || equalIgnoringCase(familyNameString, "serif") || equalIgnoringCase(familyNameString, "monospace")
+ || equalIgnoringCase(familyNameString, "fantasy") || equalIgnoringCase(familyNameString, "cursive"))
+ return new FontPlatformData(resultPattern.get(), fontDescription);
+
+ // Fontconfig did not return a good match.
+ return 0;
}
}
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp
index cd5d362..3d55c70 100644
--- a/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -31,6 +31,8 @@
#include "Font.h"
#include "AffineTransform.h"
+#include "CairoUtilities.h"
+#include "ContextShadow.h"
#include "GlyphBuffer.h"
#include "Gradient.h"
#include "GraphicsContext.h"
@@ -38,18 +40,63 @@
#include "Pattern.h"
#include "SimpleFontData.h"
-#define SYNTHETIC_OBLIQUE_ANGLE 14
-
namespace WebCore {
-void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
- int from, int numGlyphs, const FloatPoint& point) const
+static void prepareContextForGlyphDrawing(cairo_t* context, const SimpleFontData* font, const FloatPoint& point)
{
- cairo_t* cr = context->platformContext();
- cairo_save(cr);
+ static const float syntheticObliqueSkew = -tanf(14 * acosf(0) / 90);
+ cairo_set_scaled_font(context, font->platformData().scaledFont());
+ if (font->platformData().syntheticOblique()) {
+ cairo_matrix_t mat = {1, 0, syntheticObliqueSkew, 1, point.x(), point.y()};
+ cairo_transform(context, &mat);
+ } else
+ cairo_translate(context, point.x(), point.y());
+}
- cairo_set_scaled_font(cr, font->platformData().scaledFont());
+static void drawGlyphsToContext(cairo_t* context, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
+{
+ cairo_show_glyphs(context, glyphs, numGlyphs);
+ if (font->syntheticBoldOffset()) {
+ // We could use cairo_save/cairo_restore here, but two translations are likely faster.
+ cairo_translate(context, font->syntheticBoldOffset(), 0);
+ cairo_show_glyphs(context, glyphs, numGlyphs);
+ cairo_translate(context, -font->syntheticBoldOffset(), 0);
+ }
+}
+
+static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
+{
+ ContextShadow* shadow = graphicsContext->contextShadow();
+ ASSERT(shadow);
+
+ if (!(graphicsContext->textDrawingMode() & cTextFill) || shadow->m_type == ContextShadow::NoShadow)
+ return;
+
+ if (shadow->m_type == ContextShadow::SolidShadow) {
+ // Optimize non-blurry shadows, by just drawing text without the ContextShadow.
+ cairo_save(context);
+ cairo_translate(context, shadow->m_offset.width(), shadow->m_offset.height());
+ setSourceRGBAFromColor(context, shadow->m_color);
+ prepareContextForGlyphDrawing(context, font, point);
+ cairo_show_glyphs(context, glyphs, numGlyphs);
+ cairo_restore(context);
+ return;
+ }
+
+ cairo_text_extents_t extents;
+ cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
+ FloatRect fontExtentsRect(point.x(), point.y() - extents.height, extents.width, extents.height);
+ cairo_t* shadowContext = shadow->beginShadowLayer(context, fontExtentsRect);
+ if (shadowContext) {
+ prepareContextForGlyphDrawing(shadowContext, font, point);
+ drawGlyphsToContext(shadowContext, font, glyphs, numGlyphs);
+ shadow->endShadowLayer(context);
+ }
+}
+void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
+ int from, int numGlyphs, const FloatPoint& point) const
+{
GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from);
float offset = 0.0f;
@@ -59,75 +106,11 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
offset += glyphBuffer.advanceAt(from + i);
}
- Color fillColor = context->fillColor();
-
- // Synthetic Oblique
- if(font->platformData().syntheticOblique()) {
- cairo_matrix_t mat = {1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, point.x(), point.y()};
- cairo_transform(cr, &mat);
- } else {
- cairo_translate(cr, point.x(), point.y());
- }
-
- // Text shadow, inspired by FontMac
- FloatSize shadowOffset;
- float shadowBlur = 0;
- Color shadowColor;
- bool hasShadow = context->textDrawingMode() & cTextFill
- && context->getShadow(shadowOffset, shadowBlur, shadowColor);
-
- // TODO: Blur support
- if (hasShadow) {
- // Disable graphics context shadows (not yet implemented) and paint them manually
- context->clearShadow();
- Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- cairo_save(cr);
-
- float red, green, blue, alpha;
- shadowFillColor.getRGBA(red, green, blue, alpha);
- cairo_set_source_rgba(cr, red, green, blue, alpha);
-
-#if ENABLE(FILTERS)
- cairo_text_extents_t extents;
- cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
-
- FloatRect rect(FloatPoint(), FloatSize(extents.width, extents.height));
- IntSize shadowBufferSize;
- FloatRect shadowRect;
- float radius = 0;
- context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur);
-
- // Draw shadow into a new ImageBuffer
- OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
- GraphicsContext* shadowContext = shadowBuffer->context();
- cairo_t* shadowCr = shadowContext->platformContext();
-
- cairo_translate(shadowCr, radius, extents.height + radius);
-
- cairo_set_scaled_font(shadowCr, font->platformData().scaledFont());
- cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
- if (font->syntheticBoldOffset()) {
- cairo_save(shadowCr);
- cairo_translate(shadowCr, font->syntheticBoldOffset(), 0);
- cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
- cairo_restore(shadowCr);
- }
- cairo_translate(cr, 0.0, -extents.height);
- context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
-#else
- cairo_translate(cr, shadowOffset.width(), shadowOffset.height());
- cairo_show_glyphs(cr, glyphs, numGlyphs);
- if (font->syntheticBoldOffset()) {
- cairo_save(cr);
- cairo_translate(cr, font->syntheticBoldOffset(), 0);
- cairo_show_glyphs(cr, glyphs, numGlyphs);
- cairo_restore(cr);
- }
-#endif
-
- cairo_restore(cr);
- }
+ cairo_t* cr = context->platformContext();
+ drawGlyphsShadow(context, cr, point, font, glyphs, numGlyphs);
+ cairo_save(cr);
+ prepareContextForGlyphDrawing(cr, font, point);
if (context->textDrawingMode() & cTextFill) {
if (context->fillGradient()) {
cairo_set_source(cr, context->fillGradient()->platformGradient());
@@ -148,16 +131,10 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_pattern_destroy(pattern);
} else {
float red, green, blue, alpha;
- fillColor.getRGBA(red, green, blue, alpha);
+ context->fillColor().getRGBA(red, green, blue, alpha);
cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha());
}
- cairo_show_glyphs(cr, glyphs, numGlyphs);
- if (font->syntheticBoldOffset()) {
- cairo_save(cr);
- cairo_translate(cr, font->syntheticBoldOffset(), 0);
- cairo_show_glyphs(cr, glyphs, numGlyphs);
- cairo_restore(cr);
- }
+ drawGlyphsToContext(cr, font, glyphs, numGlyphs);
}
// Prevent running into a long computation within cairo. If the stroke width is
@@ -183,20 +160,15 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
}
cairo_pattern_destroy(pattern);
} else {
- Color strokeColor = context->strokeColor();
float red, green, blue, alpha;
- strokeColor.getRGBA(red, green, blue, alpha);
+ context->strokeColor().getRGBA(red, green, blue, alpha);
cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha());
- }
+ }
cairo_glyph_path(cr, glyphs, numGlyphs);
cairo_set_line_width(cr, context->strokeThickness());
cairo_stroke(cr);
}
- // Re-enable the platform shadow we disabled earlier
- if (hasShadow)
- context->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace);
-
cairo_restore(cr);
}
diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp
index 0617e6c..ba307fa 100644
--- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp
+++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp
@@ -75,40 +75,65 @@ void setCairoFontOptionsFromFontConfigPattern(cairo_font_options_t* options, FcP
FcBool booleanResult;
int integerResult;
- // We will determine if subpixel anti-aliasing is enabled via the FC_RGBA setting.
- if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &booleanResult) == FcResultMatch && booleanResult)
- cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);
-
if (FcPatternGetInteger(pattern, FC_RGBA, 0, &integerResult) == FcResultMatch) {
+ cairo_font_options_set_subpixel_order(options, convertFontConfigSubpixelOrder(integerResult));
+
+ // Based on the logic in cairo-ft-font.c in the cairo source, a font with
+ // a subpixel order implies that is uses subpixel antialiasing.
if (integerResult != FC_RGBA_NONE)
cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
- cairo_font_options_set_subpixel_order(options, convertFontConfigSubpixelOrder(integerResult));
+ }
+
+ if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &booleanResult) == FcResultMatch) {
+ // Only override the anti-aliasing setting if was previously turned off. Otherwise
+ // we'll override the preference which decides between gray anti-aliasing and
+ // subpixel anti-aliasing.
+ if (!booleanResult)
+ cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_NONE);
+ else if (cairo_font_options_get_antialias(options) == CAIRO_ANTIALIAS_NONE)
+ cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);
}
if (FcPatternGetInteger(pattern, FC_HINT_STYLE, 0, &integerResult) == FcResultMatch)
cairo_font_options_set_hint_style(options, convertFontConfigHintStyle(integerResult));
-
if (FcPatternGetBool(pattern, FC_HINTING, 0, &booleanResult) == FcResultMatch && !booleanResult)
cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
}
+static const cairo_font_options_t* getDefaultFontOptions()
+{
+ static const cairo_font_options_t* options = cairo_font_options_create();
+#if PLATFORM(GTK) || ENABLE(GLIB_SUPPORT)
+ if (GdkScreen* screen = gdk_screen_get_default()) {
+ const cairo_font_options_t* screenOptions = gdk_screen_get_font_options(screen);
+ if (screenOptions)
+ options = screenOptions;
+ }
+#endif
+ return options;
+}
+
FontPlatformData::FontPlatformData(FcPattern* pattern, const FontDescription& fontDescription)
: m_pattern(pattern)
, m_fallbacks(0)
, m_size(fontDescription.computedPixelSize())
, m_syntheticBold(false)
, m_syntheticOblique(false)
+ , m_fixedWidth(false)
{
- cairo_font_options_t* options = cairo_font_options_create();
- setCairoFontOptionsFromFontConfigPattern(options, pattern);
+ PlatformRefPtr<cairo_font_face_t> fontFace = adoptPlatformRef(cairo_ft_font_face_create_for_pattern(m_pattern.get()));
+ initializeWithFontFace(fontFace.get());
- cairo_matrix_t fontMatrix;
- cairo_matrix_init_scale(&fontMatrix, m_size, m_size);
- cairo_matrix_t ctm;
- cairo_matrix_init_identity(&ctm);
+ int spacing;
+ if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing) == FcResultMatch && spacing == FC_MONO)
+ m_fixedWidth = true;
- PlatformRefPtr<cairo_font_face_t> fontFace = adoptPlatformRef(cairo_ft_font_face_create_for_pattern(m_pattern.get()));
- m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace.get(), &fontMatrix, &ctm, options));
+ if (fontDescription.weight() >= FontWeightBold) {
+ // The FC_EMBOLDEN property instructs us to fake the boldness of the font.
+ FcBool fontConfigEmbolden;
+ if (FcPatternGetBool(pattern, FC_EMBOLDEN, 0, &fontConfigEmbolden) == FcResultMatch)
+ m_syntheticBold = fontConfigEmbolden;
+ }
}
FontPlatformData::FontPlatformData(float size, bool bold, bool italic)
@@ -116,7 +141,9 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool italic)
, m_size(size)
, m_syntheticBold(bold)
, m_syntheticOblique(italic)
+ , m_fixedWidth(false)
{
+ // We cannot create a scaled font here.
}
FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic)
@@ -125,24 +152,13 @@ FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool
, m_syntheticBold(bold)
, m_syntheticOblique(italic)
{
- cairo_matrix_t fontMatrix;
- cairo_matrix_init_scale(&fontMatrix, size, size);
- cairo_matrix_t ctm;
- cairo_matrix_init_identity(&ctm);
- static const cairo_font_options_t* defaultOptions = cairo_font_options_create();
- const cairo_font_options_t* options = NULL;
-
-#if !PLATFORM(EFL) || ENABLE(GLIB_SUPPORT)
- if (GdkScreen* screen = gdk_screen_get_default())
- options = gdk_screen_get_font_options(screen);
-#endif
-
- // gdk_screen_get_font_options() returns NULL if no default options are
- // set, so we always have to check.
- if (!options)
- options = defaultOptions;
+ initializeWithFontFace(fontFace);
- m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options));
+ FT_Face fontConfigFace = cairo_ft_scaled_font_lock_face(m_scaledFont.get());
+ if (fontConfigFace) {
+ m_fixedWidth = fontConfigFace->face_flags & FT_FACE_FLAG_FIXED_WIDTH;
+ cairo_ft_scaled_font_unlock_face(m_scaledFont.get());
+ }
}
FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
@@ -154,6 +170,7 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
m_size = other.m_size;
m_syntheticBold = other.m_syntheticBold;
m_syntheticOblique = other.m_syntheticOblique;
+ m_fixedWidth = other.m_fixedWidth;
m_scaledFont = other.m_scaledFont;
m_pattern = other.m_pattern;
@@ -172,6 +189,16 @@ FontPlatformData::FontPlatformData(const FontPlatformData& other)
*this = other;
}
+FontPlatformData::FontPlatformData(const FontPlatformData& other, float size)
+{
+ *this = other;
+
+ // We need to reinitialize the instance, because the difference in size
+ // necessitates a new scaled font instance.
+ m_size = size;
+ initializeWithFontFace(cairo_scaled_font_get_font_face(m_scaledFont.get()));
+}
+
FontPlatformData::~FontPlatformData()
{
if (m_fallbacks) {
@@ -182,14 +209,7 @@ FontPlatformData::~FontPlatformData()
bool FontPlatformData::isFixedPitch()
{
- // TODO: Support isFixedPitch() for custom fonts.
- if (!m_pattern)
- return false;
-
- int spacing;
- if (FcPatternGetInteger(m_pattern.get(), FC_SPACING, 0, &spacing) == FcResultMatch)
- return spacing == FC_MONO;
- return false;
+ return m_fixedWidth;
}
bool FontPlatformData::operator==(const FontPlatformData& other) const
@@ -208,4 +228,37 @@ String FontPlatformData::description() const
}
#endif
+void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace)
+{
+ cairo_font_options_t* options = cairo_font_options_copy(getDefaultFontOptions());
+
+ cairo_matrix_t ctm;
+ cairo_matrix_init_identity(&ctm);
+
+ cairo_matrix_t fontMatrix;
+ if (!m_pattern)
+ cairo_matrix_init_scale(&fontMatrix, m_size, m_size);
+ else {
+ setCairoFontOptionsFromFontConfigPattern(options, m_pattern.get());
+
+ // FontConfig may return a list of transformation matrices with the pattern, for instance,
+ // for fonts that are oblique. We use that to initialize the cairo font matrix.
+ FcMatrix fontConfigMatrix, *tempFontConfigMatrix;
+ FcMatrixInit(&fontConfigMatrix);
+
+ // These matrices may be stacked in the pattern, so it's our job to get them all and multiply them.
+ for (int i = 0; FcPatternGetMatrix(m_pattern.get(), FC_MATRIX, i, &tempFontConfigMatrix) == FcResultMatch; i++)
+ FcMatrixMultiply(&fontConfigMatrix, &fontConfigMatrix, tempFontConfigMatrix);
+ cairo_matrix_init(&fontMatrix, fontConfigMatrix.xx, -fontConfigMatrix.yx,
+ -fontConfigMatrix.xy, fontConfigMatrix.yy, 0, 0);
+
+ // The matrix from FontConfig does not include the scale.
+ cairo_matrix_scale(&fontMatrix, m_size, m_size);
+ }
+
+ m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options));
+ cairo_font_options_destroy(options);
+}
+
+
}
diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h
index f3488ef..7d3ff99 100644
--- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h
+++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h
@@ -57,6 +57,7 @@ public:
FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic);
FontPlatformData(float size, bool bold, bool italic);
FontPlatformData(const FontPlatformData&);
+ FontPlatformData(const FontPlatformData&, float size);
~FontPlatformData();
@@ -89,7 +90,11 @@ public:
float m_size;
bool m_syntheticBold;
bool m_syntheticOblique;
+ bool m_fixedWidth;
PlatformRefPtr<cairo_scaled_font_t> m_scaledFont;
+
+private:
+ void initializeWithFontFace(cairo_font_face_t*);
};
}
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 05096a9..0847da1 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -36,20 +36,18 @@
#include "AffineTransform.h"
#include "CairoPath.h"
#include "CairoUtilities.h"
-#include "FEGaussianBlur.h"
+#include "ContextShadow.h"
#include "FloatRect.h"
#include "Font.h"
+#include "GraphicsContextPlatformPrivateCairo.h"
+#include "GraphicsContextPrivate.h"
#include "OwnPtrCairo.h"
-#include "ImageBuffer.h"
-#include "ImageBufferFilter.h"
#include "IntRect.h"
#include "NotImplemented.h"
#include "Path.h"
#include "Pattern.h"
#include "PlatformRefPtrCairo.h"
#include "SimpleFontData.h"
-#include "SourceGraphic.h"
-
#include <cairo.h>
#include <math.h>
#include <stdio.h>
@@ -61,8 +59,6 @@
#elif PLATFORM(WIN)
#include <cairo-win32.h>
#endif
-#include "GraphicsContextPlatformPrivateCairo.h"
-#include "GraphicsContextPrivate.h"
using namespace std;
@@ -132,26 +128,6 @@ static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const
cairo_fill(cr);
}
-static void appendPathToCairoContext(cairo_t* to, cairo_t* from)
-{
- OwnPtr<cairo_path_t> cairoPath(cairo_copy_path(from));
- cairo_append_path(to, cairoPath.get());
-}
-
-// We apply the pending path built via addPath to the Cairo context
-// lazily. This prevents interaction between the path and other routines
-// such as fillRect.
-static void setPathOnCairoContext(cairo_t* to, cairo_t* from)
-{
- cairo_new_path(to);
- appendPathToCairoContext(to, from);
-}
-
-static void appendWebCorePathToCairoContext(cairo_t* context, const Path& path)
-{
- appendPathToCairoContext(context, path.platformPath()->context());
-}
-
static void addConvexPolygonToContext(cairo_t* context, size_t numPoints, const FloatPoint* points)
{
cairo_move_to(context, points[0].x(), points[0].y());
@@ -160,83 +136,59 @@ static void addConvexPolygonToContext(cairo_t* context, size_t numPoints, const
cairo_close_path(context);
}
-void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowOffset, float shadowBlur)
-{
-#if ENABLE(FILTERS)
- // limit radius to 128
- radius = min(128.f, max(shadowBlur, 0.f));
-
- shadowBufferSize = IntSize(sourceRect.width() + radius * 2, sourceRect.height() + radius * 2);
+enum PathDrawingStyle {
+ Fill = 1,
+ Stroke = 2,
+ FillAndStroke = Fill + Stroke
+};
- // determine dimensions of shadow rect
- shadowRect = FloatRect(sourceRect.location(), shadowBufferSize);
- shadowRect.move(shadowOffset.width() - radius, shadowOffset.height() - radius);
-#endif
-}
-
-static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* gcp, bool fillShadow, bool strokeShadow)
+static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* contextPrivate, PathDrawingStyle drawingStyle)
{
-#if ENABLE(FILTERS)
- FloatSize shadowOffset;
- float shadowBlur;
- Color shadowColor;
- if (!context->getShadow(shadowOffset, shadowBlur, shadowColor))
+ ContextShadow* shadow = context->contextShadow();
+ ASSERT(shadow);
+ if (shadow->m_type == ContextShadow::NoShadow)
return;
-
- // Calculate filter values to create appropriate shadow.
- cairo_t* cr = context->platformContext();
- double x0, x1, y0, y1;
- if (strokeShadow)
- cairo_stroke_extents(cr, &x0, &y0, &x1, &y1);
- else
- cairo_fill_extents(cr, &x0, &y0, &x1, &y1);
- FloatRect rect(x0, y0, x1 - x0, y1 - y0);
-
- IntSize shadowBufferSize;
- FloatRect shadowRect;
- float radius = 0;
- GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur);
-
- cairo_clip_extents(cr, &x0, &y0, &x1, &y1);
- FloatRect clipRect(x0, y0, x1 - x0, y1 - y0);
-
- FloatPoint rectLocation = shadowRect.location();
-
- // Reduce the shadow rect using the clip area.
- if (!clipRect.contains(shadowRect)) {
- shadowRect.intersect(clipRect);
- if (shadowRect.isEmpty())
- return;
- shadowRect.inflate(radius);
- shadowBufferSize = IntSize(shadowRect.width(), shadowRect.height());
- }
- shadowOffset = rectLocation - shadowRect.location();
+ // Calculate the extents of the rendered solid paths.
+ cairo_t* cairoContext = context->platformContext();
+ cairo_path_t* path = cairo_copy_path(cairoContext);
+
+ FloatRect solidFigureExtents;
+ double x0 = 0;
+ double x1 = 0;
+ double y0 = 0;
+ double y1 = 0;
+ if (drawingStyle & Stroke) {
+ cairo_stroke_extents(cairoContext, &x0, &y0, &x1, &y1);
+ solidFigureExtents = FloatRect(x0, y0, x1 - x0, y1 - y0);
+ }
+ if (drawingStyle & Fill) {
+ cairo_fill_extents(cairoContext, &x0, &y0, &x1, &y1);
+ FloatRect fillExtents(x0, y0, x1 - x0, y1 - y0);
+ solidFigureExtents.unite(fillExtents);
+ }
- // Create suitably-sized ImageBuffer to hold the shadow.
- OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+ cairo_t* shadowContext = shadow->beginShadowLayer(cairoContext, solidFigureExtents);
+ if (!shadowContext)
+ return;
- // Draw shadow into a new ImageBuffer.
- cairo_t* shadowContext = shadowBuffer->context()->platformContext();
- copyContextProperties(cr, shadowContext);
- cairo_translate(shadowContext, -rect.x() + radius + shadowOffset.width(), -rect.y() + radius + shadowOffset.height());
- cairo_new_path(shadowContext);
- OwnPtr<cairo_path_t> path(cairo_copy_path(cr));
- cairo_append_path(shadowContext, path.get());
+ // It's important to copy the context properties to the new shadow
+ // context to preserve things such as the fill rule and stroke width.
+ copyContextProperties(cairoContext, shadowContext);
+ cairo_append_path(shadowContext, path);
- if (fillShadow)
- setPlatformFill(context, shadowContext, gcp);
- if (strokeShadow)
- setPlatformStroke(context, shadowContext, gcp);
+ if (drawingStyle & Fill)
+ setPlatformFill(context, shadowContext, contextPrivate);
+ if (drawingStyle & Stroke)
+ setPlatformStroke(context, shadowContext, contextPrivate);
- context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
-#endif
+ shadow->endShadowLayer(cairoContext);
}
static void fillCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivate* gcp, cairo_t* cairoContext)
{
cairo_set_fill_rule(cairoContext, context->fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
- drawPathShadow(context, gcp, true, false);
+ drawPathShadow(context, gcp, Fill);
setPlatformFill(context, cairoContext, gcp);
cairo_new_path(cairoContext);
@@ -244,7 +196,7 @@ static void fillCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivat
static void strokeCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivate* gcp, cairo_t* cairoContext)
{
- drawPathShadow(context, gcp, false, true);
+ drawPathShadow(context, gcp, Stroke);
setPlatformStroke(context, cairoContext, gcp);
cairo_new_path(cairoContext);
}
@@ -281,12 +233,20 @@ void GraphicsContext::savePlatformState()
{
cairo_save(m_data->cr);
m_data->save();
+ m_data->shadowStack.append(m_data->shadow);
}
void GraphicsContext::restorePlatformState()
{
cairo_restore(m_data->cr);
m_data->restore();
+
+ if (m_data->shadowStack.isEmpty())
+ m_data->shadow = ContextShadow();
+ else {
+ m_data->shadow = m_data->shadowStack.last();
+ m_data->shadowStack.removeLast();
+ }
}
// Draws a filled rectangle with a stroked border.
@@ -602,7 +562,7 @@ void GraphicsContext::drawPath()
setPathOnCairoContext(cr, m_data->m_pendingPath.context());
cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
- drawPathShadow(this, m_common, true, true);
+ drawPathShadow(this, m_common, FillAndStroke);
setPlatformFill(this, cr, m_common);
setPlatformStroke(this, cr, m_common);
@@ -621,49 +581,14 @@ void GraphicsContext::fillRect(const FloatRect& rect)
cairo_restore(cr);
}
-static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor)
-{
-#if ENABLE(FILTERS)
- FloatSize shadowOffset;
- float shadowBlur;
- Color shadowColor;
- if (!context->getShadow(shadowOffset, shadowBlur, shadowColor))
- return;
-
- AffineTransform transform = context->getCTM();
- // drawTiledShadow still does not work with rotations.
- if ((transform.isIdentityOrTranslationOrFlipped())) {
- cairo_t* cr = context->platformContext();
- cairo_save(cr);
- appendWebCorePathToCairoContext(cr, Path::createRectangle(rect));
- FloatSize corner;
- IntRect shadowRect(rect);
- context->drawTiledShadow(shadowRect, corner, corner, corner, corner, DeviceColorSpace);
- cairo_restore(cr);
-
- return;
- }
-
- IntSize shadowBufferSize;
- FloatRect shadowRect;
- float radius = 0;
- GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur);
-
- // Draw shadow into a new ImageBuffer
- OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
- GraphicsContext* shadowContext = shadowBuffer->context();
- shadowContext->fillRect(FloatRect(FloatPoint(radius, radius), rect.size()), rectColor, DeviceColorSpace);
-
- context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
-#endif
-}
-
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace)
{
if (paintingDisabled())
return;
- drawBorderlessRectShadow(this, rect, color);
+ if (m_data->hasShadow())
+ m_data->shadow.drawRectShadow(this, enclosingIntRect(rect));
+
if (color.alpha())
fillRectSourceOver(m_data->cr, rect, color);
}
@@ -737,8 +662,13 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
setPlatformStrokeStyle(DottedStroke);
#else
int radius = (width - 1) / 2;
- for (unsigned i = 0; i < rectCount; i++)
- appendWebCorePathToCairoContext(cr, Path::createRoundedRectangle(rects[i], FloatSize(radius, radius)));
+ Path path;
+ for (unsigned i = 0; i < rectCount; ++i) {
+ if (i > 0)
+ path.clear();
+ path.addRoundedRect(rects[i], FloatSize(radius, radius));
+ appendWebCorePathToCairoContext(cr, path);
+ }
// Force the alpha to 50%. This matches what the Mac does with outline rings.
Color ringColor(color.red(), color.green(), color.blue(), 127);
@@ -928,57 +858,26 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
cairo_set_fill_rule(cr, savedFillRule);
}
-void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color const&, ColorSpace)
+void GraphicsContext::setPlatformShadow(FloatSize const& size, float blur, Color const& color, ColorSpace)
{
- // Cairo doesn't support shadows natively, they are drawn manually in the draw*
- // functions
-
+ // Cairo doesn't support shadows natively, they are drawn manually in the draw* functions
if (m_common->state.shadowsIgnoreTransforms) {
// Meaning that this graphics context is associated with a CanvasRenderingContext
// We flip the height since CG and HTML5 Canvas have opposite Y axis
m_common->state.shadowOffset = FloatSize(size.width(), -size.height());
- }
+ m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height()));
+ } else
+ m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
}
-void GraphicsContext::applyPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float radius)
+ContextShadow* GraphicsContext::contextShadow()
{
-#if ENABLE(FILTERS)
- setColor(m_data->cr, shadowColor);
- PlatformRefPtr<cairo_surface_t> shadowMask(createShadowMask(buffer, shadowRect, radius));
- cairo_mask_surface(m_data->cr, shadowMask.get(), shadowRect.x(), shadowRect.y());
-#endif
-}
-
-PlatformRefPtr<cairo_surface_t> GraphicsContext::createShadowMask(PassOwnPtr<ImageBuffer> buffer, const FloatRect& shadowRect, float radius)
-{
-#if ENABLE(FILTERS)
- if (!radius)
- return buffer->m_data.m_surface;
-
- FloatPoint blurRadius = FloatPoint(radius, radius);
- float stdDeviation = FEGaussianBlur::calculateStdDeviation(radius);
- if (!stdDeviation)
- return buffer->m_data.m_surface;
-
- // create filter
- RefPtr<Filter> filter = ImageBufferFilter::create();
- filter->setSourceImage(buffer);
- RefPtr<FilterEffect> source = SourceGraphic::create();
- source->setRepaintRectInLocalCoordinates(FloatRect(FloatPoint(), shadowRect.size()));
- source->setIsAlphaImage(true);
- RefPtr<FilterEffect> blur = FEGaussianBlur::create(stdDeviation, stdDeviation);
- FilterEffectVector& inputEffects = blur->inputEffects();
- inputEffects.append(source.get());
- blur->setRepaintRectInLocalCoordinates(FloatRect(FloatPoint(), shadowRect.size()));
- blur->apply(filter.get());
- return blur->resultImage()->m_data.m_surface;
-#endif
+ return &m_data->shadow;
}
-
void GraphicsContext::clearPlatformShadow()
{
- notImplemented();
+ m_data->shadow.clear();
}
void GraphicsContext::beginTransparencyLayer(float opacity)
@@ -1095,43 +994,6 @@ float GraphicsContext::getAlpha()
return m_common->state.globalAlpha;
}
-static inline cairo_operator_t toCairoOperator(CompositeOperator op)
-{
- switch (op) {
- case CompositeClear:
- return CAIRO_OPERATOR_CLEAR;
- case CompositeCopy:
- return CAIRO_OPERATOR_SOURCE;
- case CompositeSourceOver:
- return CAIRO_OPERATOR_OVER;
- case CompositeSourceIn:
- return CAIRO_OPERATOR_IN;
- case CompositeSourceOut:
- return CAIRO_OPERATOR_OUT;
- case CompositeSourceAtop:
- return CAIRO_OPERATOR_ATOP;
- case CompositeDestinationOver:
- return CAIRO_OPERATOR_DEST_OVER;
- case CompositeDestinationIn:
- return CAIRO_OPERATOR_DEST_IN;
- case CompositeDestinationOut:
- return CAIRO_OPERATOR_DEST_OUT;
- case CompositeDestinationAtop:
- return CAIRO_OPERATOR_DEST_ATOP;
- case CompositeXOR:
- return CAIRO_OPERATOR_XOR;
- case CompositePlusDarker:
- return CAIRO_OPERATOR_SATURATE;
- case CompositeHighlight:
- // There is no Cairo equivalent for CompositeHighlight.
- return CAIRO_OPERATOR_OVER;
- case CompositePlusLighter:
- return CAIRO_OPERATOR_ADD;
- default:
- return CAIRO_OPERATOR_SOURCE;
- }
-}
-
void GraphicsContext::setCompositeOperation(CompositeOperator op)
{
if (paintingDisabled())
@@ -1248,206 +1110,20 @@ static inline FloatPoint getPhase(const FloatRect& dest, const FloatRect& tile)
return phase;
}
-/*
- This function uses tiling to improve the performance of the shadow
- drawing of rounded rectangles. The code basically does the following
- steps:
-
- 1. Calculate the minimum rectangle size required to create the
- tiles
-
- 2. If that size is smaller than the real rectangle render the new
- small rectangle and its shadow in a new surface, in other case
- render the shadow of the real rectangle in the destination
- surface.
-
- 3. Calculate the sizes and positions of the tiles and their
- destinations and use drawPattern to render the final shadow. The
- code divides the rendering in 8 tiles:
-
- 1 | 2 | 3
- -----------
- 4 | | 5
- -----------
- 6 | 7 | 8
-
- The corners are directly copied from the small rectangle to the
- real one and the side tiles are 1 pixel width, we use them as
-
- tiles to cover the destination side. The corner tiles are bigger
- than just the side of the rounded corner, we need to increase it
- because the modifications caused by the corner over the blur
- effect. We fill the central part with solid color to complete the
- shadow.
- */
-void GraphicsContext::drawTiledShadow(const IntRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, ColorSpace colorSpace)
-{
-#if ENABLE(FILTERS)
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
- if (!getShadow(shadowSize, shadowBlur, shadowColor))
- return;
-
- // Calculate filter values to create appropriate shadow.
- cairo_t* cr = m_data->cr;
-
- IntSize shadowBufferSize;
- FloatRect shadowRect;
- float blurRadius = 0;
- GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, blurRadius, rect, shadowSize, shadowBlur);
-
- // Size of the tiling side.
- int sideTileWidth = 1;
- float radiusTwice = blurRadius * 2;
-
- // Find the extra space needed from the curve of the corners.
- int extraWidthFromCornerRadii = radiusTwice + max(topLeftRadius.width(), bottomLeftRadius.width()) +
- radiusTwice + max(topRightRadius.width(), bottomRightRadius.width());
- int extraHeightFromCornerRadii = radiusTwice + max(topLeftRadius.height(), topRightRadius.height()) +
- radiusTwice + max(bottomLeftRadius.height(), bottomRightRadius.height());
-
- // The length of a side of the buffer is the enough space for four blur radii,
- // the radii of the corners, and then 1 pixel to draw the side tiles.
- IntSize smallBufferSize = IntSize(sideTileWidth + extraWidthFromCornerRadii,
- sideTileWidth + extraHeightFromCornerRadii);
-
- if ((smallBufferSize.width() > shadowBufferSize.width()) || (smallBufferSize.height() > shadowBufferSize.height()) || (blurRadius <= 0)) {
- // Create suitably-sized ImageBuffer to hold the shadow.
- OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
- if (!shadowBuffer)
- return;
-
- // Draw shadow into a new ImageBuffer.
- cairo_t* shadowContext = shadowBuffer->context()->platformContext();
- copyContextProperties(cr, shadowContext);
- cairo_translate(shadowContext, -rect.x() + blurRadius, -rect.y() + blurRadius);
- cairo_new_path(shadowContext);
- OwnPtr<cairo_path_t> path(cairo_copy_path(cr));
- cairo_append_path(shadowContext, path.get());
-
- setPlatformFill(this, shadowContext, m_common);
-
- applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, blurRadius);
-
- return;
- }
-
- OwnPtr<ImageBuffer> smallBuffer = ImageBuffer::create(smallBufferSize);
- if (!smallBuffer)
- return;
-
- IntRect smallRect = IntRect(blurRadius, blurRadius, smallBufferSize.width() - radiusTwice, smallBufferSize.height() - radiusTwice);
-
- // Draw shadow into a new ImageBuffer.
- cairo_t* smallBufferContext = smallBuffer->context()->platformContext();
- copyContextProperties(cr, smallBufferContext);
- appendWebCorePathToCairoContext(smallBuffer->context()->platformContext(), Path::createRoundedRectangle(smallRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius));
- setPlatformFill(this, smallBufferContext, m_common);
-
- OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(smallBufferSize);
- if (!shadowBuffer)
- return;
-
- smallRect.setSize(smallBufferSize);
-
- PlatformRefPtr<cairo_surface_t> shadowMask(createShadowMask(smallBuffer.release(), smallRect, blurRadius));
-
- cairo_t* shadowContext = shadowBuffer->context()->platformContext();
- setColor(shadowContext, shadowColor);
- cairo_mask_surface(shadowContext, shadowMask.get(), 0, 0);
-
- // Fill the internal part of the shadow.
- shadowRect.inflate(-radiusTwice);
- if (!shadowRect.isEmpty()) {
- cairo_save(cr);
- appendWebCorePathToCairoContext(cr, Path::createRoundedRectangle(shadowRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius));
- setColor(cr, shadowColor);
- cairo_fill(cr);
- cairo_restore(cr);
- }
- shadowRect.inflate(radiusTwice);
-
- // Draw top side.
- FloatRect tileRect = FloatRect(radiusTwice + topLeftRadius.width(), 0, sideTileWidth, radiusTwice);
- FloatRect destRect = tileRect;
- destRect.move(shadowRect.x(), shadowRect.y());
- destRect.setWidth(shadowRect.width() - topLeftRadius.width() - topRightRadius.width() - blurRadius * 4);
- FloatPoint phase = getPhase(destRect, tileRect);
- AffineTransform patternTransform;
- patternTransform.makeIdentity();
- shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
- // Draw the bottom side.
- tileRect = FloatRect(radiusTwice + bottomLeftRadius.width(), smallBufferSize.height() - radiusTwice, sideTileWidth, radiusTwice);
- destRect = tileRect;
- destRect.move(shadowRect.x(), shadowRect.y() + radiusTwice + rect.height() - smallBufferSize.height());
- destRect.setWidth(shadowRect.width() - bottomLeftRadius.width() - bottomRightRadius.width() - blurRadius * 4);
- phase = getPhase(destRect, tileRect);
- shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
- // Draw the right side.
- tileRect = FloatRect(smallBufferSize.width() - radiusTwice, radiusTwice + topRightRadius.height(), radiusTwice, sideTileWidth);
- destRect = tileRect;
- destRect.move(shadowRect.x() + radiusTwice + rect.width() - smallBufferSize.width(), shadowRect.y());
- destRect.setHeight(shadowRect.height() - topRightRadius.height() - bottomRightRadius.height() - blurRadius * 4);
- phase = getPhase(destRect, tileRect);
- shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
- // Draw the left side.
- tileRect = FloatRect(0, radiusTwice + topLeftRadius.height(), radiusTwice, sideTileWidth);
- destRect = tileRect;
- destRect.move(shadowRect.x(), shadowRect.y());
- destRect.setHeight(shadowRect.height() - topLeftRadius.height() - bottomLeftRadius.height() - blurRadius * 4);
- phase = FloatPoint(destRect.x() - tileRect.x(), destRect.y() - tileRect.y());
- shadowBuffer->drawPattern(this, tileRect, patternTransform,
- phase, colorSpace, CompositeSourceOver, destRect);
-
- // Draw the top left corner.
- tileRect = FloatRect(0, 0, radiusTwice + topLeftRadius.width(), radiusTwice + topLeftRadius.height());
- destRect = tileRect;
- destRect.move(shadowRect.x(), shadowRect.y());
- phase = getPhase(destRect, tileRect);
- shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
- // Draw the top right corner.
- tileRect = FloatRect(smallBufferSize.width() - radiusTwice - topRightRadius.width(), 0, radiusTwice + topRightRadius.width(), radiusTwice + topRightRadius.height());
- destRect = tileRect;
- destRect.move(shadowRect.x() + rect.width() - smallBufferSize.width() + radiusTwice, shadowRect.y());
- phase = getPhase(destRect, tileRect);
- shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
- // Draw the bottom right corner.
- tileRect = FloatRect(smallBufferSize.width() - radiusTwice - bottomRightRadius.width(), smallBufferSize.height() - radiusTwice - bottomRightRadius.height(), radiusTwice + bottomRightRadius.width(), radiusTwice + bottomRightRadius.height());
- destRect = tileRect;
- destRect.move(shadowRect.x() + rect.width() - smallBufferSize.width() + radiusTwice, shadowRect.y() + rect.height() - smallBufferSize.height() + radiusTwice);
- phase = getPhase(destRect, tileRect);
- shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
- // Draw the bottom left corner.
- tileRect = FloatRect(0, smallBufferSize.height() - radiusTwice - bottomLeftRadius.height(), radiusTwice + bottomLeftRadius.width(), radiusTwice + bottomLeftRadius.height());
- destRect = tileRect;
- destRect.move(shadowRect.x(), shadowRect.y() + rect.height() - smallBufferSize.height() + radiusTwice);
- phase = getPhase(destRect, tileRect);
- shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-#endif
-}
-
void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
+ if (m_data->hasShadow())
+ m_data->shadow.drawRectShadow(this, r, topLeft, topRight, bottomLeft, bottomRight);
+
cairo_t* cr = m_data->cr;
cairo_save(cr);
- appendWebCorePathToCairoContext(cr, Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight));
+ Path path;
+ path.addRoundedRect(r, topLeft, topRight, bottomLeft, bottomRight);
+ appendWebCorePathToCairoContext(cr, path);
setColor(cr, color);
- AffineTransform transform = this->getCTM();
- // drawTiledShadow still does not work with rotations.
- if (transform.isIdentityOrTranslationOrFlipped())
- drawTiledShadow(r, topLeft, topRight, bottomLeft, bottomRight, colorSpace);
- else
- drawPathShadow(this, m_common, true, false);
cairo_fill(cr);
cairo_restore(cr);
}
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
index 81987ef..527cb72 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
+++ b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
@@ -28,6 +28,7 @@
#include "GraphicsContext.h"
#include "CairoPath.h"
+#include "ContextShadow.h"
#include <cairo.h>
#include <math.h>
#include <stdio.h>
@@ -98,6 +99,10 @@ public:
Vector<float> layers;
CairoPath m_pendingPath;
+ ContextShadow shadow;
+ Vector<ContextShadow> shadowStack;
+ bool hasShadow() const { return shadow.m_type != ContextShadow::NoShadow; }
+
#if PLATFORM(GTK)
GdkEventExpose* expose;
#elif PLATFORM(WIN)
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 976dcb4..d452c3a 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -69,7 +69,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
{
}
-ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, bool& success)
: m_data(size)
, m_size(size)
{
diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp
index 904e819..8f7a194 100644
--- a/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -31,7 +31,9 @@
#if PLATFORM(CAIRO)
#include "AffineTransform.h"
+#include "CairoUtilities.h"
#include "Color.h"
+#include "ContextShadow.h"
#include "FloatRect.h"
#include "PlatformRefPtrCairo.h"
#include "GraphicsContext.h"
@@ -133,29 +135,18 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() };
cairo_pattern_set_matrix(pattern, &matrix);
- // Draw the shadow
-#if ENABLE(FILTERS)
- FloatSize shadowOffset;
- float shadowBlur;
- Color shadowColor;
- if (context->getShadow(shadowOffset, shadowBlur, shadowColor)) {
- IntSize shadowBufferSize;
- FloatRect shadowRect;
- float radius = 0;
- context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, dstRect, shadowOffset, shadowBlur);
- shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() * context->getAlpha()) / 255.f);
-
- //draw shadow into a new ImageBuffer
- OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
- cairo_t* shadowContext = shadowBuffer->context()->platformContext();
- cairo_set_source(shadowContext, pattern);
- cairo_translate(shadowContext, -dstRect.x(), -dstRect.y());
- cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
- cairo_fill(shadowContext);
-
- context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
+ ContextShadow* shadow = context->contextShadow();
+ ASSERT(shadow);
+ if (shadow->m_type != ContextShadow::NoShadow) {
+ cairo_t* shadowContext = shadow->beginShadowLayer(cr, dstRect);
+ if (shadowContext) {
+ cairo_translate(shadowContext, dstRect.x(), dstRect.y());
+ cairo_set_source(shadowContext, pattern);
+ cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
+ cairo_fill(shadowContext);
+ shadow->endShadowLayer(cr);
+ }
}
-#endif
// Draw the image.
cairo_translate(cr, dstRect.x(), dstRect.y());
@@ -172,46 +163,15 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
}
void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform,
- const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace colorSpace, CompositeOperator op, const FloatRect& destRect)
{
cairo_surface_t* image = nativeImageForCurrentFrame();
if (!image) // If it's too early we won't have an image yet.
return;
- // Avoid NaN
- if (!isfinite(phase.x()) || !isfinite(phase.y()))
- return;
-
cairo_t* cr = context->platformContext();
- context->save();
-
- PlatformRefPtr<cairo_surface_t> clippedImageSurface = 0;
- if (tileRect.size() != size()) {
- IntRect imageSize = enclosingIntRect(tileRect);
- clippedImageSurface = adoptPlatformRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, imageSize.width(), imageSize.height()));
- PlatformRefPtr<cairo_t> clippedImageContext(cairo_create(clippedImageSurface.get()));
- cairo_set_source_surface(clippedImageContext.get(), image, -tileRect.x(), -tileRect.y());
- cairo_paint(clippedImageContext.get());
- image = clippedImageSurface.get();
- }
-
- cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
- cairo_matrix_t pattern_matrix = cairo_matrix_t(patternTransform);
- cairo_matrix_t phase_matrix = {1, 0, 0, 1, phase.x() + tileRect.x() * patternTransform.a(), phase.y() + tileRect.y() * patternTransform.d()};
- cairo_matrix_t combined;
- cairo_matrix_multiply(&combined, &pattern_matrix, &phase_matrix);
- cairo_matrix_invert(&combined);
- cairo_pattern_set_matrix(pattern, &combined);
-
- context->setCompositeOperation(op);
- cairo_set_source(cr, pattern);
- cairo_pattern_destroy(pattern);
- cairo_rectangle(cr, destRect.x(), destRect.y(), destRect.width(), destRect.height());
- cairo_fill(cr);
-
- context->restore();
+ drawPatternToCairoContext(cr, image, size(), tileRect, patternTransform, phase, toCairoOperator(op), destRect);
if (imageObserver())
imageObserver()->didDraw(this);
diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp
index 776bceb..d5045be 100644
--- a/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -337,40 +337,4 @@ void Path::transform(const AffineTransform& trans)
cairo_transform(cr, &c_matrix);
}
-String Path::debugString() const
-{
- if (isEmpty())
- return String();
-
- String pathString;
- OwnPtr<cairo_path_t> path(cairo_copy_path(platformPath()->context()));
- cairo_path_data_t* data;
-
- for (int i = 0; i < path->num_data; i += path->data[i].header.length) {
- data = &path->data[i];
- switch (data->header.type) {
- case CAIRO_PATH_MOVE_TO:
- if (i < (path->num_data - path->data[i].header.length))
- pathString += String::format("M%.2f,%.2f ",
- data[1].point.x, data[1].point.y);
- break;
- case CAIRO_PATH_LINE_TO:
- pathString += String::format("L%.2f,%.2f ",
- data[1].point.x, data[1].point.y);
- break;
- case CAIRO_PATH_CURVE_TO:
- pathString += String::format("C%.2f,%.2f,%.2f,%.2f,%.2f,%.2f ",
- data[1].point.x, data[1].point.y,
- data[2].point.x, data[2].point.y,
- data[3].point.x, data[3].point.y);
- break;
- case CAIRO_PATH_CLOSE_PATH:
- pathString += "Z ";
- break;
- }
- }
-
- return pathString.simplifyWhiteSpace();
-}
-
} // namespace WebCore
diff --git a/WebCore/platform/graphics/cg/ColorCG.cpp b/WebCore/platform/graphics/cg/ColorCG.cpp
index 6f05c38..c9b05da 100644
--- a/WebCore/platform/graphics/cg/ColorCG.cpp
+++ b/WebCore/platform/graphics/cg/ColorCG.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
#if PLATFORM(CG)
+#include "GraphicsContextCG.h"
#include <wtf/Assertions.h>
#include <wtf/RetainPtr.h>
#include <ApplicationServices/ApplicationServices.h>
@@ -69,37 +70,79 @@ Color::Color(CGColorRef color)
m_valid = true;
}
-#if OS(WINDOWS)
+static inline CGColorSpaceRef cachedCGColorSpace(ColorSpace colorSpace)
+{
+ switch (colorSpace) {
+ case ColorSpaceDeviceRGB:
+ return deviceRGBColorSpaceRef();
+ case ColorSpaceSRGB:
+ return sRGBColorSpaceRef();
+ case ColorSpaceLinearRGB:
+ return linearRGBColorSpaceRef();
+ }
+ ASSERT_NOT_REACHED();
+ return deviceRGBColorSpaceRef();
+}
-CGColorRef createCGColor(const Color& c)
+static CGColorRef leakCGColor(const Color& color, ColorSpace colorSpace)
{
- CGColorRef color = NULL;
-#ifdef OBSOLETE_COLORSYNC_API
- CMProfileRef prof = NULL;
- CMGetSystemProfile(&prof);
- RetainPtr<CGColorSpaceRef> rgbSpace(AdoptCF, CGColorSpaceCreateWithPlatformColorSpace(prof));
-#else
- ColorSyncProfileRef prof = ColorSyncProfileCreateWithDisplayID(0);
- RetainPtr<CGColorSpaceRef> rgbSpace(AdoptCF, CGColorSpaceCreateWithPlatformColorSpace(const_cast<void*>(reinterpret_cast<const void*>(prof))));
-#endif
-
- if (rgbSpace) {
- CGFloat components[4] = { static_cast<CGFloat>(c.red()) / 255, static_cast<CGFloat>(c.green()) / 255,
- static_cast<CGFloat>(c.blue()) / 255, static_cast<CGFloat>(c.alpha()) / 255 };
- color = CGColorCreate(rgbSpace.get(), components);
+ CGFloat components[4];
+ color.getRGBA(components[0], components[1], components[2], components[3]);
+ return CGColorCreate(cachedCGColorSpace(colorSpace), components);
+}
+
+template<ColorSpace colorSpace> static CGColorRef cachedCGColor(const Color& color)
+{
+ switch (color.rgb()) {
+ case Color::transparent: {
+ static CGColorRef transparentCGColor = leakCGColor(color, colorSpace);
+ return transparentCGColor;
+ }
+ case Color::black: {
+ static CGColorRef blackCGColor = leakCGColor(color, colorSpace);
+ return blackCGColor;
+ }
+ case Color::white: {
+ static CGColorRef whiteCGColor = leakCGColor(color, colorSpace);
+ return whiteCGColor;
+ }
}
-#ifdef OBSOLETE_COLORSYNC_API
- CMCloseProfile(prof);
-#else
- if (prof)
- CFRelease(prof);
-#endif
+ ASSERT(color.rgb());
- return color;
+ const size_t cacheSize = 32;
+ static RGBA32 cachedRGBAValues[cacheSize];
+ static RetainPtr<CGColorRef>* cachedCGColors = new RetainPtr<CGColorRef>[cacheSize];
+
+ for (size_t i = 0; i < cacheSize; ++i) {
+ if (cachedRGBAValues[i] == color.rgb())
+ return cachedCGColors[i].get();
+ }
+
+ CGColorRef newCGColor = leakCGColor(color, colorSpace);
+
+ static size_t cursor;
+ cachedRGBAValues[cursor] = color.rgb();
+ cachedCGColors[cursor].adoptCF(newCGColor);
+ if (++cursor == cacheSize)
+ cursor = 0;
+
+ return newCGColor;
}
-#endif // OS(WINDOWS)
+CGColorRef cachedCGColor(const Color& color, ColorSpace colorSpace)
+{
+ switch (colorSpace) {
+ case ColorSpaceDeviceRGB:
+ return cachedCGColor<ColorSpaceDeviceRGB>(color);
+ case ColorSpaceSRGB:
+ return cachedCGColor<ColorSpaceSRGB>(color);
+ case ColorSpaceLinearRGB:
+ return cachedCGColor<ColorSpaceLinearRGB>(color);
+ }
+ ASSERT_NOT_REACHED();
+ return cachedCGColor(color, ColorSpaceDeviceRGB);
+}
}
diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
index 2a81fd2..fe4fc7f 100644
--- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
@@ -64,9 +64,35 @@ bool GraphicsContext3D::getImageData(Image* image,
return false;
size_t width = CGImageGetWidth(cgImage);
size_t height = CGImageGetHeight(cgImage);
- if (!width || !height || CGImageGetBitsPerComponent(cgImage) != 8)
+ if (!width || !height)
return false;
- size_t componentsPerPixel = CGImageGetBitsPerPixel(cgImage) / 8;
+ size_t bitsPerComponent = CGImageGetBitsPerComponent(cgImage);
+ size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
+ if (bitsPerComponent != 8 && bitsPerComponent != 16)
+ return false;
+ if (bitsPerPixel % bitsPerComponent)
+ return false;
+ size_t componentsPerPixel = bitsPerPixel / bitsPerComponent;
+ bool srcByteOrder16Big = false;
+ if (bitsPerComponent == 16) {
+ CGBitmapInfo bitInfo = CGImageGetBitmapInfo(cgImage);
+ switch (bitInfo & kCGBitmapByteOrderMask) {
+ case kCGBitmapByteOrder16Big:
+ srcByteOrder16Big = true;
+ break;
+ case kCGBitmapByteOrder16Little:
+ srcByteOrder16Big = false;
+ break;
+ case kCGBitmapByteOrderDefault:
+ // This is a bug in earlier version of cg where the default endian
+ // is little whereas the decoded 16-bit png image data is actually
+ // Big. Later version (10.6.4) no longer returns ByteOrderDefault.
+ srcByteOrder16Big = true;
+ break;
+ default:
+ return false;
+ }
+ }
SourceDataFormat srcDataFormat = kSourceFormatRGBA8;
AlphaOp neededAlphaOp = kAlphaDoNothing;
switch (CGImageGetAlphaInfo(cgImage)) {
@@ -79,10 +105,16 @@ bool GraphicsContext3D::getImageData(Image* image,
neededAlphaOp = kAlphaDoUnmultiply;
switch (componentsPerPixel) {
case 2:
- srcDataFormat = kSourceFormatAR8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatAR8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatAR16Big : kSourceFormatAR16Little;
break;
case 4:
- srcDataFormat = kSourceFormatARGB8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatARGB8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatARGB16Big : kSourceFormatARGB16Little;
break;
default:
return false;
@@ -94,13 +126,22 @@ bool GraphicsContext3D::getImageData(Image* image,
neededAlphaOp = kAlphaDoPremultiply;
switch (componentsPerPixel) {
case 1:
- srcDataFormat = kSourceFormatA8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatA8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatA16Big : kSourceFormatA16Little;
break;
case 2:
- srcDataFormat = kSourceFormatAR8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatAR8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatAR16Big : kSourceFormatAR16Little;
break;
case 4:
- srcDataFormat = kSourceFormatARGB8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatARGB8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatARGB16Big : kSourceFormatARGB16Little;
break;
default:
return false;
@@ -110,10 +151,16 @@ bool GraphicsContext3D::getImageData(Image* image,
// This path is only accessible for MacOS earlier than 10.6.4.
switch (componentsPerPixel) {
case 2:
- srcDataFormat = kSourceFormatAR8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatAR8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatAR16Big : kSourceFormatAR16Little;
break;
case 4:
- srcDataFormat = kSourceFormatARGB8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatARGB8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatARGB16Big : kSourceFormatARGB16Little;
break;
default:
return false;
@@ -127,10 +174,16 @@ bool GraphicsContext3D::getImageData(Image* image,
neededAlphaOp = kAlphaDoUnmultiply;
switch (componentsPerPixel) {
case 2:
- srcDataFormat = kSourceFormatRA8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatRA8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatRA16Big : kSourceFormatRA16Little;
break;
case 4:
- srcDataFormat = kSourceFormatRGBA8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatRGBA8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatRGBA16Big : kSourceFormatRGBA16Little;
break;
default:
return false;
@@ -141,13 +194,22 @@ bool GraphicsContext3D::getImageData(Image* image,
neededAlphaOp = kAlphaDoPremultiply;
switch (componentsPerPixel) {
case 1:
- srcDataFormat = kSourceFormatA8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatA8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatA16Big : kSourceFormatA16Little;
break;
case 2:
- srcDataFormat = kSourceFormatRA8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatRA8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatRA16Big : kSourceFormatRA16Little;
break;
case 4:
- srcDataFormat = kSourceFormatRGBA8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatRGBA8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatRGBA16Big : kSourceFormatRGBA16Little;
break;
default:
return false;
@@ -156,10 +218,16 @@ bool GraphicsContext3D::getImageData(Image* image,
case kCGImageAlphaNoneSkipLast:
switch (componentsPerPixel) {
case 2:
- srcDataFormat = kSourceFormatRA8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatRA8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatRA16Big : kSourceFormatRA16Little;
break;
case 4:
- srcDataFormat = kSourceFormatRGBA8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatRGBA8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatRGBA16Big : kSourceFormatRGBA16Little;
break;
default:
return false;
@@ -168,10 +236,16 @@ bool GraphicsContext3D::getImageData(Image* image,
case kCGImageAlphaNone:
switch (componentsPerPixel) {
case 1:
- srcDataFormat = kSourceFormatR8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatR8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatR16Big : kSourceFormatR16Little;
break;
case 3:
- srcDataFormat = kSourceFormatRGB8;
+ if (bitsPerComponent == 8)
+ srcDataFormat = kSourceFormatRGB8;
+ else
+ srcDataFormat = srcByteOrder16Big ? kSourceFormatRGB16Big : kSourceFormatRGB16Little;
break;
default:
return false;
@@ -188,7 +262,7 @@ bool GraphicsContext3D::getImageData(Image* image,
outputVector.resize(width * height * 4);
unsigned int srcUnpackAlignment = 0;
size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
- unsigned int padding = bytesPerRow - componentsPerPixel * width;
+ unsigned int padding = bytesPerRow - bitsPerPixel / 8 * width;
if (padding) {
srcUnpackAlignment = padding + 1;
while (bytesPerRow % srcUnpackAlignment)
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index e5079dc..9e0a2f5 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -26,7 +26,7 @@
#define _USE_MATH_DEFINES 1
#include "config.h"
-#include "GraphicsContext.h"
+#include "GraphicsContextCG.h"
#include "AffineTransform.h"
#include "FloatConversion.h"
@@ -69,60 +69,14 @@ using namespace std;
namespace WebCore {
-static CGColorRef createCGColorWithColorSpace(const Color& color, ColorSpace colorSpace)
-{
- CGFloat components[4];
- color.getRGBA(components[0], components[1], components[2], components[3]);
-
- CGColorRef cgColor = 0;
- if (colorSpace == sRGBColorSpace)
- cgColor = CGColorCreate(sRGBColorSpaceRef(), components);
- else
- cgColor = CGColorCreate(deviceRGBColorSpaceRef(), components);
-
- return cgColor;
-}
-
static void setCGFillColor(CGContextRef context, const Color& color, ColorSpace colorSpace)
{
- CGColorRef cgColor = createCGColorWithColorSpace(color, colorSpace);
- CGContextSetFillColorWithColor(context, cgColor);
- CFRelease(cgColor);
+ CGContextSetFillColorWithColor(context, cachedCGColor(color, colorSpace));
}
static void setCGStrokeColor(CGContextRef context, const Color& color, ColorSpace colorSpace)
{
- CGColorRef cgColor = createCGColorWithColorSpace(color, colorSpace);
- CGContextSetStrokeColorWithColor(context, cgColor);
- CFRelease(cgColor);
-}
-
-static void setCGFillColorSpace(CGContextRef context, ColorSpace colorSpace)
-{
- switch (colorSpace) {
- case DeviceColorSpace:
- break;
- case sRGBColorSpace:
- CGContextSetFillColorSpace(context, sRGBColorSpaceRef());
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-}
-
-static void setCGStrokeColorSpace(CGContextRef context, ColorSpace colorSpace)
-{
- switch (colorSpace) {
- case DeviceColorSpace:
- break;
- case sRGBColorSpace:
- CGContextSetStrokeColorSpace(context, sRGBColorSpaceRef());
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
- }
+ CGContextSetStrokeColorWithColor(context, cachedCGColor(color, colorSpace));
}
CGColorSpaceRef deviceRGBColorSpaceRef()
@@ -142,6 +96,17 @@ CGColorSpaceRef sRGBColorSpaceRef()
#endif
}
+CGColorSpaceRef linearRGBColorSpaceRef()
+{
+ // FIXME: Windows should be able to use kCGColorSpaceGenericRGBLinear, this is tracked by http://webkit.org/b/31363.
+#if PLATFORM(WIN) || defined(BUILDING_ON_TIGER)
+ return deviceRGBColorSpaceRef();
+#else
+ static CGColorSpaceRef linearRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear);
+ return linearRGBSpace;
+#endif
+}
+
GraphicsContext::GraphicsContext(CGContextRef cgContext)
: m_common(createGraphicsContextPrivate())
, m_data(new GraphicsContextPlatformPrivate(cgContext))
@@ -586,9 +551,6 @@ void GraphicsContext::fillPath()
CGContextRef context = platformContext();
- // FIXME: Is this helpful and correct in the fillPattern and fillGradient cases?
- setCGFillColorSpace(context, m_common->state.fillColorSpace);
-
if (m_common->state.fillGradient) {
CGContextSaveGState(context);
if (fillRule() == RULE_EVENODD)
@@ -613,9 +575,6 @@ void GraphicsContext::strokePath()
CGContextRef context = platformContext();
- // FIXME: Is this helpful and correct in the strokePattern and strokeGradient cases?
- setCGStrokeColorSpace(context, m_common->state.strokeColorSpace);
-
if (m_common->state.strokeGradient) {
CGContextSaveGState(context);
CGContextReplacePathWithStrokedPath(context);
@@ -638,9 +597,6 @@ void GraphicsContext::fillRect(const FloatRect& rect)
CGContextRef context = platformContext();
- // FIXME: Is this helpful and correct in the fillPattern and fillGradient cases?
- setCGFillColorSpace(context, m_common->state.fillColorSpace);
-
if (m_common->state.fillGradient) {
CGContextSaveGState(context);
CGContextClipToRect(context, rect);
@@ -659,17 +615,18 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
{
if (paintingDisabled())
return;
+
CGContextRef context = platformContext();
Color oldFillColor = fillColor();
ColorSpace oldColorSpace = fillColorSpace();
if (oldFillColor != color || oldColorSpace != colorSpace)
- setCGFillColor(context, color, colorSpace);
+ setCGFillColor(context, color, colorSpace);
CGContextFillRect(context, rect);
if (oldFillColor != color || oldColorSpace != colorSpace)
- setCGFillColor(context, oldFillColor, oldColorSpace);
+ setCGFillColor(context, oldFillColor, oldColorSpace);
}
void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
@@ -684,7 +641,9 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
if (oldFillColor != color || oldColorSpace != colorSpace)
setCGFillColor(context, color, colorSpace);
- addPath(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
+ Path path;
+ path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
+ addPath(path);
fillPath();
if (oldFillColor != color || oldColorSpace != colorSpace)
@@ -821,13 +780,8 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con
// and we should therefore just use the default shadow color.
if (!color.isValid())
CGContextSetShadow(context, CGSizeMake(xOffset, yOffset), blurRadius);
- else {
- RetainPtr<CGColorRef> colorCG(AdoptCF, createCGColorWithColorSpace(color, colorSpace));
- CGContextSetShadowWithColor(context,
- CGSizeMake(xOffset, yOffset),
- blurRadius,
- colorCG.get());
- }
+ else
+ CGContextSetShadowWithColor(context, CGSizeMake(xOffset, yOffset), blurRadius, cachedCGColor(color, colorSpace));
}
void GraphicsContext::clearPlatformShadow()
@@ -865,9 +819,6 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
CGContextRef context = platformContext();
- // FIXME: Is this helpful and correct in the strokePattern and strokeGradient cases?
- setCGStrokeColorSpace(context, m_common->state.strokeColorSpace);
-
if (m_common->state.strokeGradient) {
CGContextSaveGState(context);
setStrokeThickness(lineWidth);
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.h b/WebCore/platform/graphics/cg/GraphicsContextCG.h
new file mode 100644
index 0000000..5de95ef
--- /dev/null
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GraphicsContextCG_h
+#define GraphicsContextCG_h
+
+#include "GraphicsContext.h"
+
+typedef struct CGColorSpace *CGColorSpaceRef;
+
+namespace WebCore {
+
+CGColorSpaceRef deviceRGBColorSpaceRef();
+CGColorSpaceRef sRGBColorSpaceRef();
+CGColorSpaceRef linearRGBColorSpaceRef();
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
index aac4f45..1d0a99f 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
+++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -28,12 +28,6 @@
namespace WebCore {
-// FIXME: This would be in GraphicsContextCG.h if that existed.
-CGColorSpaceRef deviceRGBColorSpaceRef();
-
-// FIXME: This would be in GraphicsContextCG.h if that existed.
-CGColorSpaceRef sRGBColorSpaceRef();
-
class GraphicsContextPlatformPrivate {
public:
GraphicsContextPlatformPrivate(CGContextRef cgContext)
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index ecbcf60..640692a 100644
--- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -31,12 +31,12 @@
#include "Base64.h"
#include "BitmapImage.h"
#include "GraphicsContext.h"
+#include "GraphicsContextCG.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/text/StringConcatenate.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/RetainPtr.h>
#include <wtf/Threading.h>
@@ -56,7 +56,7 @@ ImageBufferData::ImageBufferData(const IntSize&)
{
}
-ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, bool& success)
: m_data(size)
, m_size(size)
{
@@ -65,12 +65,11 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
return;
unsigned bytesPerRow = size.width();
- if (imageColorSpace != GrayScale) {
- // Protect against overflow
- if (bytesPerRow > 0x3FFFFFFF)
- return;
- bytesPerRow *= 4;
- }
+
+ // Protect against overflow
+ if (bytesPerRow > 0x3FFFFFFF)
+ return;
+ bytesPerRow *= 4;
m_data.m_bytesPerRow = bytesPerRow;
size_t dataSize = size.height() * bytesPerRow;
@@ -80,27 +79,20 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0);
switch(imageColorSpace) {
- case DeviceRGB:
- m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
- break;
- case GrayScale:
- m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceGray());
- break;
-#if ((PLATFORM(MAC) || PLATFORM(CHROMIUM)) && !defined(BUILDING_ON_TIGER))
- case LinearRGB:
- m_data.m_colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear));
- break;
-
-#endif
- default:
- m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
- break;
+ case ColorSpaceDeviceRGB:
+ m_data.m_colorSpace = deviceRGBColorSpaceRef();
+ break;
+ case ColorSpaceSRGB:
+ m_data.m_colorSpace = sRGBColorSpaceRef();
+ break;
+ case ColorSpaceLinearRGB:
+ m_data.m_colorSpace = linearRGBColorSpaceRef();
+ break;
}
- m_data.m_grayScale = imageColorSpace == GrayScale;
- m_data.m_bitmapInfo = m_data.m_grayScale ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast;
+ m_data.m_bitmapInfo = kCGImageAlphaPremultipliedLast;
RetainPtr<CGContextRef> cgContext(AdoptCF, CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow,
- m_data.m_colorSpace.get(), m_data.m_bitmapInfo));
+ m_data.m_colorSpace, m_data.m_bitmapInfo));
if (!cgContext)
return;
@@ -135,8 +127,8 @@ PassRefPtr<Image> ImageBuffer::copyImage() const
static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data)
{
- return CGImageCreate(size.width(), size.height(), 8, data.m_grayScale ? 8 : 32, data.m_bytesPerRow,
- data.m_colorSpace.get(), data.m_bitmapInfo, data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
+ return CGImageCreate(size.width(), size.height(), 8, 32, data.m_bytesPerRow,
+ data.m_colorSpace, data.m_bitmapInfo, data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
}
void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
@@ -145,7 +137,7 @@ void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace,
if (destContext == context()) {
// We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first.
RefPtr<Image> copy = copyImage();
- destContext->drawImage(copy.get(), DeviceColorSpace, destRect, srcRect, op, useLowQualityScale);
+ destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale);
} else {
RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
destContext->drawImage(imageForRendering.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
@@ -371,7 +363,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
base64Encode(reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())), CFDataGetLength(data.get()), out);
out.append('\0');
- return String::format("data:%s;base64,%s", mimeType.utf8().data(), out.data());
+ return makeString("data:", mimeType, ";base64,", out.data());
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/cg/ImageBufferData.h b/WebCore/platform/graphics/cg/ImageBufferData.h
index 2f9d854..456c934 100644
--- a/WebCore/platform/graphics/cg/ImageBufferData.h
+++ b/WebCore/platform/graphics/cg/ImageBufferData.h
@@ -46,9 +46,8 @@ public:
RetainPtr<CGDataProviderRef> m_dataProvider;
CGBitmapInfo m_bitmapInfo;
- bool m_grayScale;
unsigned m_bytesPerRow;
- RetainPtr<CGColorSpaceRef> m_colorSpace;
+ CGColorSpaceRef m_colorSpace;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/cg/ImageCG.cpp b/WebCore/platform/graphics/cg/ImageCG.cpp
index 70a80a0..c7ed0c8 100644
--- a/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,12 +31,12 @@
#include "AffineTransform.h"
#include "FloatConversion.h"
#include "FloatRect.h"
-#include "GraphicsContext.h"
-#include "GraphicsContextPlatformPrivateCG.h"
+#include "GraphicsContextCG.h"
#include "ImageObserver.h"
#include "PDFDocumentImage.h"
#include "PlatformString.h"
#include <ApplicationServices/ApplicationServices.h>
+#include <wtf/RetainPtr.h>
#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
#include "WebCoreSystemInterface.h"
@@ -138,11 +138,12 @@ static RetainPtr<CGImageRef> imageWithColorSpace(CGImageRef originalImage, Color
return originalImage;
switch (colorSpace) {
- case DeviceColorSpace:
+ case ColorSpaceDeviceRGB:
return originalImage;
- case sRGBColorSpace:
- return RetainPtr<CGImageRef>(AdoptCF, CGImageCreateCopyWithColorSpace(originalImage,
- sRGBColorSpaceRef()));
+ case ColorSpaceSRGB:
+ return RetainPtr<CGImageRef>(AdoptCF, CGImageCreateCopyWithColorSpace(originalImage, sRGBColorSpaceRef()));
+ case ColorSpaceLinearRGB:
+ return RetainPtr<CGImageRef>(AdoptCF, CGImageCreateCopyWithColorSpace(originalImage, linearRGBColorSpaceRef()));
}
ASSERT_NOT_REACHED();
@@ -186,7 +187,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
// containing only the portion we want to display. We need to do this because high-quality
// interpolation smoothes sharp edges, causing pixels from outside the source rect to bleed
// into the destination rect. See <rdar://problem/6112909>.
- shouldUseSubimage = (interpolationQuality == kCGInterpolationHigh || interpolationQuality == kCGInterpolationDefault) && srcRect.size() != destRect.size();
+ shouldUseSubimage = (interpolationQuality == kCGInterpolationHigh || interpolationQuality == kCGInterpolationDefault) && (srcRect.size() != destRect.size() || !ctxt->getCTM().isIdentityOrTranslationOrFlipped());
float xScale = srcRect.width() / destRect.width();
float yScale = srcRect.height() / destRect.height();
if (shouldUseSubimage) {
diff --git a/WebCore/platform/graphics/cg/PathCG.cpp b/WebCore/platform/graphics/cg/PathCG.cpp
index 90d4b8a..b47ed02 100644
--- a/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/WebCore/platform/graphics/cg/PathCG.cpp
@@ -254,61 +254,9 @@ FloatPoint Path::currentPoint() const
return CGPathGetCurrentPoint(m_path);
}
-static void CGPathToCFStringApplierFunction(void* info, const CGPathElement *element)
-{
- CFMutableStringRef string = static_cast<CFMutableStringRef>(info);
-
- CGPoint* points = element->points;
- switch (element->type) {
- case kCGPathElementMoveToPoint:
- CFStringAppendFormat(string, 0, CFSTR("M%.2f,%.2f "), points[0].x, points[0].y);
- break;
- case kCGPathElementAddLineToPoint:
- CFStringAppendFormat(string, 0, CFSTR("L%.2f,%.2f "), points[0].x, points[0].y);
- break;
- case kCGPathElementAddQuadCurveToPoint:
- CFStringAppendFormat(string, 0, CFSTR("Q%.2f,%.2f,%.2f,%.2f "),
- points[0].x, points[0].y, points[1].x, points[1].y);
- break;
- case kCGPathElementAddCurveToPoint:
- CFStringAppendFormat(string, 0, CFSTR("C%.2f,%.2f,%.2f,%.2f,%.2f,%.2f "),
- points[0].x, points[0].y, points[1].x, points[1].y,
- points[2].x, points[2].y);
- break;
- case kCGPathElementCloseSubpath:
- CFStringAppendFormat(string, 0, CFSTR("Z "));
- break;
- }
-}
-
-static CFStringRef CFStringFromCGPath(CGPathRef path)
-{
- if (!path)
- return 0;
-
- CFMutableStringRef string = CFStringCreateMutable(NULL, 0);
- CGPathApply(path, string, CGPathToCFStringApplierFunction);
- CFStringTrimWhitespace(string);
-
-
- return string;
-}
-
-
#pragma mark -
#pragma mark Path Management
-String Path::debugString() const
-{
- String result;
- if (!isEmpty()) {
- CFStringRef pathString = CFStringFromCGPath(m_path);
- result = String(pathString);
- CFRelease(pathString);
- }
- return result;
-}
-
struct PathApplierInfo {
void* info;
PathApplierFunction function;
diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
index 8dda4d6..eba5349 100644
--- a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -43,8 +43,6 @@
#include "PlatformContextSkia.h"
#include "skia/ext/platform_canvas.h"
#elif PLATFORM(CG)
-#include "LocalCurrentGraphicsContext.h"
-
#include <CoreGraphics/CGBitmapContext.h>
#endif
@@ -121,6 +119,7 @@ PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(GraphicsLayerChrom
ContentLayerChromium::ContentLayerChromium(GraphicsLayerChromium* owner)
: LayerChromium(owner)
, m_contentsTexture(0)
+ , m_skipsDraw(false)
{
}
@@ -129,16 +128,6 @@ ContentLayerChromium::~ContentLayerChromium()
cleanupResources();
}
-void ContentLayerChromium::setLayerRenderer(LayerRendererChromium* renderer)
-{
- // If we're changing layer renderers then we need to free up any resources
- // allocated by the old renderer.
- if (layerRenderer() && layerRenderer() != renderer)
- cleanupResources();
-
- LayerChromium::setLayerRenderer(renderer);
-}
-
void ContentLayerChromium::cleanupResources()
{
if (layerRenderer()) {
@@ -149,6 +138,42 @@ void ContentLayerChromium::cleanupResources()
}
}
+bool ContentLayerChromium::requiresClippedUpdateRect() const
+{
+ // To avoid allocating excessively large textures, switch into "large layer mode" if
+ // one of the layer's dimensions is larger than 2000 pixels or the current size
+ // of the visible rect. This is a temporary measure until layer tiling is implemented.
+ static const int maxLayerSize = 2000;
+ return (m_bounds.width() > max(maxLayerSize, layerRenderer()->rootLayerContentRect().width())
+ || m_bounds.height() > max(maxLayerSize, layerRenderer()->rootLayerContentRect().height())
+ || !layerRenderer()->checkTextureSize(m_bounds));
+}
+
+void ContentLayerChromium::calculateClippedUpdateRect(IntRect& dirtyRect, IntRect& drawRect) const
+{
+ // For the given layer size and content rect, calculate:
+ // 1) The minimal texture space rectangle to be uploaded, returned in dirtyRect.
+ // 2) The content rect-relative rectangle to draw this texture in, returned in drawRect.
+
+ const IntRect clipRect = layerRenderer()->currentScissorRect();
+ const TransformationMatrix& transform = drawTransform();
+ // The layer's draw transform points to the center of the layer, relative to
+ // the content rect. layerPos is the distance from the top left of the
+ // layer to the top left of the content rect.
+ const IntPoint layerPos(m_bounds.width() / 2 - transform.m41(),
+ m_bounds.height() / 2 - transform.m42());
+ // Transform the contentRect into the space of the layer.
+ IntRect contentRectInLayerSpace(layerPos, clipRect.size());
+
+ // Clip the entire layer against the visible region in the content rect
+ // and use that as the drawable texture, instead of the entire layer.
+ dirtyRect = IntRect(IntPoint(0, 0), m_bounds);
+ dirtyRect.intersect(contentRectInLayerSpace);
+
+ // The draw position is relative to the content rect.
+ drawRect = IntRect(toPoint(dirtyRect.location() - layerPos), dirtyRect.size());
+}
+
void ContentLayerChromium::updateContents()
{
RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
@@ -159,29 +184,47 @@ void ContentLayerChromium::updateContents()
ASSERT(layerRenderer());
- // FIXME: Remove this test when tiled layers are implemented.
- m_skipsDraw = false;
- if (!layerRenderer()->checkTextureSize(m_bounds)) {
- m_skipsDraw = true;
- return;
- }
-
void* pixels = 0;
- IntRect dirtyRect(m_dirtyRect);
+ IntRect dirtyRect;
+ IntRect updateRect;
IntSize requiredTextureSize;
IntSize bitmapSize;
- requiredTextureSize = m_bounds;
- IntRect boundsRect(IntPoint(0, 0), m_bounds);
-
- // If the texture needs to be reallocated then we must redraw the entire
- // contents of the layer.
- if (requiredTextureSize != m_allocatedTextureSize)
- dirtyRect = boundsRect;
- else {
- // Clip the dirtyRect to the size of the layer to avoid drawing outside
- // the bounds of the backing texture.
- dirtyRect.intersect(boundsRect);
+ // FIXME: Remove this test when tiled layers are implemented.
+ if (requiresClippedUpdateRect()) {
+ // A layer with 3D transforms could require an arbitrarily large number
+ // of texels to be repainted, so ignore these layers until tiling is
+ // implemented.
+ if (!drawTransform().isIdentityOrTranslation()) {
+ m_skipsDraw = true;
+ return;
+ }
+
+ calculateClippedUpdateRect(dirtyRect, m_largeLayerDrawRect);
+ if (!layerRenderer()->checkTextureSize(m_largeLayerDrawRect.size())) {
+ m_skipsDraw = true;
+ return;
+ }
+ if (m_largeLayerDirtyRect == dirtyRect)
+ return;
+
+ m_largeLayerDirtyRect = dirtyRect;
+ requiredTextureSize = dirtyRect.size();
+ updateRect = IntRect(IntPoint(0, 0), dirtyRect.size());
+ } else {
+ dirtyRect = IntRect(m_dirtyRect);
+ IntRect boundsRect(IntPoint(0, 0), m_bounds);
+ requiredTextureSize = m_bounds;
+ // If the texture needs to be reallocated then we must redraw the entire
+ // contents of the layer.
+ if (requiredTextureSize != m_allocatedTextureSize)
+ dirtyRect = boundsRect;
+ else {
+ // Clip the dirtyRect to the size of the layer to avoid drawing
+ // outside the bounds of the backing texture.
+ dirtyRect.intersect(boundsRect);
+ }
+ updateRect = dirtyRect;
}
#if PLATFORM(SKIA)
@@ -228,7 +271,6 @@ void ContentLayerChromium::updateContents()
CGContextScaleCTM(contextCG.get(), 1, -1);
GraphicsContext graphicsContext(contextCG.get());
- LocalCurrentGraphicsContext scopedNSGraphicsContext(&graphicsContext);
// Translate the graphics context into the coordinate system of the dirty rect.
graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y());
@@ -246,7 +288,7 @@ void ContentLayerChromium::updateContents()
textureId = layerRenderer()->createLayerTexture();
if (pixels)
- updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId);
+ updateTextureRect(pixels, bitmapSize, requiredTextureSize, updateRect, textureId);
}
void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId)
@@ -272,7 +314,8 @@ void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& bitmap
}
m_dirtyRect.setSize(FloatSize());
- m_contentsDirty = false;
+ // Large layers always stay dirty, because they need to update when the content rect changes.
+ m_contentsDirty = requiresClippedUpdateRect();
}
void ContentLayerChromium::draw()
@@ -288,9 +331,21 @@ void ContentLayerChromium::draw()
GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTexture));
layerRenderer()->useShader(sv->contentShaderProgram());
GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0));
- drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
- bounds().width(), bounds().height(), drawOpacity(),
- sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+
+ if (requiresClippedUpdateRect()) {
+ float m43 = drawTransform().m43();
+ TransformationMatrix transform;
+ transform.translate3d(m_largeLayerDrawRect.center().x(), m_largeLayerDrawRect.center().y(), m43);
+ drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
+ transform, m_largeLayerDrawRect.width(),
+ m_largeLayerDrawRect.height(), drawOpacity(),
+ sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+ } else {
+ drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
+ drawTransform(), m_bounds.width(), m_bounds.height(),
+ drawOpacity(), sv->shaderMatrixLocation(),
+ sv->shaderAlphaLocation());
+ }
}
}
diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/WebCore/platform/graphics/chromium/ContentLayerChromium.h
index 412ba06..32c2c49 100644
--- a/WebCore/platform/graphics/chromium/ContentLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -49,7 +49,6 @@ public:
virtual void updateContents();
virtual void draw();
virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); }
- virtual void setLayerRenderer(LayerRendererChromium*);
// Stores values that are shared between instances of this class that are
// associated with the same LayerRendererChromium (and hence the same GL
@@ -80,12 +79,17 @@ protected:
void updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize,
const IntRect& updateRect, unsigned textureId);
- void cleanupResources();
+ virtual void cleanupResources();
+ bool requiresClippedUpdateRect() const;
unsigned m_contentsTexture;
IntSize m_allocatedTextureSize;
bool m_skipsDraw;
+private:
+ void calculateClippedUpdateRect(IntRect& dirtyRect, IntRect& drawRect) const;
+ IntRect m_largeLayerDrawRect;
+ IntRect m_largeLayerDirtyRect;
};
}
diff --git a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
index 9ce0efe..b54a427 100644
--- a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
+++ b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -48,7 +48,7 @@ struct DrawingBufferInternal {
#endif
};
-static unsigned generateColorTexture(SharedGraphicsContext3D* context, const IntSize& size)
+static unsigned generateColorTexture(GraphicsContext3D* context, const IntSize& size)
{
unsigned offscreenColorTexture = context->createTexture();
if (!offscreenColorTexture)
@@ -66,13 +66,13 @@ static unsigned generateColorTexture(SharedGraphicsContext3D* context, const Int
}
-DrawingBuffer::DrawingBuffer(SharedGraphicsContext3D* context, const IntSize& size, unsigned framebuffer)
+DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size)
: m_context(context)
, m_size(size)
- , m_framebuffer(framebuffer)
+ , m_fbo(context->createFramebuffer())
, m_internal(new DrawingBufferInternal)
{
- context->bindFramebuffer(framebuffer);
+ context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
m_internal->offscreenColorTexture = generateColorTexture(context, size);
}
@@ -82,14 +82,22 @@ DrawingBuffer::~DrawingBuffer()
if (m_internal->platformLayer)
m_internal->platformLayer->setDrawingBuffer(0);
#endif
- m_context->bindFramebuffer(m_framebuffer);
+
+ if (!m_context)
+ return;
+
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
m_context->deleteTexture(m_internal->offscreenColorTexture);
- m_context->deleteFramebuffer(m_framebuffer);
+
+ clear();
}
#if USE(ACCELERATED_COMPOSITING)
void DrawingBuffer::publishToPlatformLayer()
{
+ if (!m_context)
+ return;
+
if (m_callback)
m_callback->willPublish();
unsigned parentTexture = m_internal->platformLayer->textureId();
@@ -106,6 +114,9 @@ void DrawingBuffer::publishToPlatformLayer()
void DrawingBuffer::reset(const IntSize& newSize)
{
+ if (!m_context)
+ return;
+
if (m_size == newSize)
return;
m_size = newSize;
diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp
index a242523..f38273c 100644
--- a/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -161,62 +161,23 @@ static int truncateFixedPointToInteger(HB_Fixed value)
// can call |reset| to start over again.
class TextRunWalker {
public:
- TextRunWalker(const TextRun& run, unsigned startingX, const Font* font)
- : m_font(font)
- , m_startingX(startingX)
- , m_offsetX(m_startingX)
- , m_run(getTextRun(run))
- , m_iterateBackwards(m_run.rtl())
- , m_wordSpacingAdjustment(0)
- , m_padding(0)
- , m_padError(0)
- {
- // Do not use |run| inside this constructor. Use |m_run| instead.
-
- memset(&m_item, 0, sizeof(m_item));
- // We cannot know, ahead of time, how many glyphs a given script run
- // will produce. We take a guess that script runs will not produce more
- // than twice as many glyphs as there are code points plus a bit of
- // padding and fallback if we find that we are wrong.
- createGlyphArrays((m_run.length() + 2) * 2);
-
- m_item.log_clusters = new unsigned short[m_run.length()];
-
- m_item.face = 0;
- m_item.font = allocHarfbuzzFont();
-
- m_item.item.bidiLevel = m_run.rtl();
-
- int length = m_run.length();
- m_item.stringLength = length;
-
- if (!m_item.item.bidiLevel)
- m_item.string = m_run.characters();
- else {
- // Assume mirrored character is in the same Unicode multilingual plane as the original one.
- UChar* string = new UChar[length];
- mirrorCharacters(string, m_run.characters(), length);
- m_item.string = string;
- }
-
- reset();
- }
+ TextRunWalker(const TextRun&, unsigned, const Font*);
+ ~TextRunWalker();
- ~TextRunWalker()
- {
- fastFree(m_item.font);
- deleteGlyphArrays();
- delete[] m_item.log_clusters;
- if (m_item.item.bidiLevel)
- delete[] m_item.string;
- }
+ bool isWordBreak(unsigned, bool);
+ // setPadding sets a number of pixels to be distributed across the TextRun.
+ // WebKit uses this to justify text.
+ void setPadding(int);
+ void reset();
+ void setBackwardsIteration(bool);
+ // Advance to the next script run, returning false when the end of the
+ // TextRun has been reached.
+ bool nextScriptRun();
+ float widthOfFullRun();
// setWordSpacingAdjustment sets a delta (in pixels) which is applied at
// each word break in the TextRun.
- void setWordSpacingAdjustment(int wordSpacingAdjustment)
- {
- m_wordSpacingAdjustment = wordSpacingAdjustment;
- }
+ void setWordSpacingAdjustment(int wordSpacingAdjustment) { m_wordSpacingAdjustment = wordSpacingAdjustment; }
// setLetterSpacingAdjustment sets an additional number of pixels that is
// added to the advance after each output cluster. This matches the behaviour
@@ -224,393 +185,431 @@ public:
//
// (NOTE: currently does nothing because I don't know how to get the
// cluster information from Harfbuzz.)
- void setLetterSpacingAdjustment(int letterSpacingAdjustment)
- {
- m_letterSpacing = letterSpacingAdjustment;
- }
-
- bool isWordBreak(unsigned i, bool isRTL)
- {
- if (!isRTL)
- return i && isCodepointSpace(m_item.string[i]) && !isCodepointSpace(m_item.string[i - 1]);
- return i != m_item.stringLength - 1 && isCodepointSpace(m_item.string[i]) && !isCodepointSpace(m_item.string[i + 1]);
- }
-
- // setPadding sets a number of pixels to be distributed across the TextRun.
- // WebKit uses this to justify text.
- void setPadding(int padding)
- {
- m_padding = padding;
- if (!m_padding)
- return;
-
- // If we have padding to distribute, then we try to give an equal
- // amount to each space. The last space gets the smaller amount, if
- // any.
- unsigned numWordBreaks = 0;
- bool isRTL = m_iterateBackwards;
-
- for (unsigned i = 0; i < m_item.stringLength; i++) {
- if (isWordBreak(i, isRTL))
- numWordBreaks++;
- }
-
- if (numWordBreaks)
- m_padPerWordBreak = m_padding / numWordBreaks;
- else
- m_padPerWordBreak = 0;
- }
-
- void reset()
- {
- if (m_iterateBackwards)
- m_indexOfNextScriptRun = m_run.length() - 1;
- else
- m_indexOfNextScriptRun = 0;
- m_offsetX = m_startingX;
- }
+ void setLetterSpacingAdjustment(int letterSpacingAdjustment) { m_letterSpacing = letterSpacingAdjustment; }
// Set the x offset for the next script run. This affects the values in
// |xPositions|
- void setXOffsetToZero()
- {
- m_offsetX = 0;
- }
-
- bool rtl() const
- {
- return m_run.rtl();
- }
-
- void setBackwardsIteration(bool isBackwards)
- {
- m_iterateBackwards = isBackwards;
- reset();
- }
-
- // Advance to the next script run, returning false when the end of the
- // TextRun has been reached.
- bool nextScriptRun()
- {
- if (m_iterateBackwards) {
- // In right-to-left mode we need to render the shaped glyph backwards and
- // also render the script runs themselves backwards. So given a TextRun:
- // AAAAAAACTTTTTTT (A = Arabic, C = Common, T = Thai)
- // we render:
- // TTTTTTCAAAAAAA
- // (and the glyphs in each A, C and T section are backwards too)
- if (!hb_utf16_script_run_prev(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
- return false;
- } else {
- if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
- return false;
-
- // It is actually wrong to consider script runs at all in this code.
- // Other WebKit code (e.g. Mac) segments complex text just by finding
- // the longest span of text covered by a single font.
- // But we currently need to call hb_utf16_script_run_next anyway to fill
- // in the harfbuzz data structures to e.g. pick the correct script's shaper.
- // So we allow that to run first, then do a second pass over the range it
- // found and take the largest subregion that stays within a single font.
- const FontData* glyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
- unsigned endOfRun;
- for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) {
- const FontData* nextGlyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false, false).fontData;
- if (nextGlyphData != glyphData)
- break;
- }
- m_item.item.length = endOfRun;
- m_indexOfNextScriptRun = m_item.item.pos + endOfRun;
- }
-
- setupFontForScriptRun();
- shapeGlyphs();
- setGlyphXPositions(rtl());
-
- return true;
- }
-
- const uint16_t* glyphs() const
- {
- return m_glyphs16;
- }
+ void setXOffsetToZero() { m_offsetX = 0; }
+ bool rtl() const { return m_run.rtl(); }
+ const uint16_t* glyphs() const { return m_glyphs16; }
// Return the length of the array returned by |glyphs|
- const unsigned length() const
- {
- return m_item.num_glyphs;
- }
+ const unsigned length() const { return m_item.num_glyphs; }
// Return the x offset for each of the glyphs. Note that this is translated
// by the current x offset and that the x offset is updated for each script
// run.
- const SkScalar* xPositions() const
- {
- return m_xPositions;
- }
+ const SkScalar* xPositions() const { return m_xPositions; }
// Get the advances (widths) for each glyph.
- const HB_Fixed* advances() const
- {
- return m_item.advances;
- }
+ const HB_Fixed* advances() const { return m_item.advances; }
// Return the width (in px) of the current script run.
- const unsigned width() const
- {
- return m_pixelWidth;
- }
+ const unsigned width() const { return m_pixelWidth; }
// Return the cluster log for the current script run. For example:
// script run: f i a n c é (fi gets ligatured)
// log clutrs: 0 0 1 2 3 4
// So, for each input code point, the log tells you which output glyph was
// generated for it.
- const unsigned short* logClusters() const
- {
- return m_item.log_clusters;
- }
+ const unsigned short* logClusters() const { return m_item.log_clusters; }
// return the number of code points in the current script run
- const unsigned numCodePoints() const
- {
- return m_numCodePoints;
- }
+ const unsigned numCodePoints() const { return m_numCodePoints; }
- const FontPlatformData* fontPlatformDataForScriptRun()
- {
- return reinterpret_cast<FontPlatformData*>(m_item.font->userData);
- }
+ const FontPlatformData* fontPlatformDataForScriptRun() { return reinterpret_cast<FontPlatformData*>(m_item.font->userData); }
- float widthOfFullRun()
- {
- float widthSum = 0;
- while (nextScriptRun())
- widthSum += width();
+private:
+ const TextRun& getTextRun(const TextRun&);
+ const TextRun& getNormalizedTextRun(const TextRun&);
+ void setupFontForScriptRun();
+ HB_FontRec* allocHarfbuzzFont();
+ void deleteGlyphArrays();
+ void createGlyphArrays(int);
+ void resetGlyphArrays();
+ void shapeGlyphs();
+ void setGlyphXPositions(bool);
+ void mirrorCharacters(UChar*, const UChar*, int) const;
+
+ // This matches the logic in RenderBlock::findNextLineBreak
+ static bool isCodepointSpace(HB_UChar16 c) { return c == ' ' || c == '\t'; }
- return widthSum;
- }
+ const Font* const m_font;
+ HB_ShaperItem m_item;
+ uint16_t* m_glyphs16; // A vector of 16-bit glyph ids.
+ SkScalar* m_xPositions; // A vector of x positions for each glyph.
+ ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|.
+ const unsigned m_startingX; // Offset in pixels of the first script run.
+ unsigned m_offsetX; // Offset in pixels to the start of the next script run.
+ unsigned m_pixelWidth; // Width (in px) of the current script run.
+ unsigned m_numCodePoints; // Code points in current script run.
+ unsigned m_glyphsArrayCapacity; // Current size of all the Harfbuzz arrays.
-private:
- const TextRun& getTextRun(const TextRun& originalRun)
- {
- // Normalize the text run in two ways:
- // 1) Convert the |originalRun| to NFC normalized form if combining diacritical marks
- // (U+0300..) are used in the run. This conversion is necessary since most OpenType
- // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in
- // their GSUB tables.
- //
- // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since
- // the API returns FALSE (= not normalized) for complex runs that don't require NFC
- // normalization (e.g., Arabic text). Unless the run contains the diacritical marks,
- // Harfbuzz will do the same thing for us using the GSUB table.
- // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs
- // for characters like '\n' otherwise.
- for (int i = 0; i < originalRun.length(); ++i) {
- UChar ch = originalRun[i];
- UBlockCode block = ::ublock_getCode(ch);
- if (block == UBLOCK_COMBINING_DIACRITICAL_MARKS || (Font::treatAsSpace(ch) && ch != ' ')) {
- return getNormalizedTextRun(originalRun);
- }
- }
- return originalRun;
- }
+ OwnPtr<TextRun> m_normalizedRun;
+ OwnArrayPtr<UChar> m_normalizedBuffer; // A buffer for normalized run.
+ const TextRun& m_run;
+ bool m_iterateBackwards;
+ int m_wordSpacingAdjustment; // delta adjustment (pixels) for each word break.
+ float m_padding; // pixels to be distributed over the line at word breaks.
+ float m_padPerWordBreak; // pixels to be added to each word break.
+ float m_padError; // |m_padPerWordBreak| might have a fractional component.
+ // Since we only add a whole number of padding pixels at
+ // each word break we accumulate error. This is the
+ // number of pixels that we are behind so far.
+ unsigned m_letterSpacing; // pixels to be added after each glyph.
+};
- const TextRun& getNormalizedTextRun(const TextRun& originalRun)
- {
- icu::UnicodeString normalizedString;
- UErrorCode error = U_ZERO_ERROR;
- icu::Normalizer::normalize(icu::UnicodeString(originalRun.characters(), originalRun.length()), UNORM_NFC, 0 /* no options */, normalizedString, error);
- if (U_FAILURE(error))
- return originalRun;
-
- m_normalizedBuffer.set(new UChar[normalizedString.length() + 1]);
- normalizedString.extract(m_normalizedBuffer.get(), normalizedString.length() + 1, error);
- ASSERT(U_SUCCESS(error));
-
- for (int i = 0; i < normalizedString.length(); ++i) {
- if (Font::treatAsSpace(m_normalizedBuffer[i]))
- m_normalizedBuffer[i] = ' ';
- }
- m_normalizedRun.set(new TextRun(originalRun));
- m_normalizedRun->setText(m_normalizedBuffer.get(), normalizedString.length());
- return *m_normalizedRun;
- }
+TextRunWalker::TextRunWalker(const TextRun& run, unsigned startingX, const Font* font)
+ : m_font(font)
+ , m_startingX(startingX)
+ , m_offsetX(m_startingX)
+ , m_run(getTextRun(run))
+ , m_iterateBackwards(m_run.rtl())
+ , m_wordSpacingAdjustment(0)
+ , m_padding(0)
+ , m_padError(0)
+{
+ // Do not use |run| inside this constructor. Use |m_run| instead.
- void setupFontForScriptRun()
- {
- const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
- const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData();
- m_item.face = platformData.harfbuzzFace();
- void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData);
- m_item.font->userData = opaquePlatformData;
- }
+ memset(&m_item, 0, sizeof(m_item));
+ // We cannot know, ahead of time, how many glyphs a given script run
+ // will produce. We take a guess that script runs will not produce more
+ // than twice as many glyphs as there are code points plus a bit of
+ // padding and fallback if we find that we are wrong.
+ createGlyphArrays((m_run.length() + 2) * 2);
- HB_FontRec* allocHarfbuzzFont()
- {
- HB_FontRec* font = reinterpret_cast<HB_FontRec*>(fastMalloc(sizeof(HB_FontRec)));
- memset(font, 0, sizeof(HB_FontRec));
- font->klass = &harfbuzzSkiaClass;
- font->userData = 0;
- // The values which harfbuzzSkiaClass returns are already scaled to
- // pixel units, so we just set all these to one to disable further
- // scaling.
- font->x_ppem = 1;
- font->y_ppem = 1;
- font->x_scale = 1;
- font->y_scale = 1;
-
- return font;
- }
+ m_item.log_clusters = new unsigned short[m_run.length()];
+
+ m_item.face = 0;
+ m_item.font = allocHarfbuzzFont();
+
+ m_item.item.bidiLevel = m_run.rtl();
- void deleteGlyphArrays()
- {
- delete[] m_item.glyphs;
- delete[] m_item.attributes;
- delete[] m_item.advances;
- delete[] m_item.offsets;
- delete[] m_glyphs16;
- delete[] m_xPositions;
+ int length = m_run.length();
+ m_item.stringLength = length;
+
+ if (!m_item.item.bidiLevel)
+ m_item.string = m_run.characters();
+ else {
+ // Assume mirrored character is in the same Unicode multilingual plane as the original one.
+ UChar* string = new UChar[length];
+ mirrorCharacters(string, m_run.characters(), length);
+ m_item.string = string;
}
- void createGlyphArrays(int size)
- {
- m_item.glyphs = new HB_Glyph[size];
- memset(m_item.glyphs, 0, size * sizeof(HB_Glyph));
- m_item.attributes = new HB_GlyphAttributes[size];
- memset(m_item.attributes, 0, size * sizeof(HB_GlyphAttributes));
- m_item.advances = new HB_Fixed[size];
- memset(m_item.advances, 0, size * sizeof(HB_Fixed));
- m_item.offsets = new HB_FixedPoint[size];
- memset(m_item.offsets, 0, size * sizeof(HB_FixedPoint));
-
- m_glyphs16 = new uint16_t[size];
- m_xPositions = new SkScalar[size];
-
- m_item.num_glyphs = size;
+ reset();
+}
+
+TextRunWalker::~TextRunWalker()
+{
+ fastFree(m_item.font);
+ deleteGlyphArrays();
+ delete[] m_item.log_clusters;
+ if (m_item.item.bidiLevel)
+ delete[] m_item.string;
+}
+
+bool TextRunWalker::isWordBreak(unsigned index, bool isRTL)
+{
+ if (!isRTL)
+ return index && isCodepointSpace(m_item.string[index]) && !isCodepointSpace(m_item.string[index - 1]);
+ return index != m_item.stringLength - 1 && isCodepointSpace(m_item.string[index]) && !isCodepointSpace(m_item.string[index + 1]);
+}
+
+// setPadding sets a number of pixels to be distributed across the TextRun.
+// WebKit uses this to justify text.
+void TextRunWalker::setPadding(int padding)
+{
+ m_padding = padding;
+ if (!m_padding)
+ return;
+
+ // If we have padding to distribute, then we try to give an equal
+ // amount to each space. The last space gets the smaller amount, if
+ // any.
+ unsigned numWordBreaks = 0;
+ bool isRTL = m_iterateBackwards;
+
+ for (unsigned i = 0; i < m_item.stringLength; i++) {
+ if (isWordBreak(i, isRTL))
+ numWordBreaks++;
}
- void shapeGlyphs()
- {
- for (;;) {
- if (HB_ShapeItem(&m_item))
- break;
+ if (numWordBreaks)
+ m_padPerWordBreak = m_padding / numWordBreaks;
+ else
+ m_padPerWordBreak = 0;
+}
+
+void TextRunWalker::reset()
+{
+ if (m_iterateBackwards)
+ m_indexOfNextScriptRun = m_run.length() - 1;
+ else
+ m_indexOfNextScriptRun = 0;
+ m_offsetX = m_startingX;
+}
- // We overflowed our arrays. Resize and retry.
- // HB_ShapeItem fills in m_item.num_glyphs with the needed size.
- deleteGlyphArrays();
- // The |+ 1| here is a workaround for a bug in Harfbuzz: the Khmer
- // shaper (at least) can fail because of insufficient glyph buffers
- // and request 0 additional glyphs: throwing us into an infinite
- // loop.
- createGlyphArrays(m_item.num_glyphs + 1);
+void TextRunWalker::setBackwardsIteration(bool isBackwards)
+{
+ m_iterateBackwards = isBackwards;
+ reset();
+}
+
+// Advance to the next script run, returning false when the end of the
+// TextRun has been reached.
+bool TextRunWalker::nextScriptRun()
+{
+ if (m_iterateBackwards) {
+ // In right-to-left mode we need to render the shaped glyph backwards and
+ // also render the script runs themselves backwards. So given a TextRun:
+ // AAAAAAACTTTTTTT (A = Arabic, C = Common, T = Thai)
+ // we render:
+ // TTTTTTCAAAAAAA
+ // (and the glyphs in each A, C and T section are backwards too)
+ if (!hb_utf16_script_run_prev(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
+ return false;
+ } else {
+ if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
+ return false;
+
+ // It is actually wrong to consider script runs at all in this code.
+ // Other WebKit code (e.g. Mac) segments complex text just by finding
+ // the longest span of text covered by a single font.
+ // But we currently need to call hb_utf16_script_run_next anyway to fill
+ // in the harfbuzz data structures to e.g. pick the correct script's shaper.
+ // So we allow that to run first, then do a second pass over the range it
+ // found and take the largest subregion that stays within a single font.
+ const FontData* glyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
+ unsigned endOfRun;
+ for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) {
+ const FontData* nextGlyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false, false).fontData;
+ if (nextGlyphData != glyphData)
+ break;
}
+ m_item.item.length = endOfRun;
+ m_indexOfNextScriptRun = m_item.item.pos + endOfRun;
}
- void setGlyphXPositions(bool isRTL)
- {
- double position = 0;
- // logClustersIndex indexes logClusters for the first (or last when
- // RTL) codepoint of the current glyph. Each time we advance a glyph,
- // we skip over all the codepoints that contributed to the current
- // glyph.
- unsigned logClustersIndex = isRTL ? m_item.num_glyphs - 1 : 0;
-
- for (unsigned iter = 0; iter < m_item.num_glyphs; ++iter) {
- // Glyphs are stored in logical order, but for layout purposes we
- // always go left to right.
- int i = isRTL ? m_item.num_glyphs - iter - 1 : iter;
-
- m_glyphs16[i] = m_item.glyphs[i];
- double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
- m_xPositions[i] = m_offsetX + position + offsetX;
-
- double advance = truncateFixedPointToInteger(m_item.advances[i]);
- // The first half of the conjuction works around the case where
- // output glyphs aren't associated with any codepoints by the
- // clusters log.
- if (logClustersIndex < m_item.item.length
- && isWordBreak(m_item.item.pos + logClustersIndex, isRTL)) {
- advance += m_wordSpacingAdjustment;
-
- if (m_padding > 0) {
- unsigned toPad = roundf(m_padPerWordBreak + m_padError);
- m_padError += m_padPerWordBreak - toPad;
-
- if (m_padding < toPad)
- toPad = m_padding;
- m_padding -= toPad;
- advance += toPad;
- }
- }
+ setupFontForScriptRun();
+ shapeGlyphs();
+ setGlyphXPositions(rtl());
- // We would like to add m_letterSpacing after each cluster, but I
- // don't know where the cluster information is. This is typically
- // fine for Roman languages, but breaks more complex languages
- // terribly.
- // advance += m_letterSpacing;
-
- if (isRTL) {
- while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i)
- logClustersIndex--;
- } else {
- while (logClustersIndex < m_item.item.length && logClusters()[logClustersIndex] == i)
- logClustersIndex++;
- }
+ return true;
+}
- position += advance;
- }
+float TextRunWalker::widthOfFullRun()
+{
+ float widthSum = 0;
+ while (nextScriptRun())
+ widthSum += width();
- m_pixelWidth = position;
- m_offsetX += m_pixelWidth;
+ return widthSum;
+}
+
+const TextRun& TextRunWalker::getTextRun(const TextRun& originalRun)
+{
+ // Normalize the text run in two ways:
+ // 1) Convert the |originalRun| to NFC normalized form if combining diacritical marks
+ // (U+0300..) are used in the run. This conversion is necessary since most OpenType
+ // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in
+ // their GSUB tables.
+ //
+ // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since
+ // the API returns FALSE (= not normalized) for complex runs that don't require NFC
+ // normalization (e.g., Arabic text). Unless the run contains the diacritical marks,
+ // Harfbuzz will do the same thing for us using the GSUB table.
+ // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs
+ // for characters like '\n' otherwise.
+ for (int i = 0; i < originalRun.length(); ++i) {
+ UChar ch = originalRun[i];
+ UBlockCode block = ::ublock_getCode(ch);
+ if (block == UBLOCK_COMBINING_DIACRITICAL_MARKS || (Font::treatAsSpace(ch) && ch != ' '))
+ return getNormalizedTextRun(originalRun);
+ }
+ return originalRun;
+}
+
+const TextRun& TextRunWalker::getNormalizedTextRun(const TextRun& originalRun)
+{
+ icu::UnicodeString normalizedString;
+ UErrorCode error = U_ZERO_ERROR;
+ icu::Normalizer::normalize(icu::UnicodeString(originalRun.characters(), originalRun.length()), UNORM_NFC, 0 /* no options */, normalizedString, error);
+ if (U_FAILURE(error))
+ return originalRun;
+
+ m_normalizedBuffer.set(new UChar[normalizedString.length() + 1]);
+ normalizedString.extract(m_normalizedBuffer.get(), normalizedString.length() + 1, error);
+ ASSERT(U_SUCCESS(error));
+
+ for (int i = 0; i < normalizedString.length(); ++i) {
+ if (Font::treatAsSpace(m_normalizedBuffer[i]))
+ m_normalizedBuffer[i] = ' ';
}
- static bool isCodepointSpace(HB_UChar16 c)
- {
- // This matches the logic in RenderBlock::findNextLineBreak
- return c == ' ' || c == '\t';
+ m_normalizedRun.set(new TextRun(originalRun));
+ m_normalizedRun->setText(m_normalizedBuffer.get(), normalizedString.length());
+ return *m_normalizedRun;
+}
+
+void TextRunWalker::setupFontForScriptRun()
+{
+ const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
+ const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData();
+ m_item.face = platformData.harfbuzzFace();
+ void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData);
+ m_item.font->userData = opaquePlatformData;
+}
+
+HB_FontRec* TextRunWalker::allocHarfbuzzFont()
+{
+ HB_FontRec* font = reinterpret_cast<HB_FontRec*>(fastMalloc(sizeof(HB_FontRec)));
+ memset(font, 0, sizeof(HB_FontRec));
+ font->klass = &harfbuzzSkiaClass;
+ font->userData = 0;
+ // The values which harfbuzzSkiaClass returns are already scaled to
+ // pixel units, so we just set all these to one to disable further
+ // scaling.
+ font->x_ppem = 1;
+ font->y_ppem = 1;
+ font->x_scale = 1;
+ font->y_scale = 1;
+
+ return font;
+}
+
+void TextRunWalker::deleteGlyphArrays()
+{
+ delete[] m_item.glyphs;
+ delete[] m_item.attributes;
+ delete[] m_item.advances;
+ delete[] m_item.offsets;
+ delete[] m_glyphs16;
+ delete[] m_xPositions;
+}
+
+void TextRunWalker::createGlyphArrays(int size)
+{
+ m_item.glyphs = new HB_Glyph[size];
+ m_item.attributes = new HB_GlyphAttributes[size];
+ m_item.advances = new HB_Fixed[size];
+ m_item.offsets = new HB_FixedPoint[size];
+
+ m_glyphs16 = new uint16_t[size];
+ m_xPositions = new SkScalar[size];
+
+ m_item.num_glyphs = size;
+ m_glyphsArrayCapacity = size; // Save the GlyphArrays size.
+ resetGlyphArrays();
+}
+
+void TextRunWalker::resetGlyphArrays()
+{
+ int size = m_item.num_glyphs;
+ // All the types here don't have pointers. It is safe to reset to
+ // zero unless Harfbuzz breaks the compatibility in the future.
+ memset(m_item.glyphs, 0, size * sizeof(HB_Glyph));
+ memset(m_item.attributes, 0, size * sizeof(HB_GlyphAttributes));
+ memset(m_item.advances, 0, size * sizeof(HB_Fixed));
+ memset(m_item.offsets, 0, size * sizeof(HB_FixedPoint));
+ memset(m_glyphs16, 0, size * sizeof(uint16_t));
+ memset(m_xPositions, 0, size * sizeof(SkScalar));
+}
+
+void TextRunWalker::shapeGlyphs()
+{
+ // HB_ShapeItem() resets m_item.num_glyphs. If the previous call to
+ // HB_ShapeItem() used less space than was available, the capacity of
+ // the array may be larger than the current value of m_item.num_glyphs.
+ // So, we need to reset the num_glyphs to the capacity of the array.
+ m_item.num_glyphs = m_glyphsArrayCapacity;
+ resetGlyphArrays();
+ while (!HB_ShapeItem(&m_item)) {
+ // We overflowed our arrays. Resize and retry.
+ // HB_ShapeItem fills in m_item.num_glyphs with the needed size.
+ deleteGlyphArrays();
+ // The |+ 1| here is a workaround for a bug in Harfbuzz: the Khmer
+ // shaper (at least) can fail because of insufficient glyph buffers
+ // and request 0 additional glyphs: throwing us into an infinite
+ // loop.
+ createGlyphArrays(m_item.num_glyphs + 1);
}
+}
+
+void TextRunWalker::setGlyphXPositions(bool isRTL)
+{
+ double position = 0;
+ // logClustersIndex indexes logClusters for the first (or last when
+ // RTL) codepoint of the current glyph. Each time we advance a glyph,
+ // we skip over all the codepoints that contributed to the current
+ // glyph.
+ unsigned logClustersIndex = isRTL ? m_item.num_glyphs - 1 : 0;
+
+ for (unsigned iter = 0; iter < m_item.num_glyphs; ++iter) {
+ // Glyphs are stored in logical order, but for layout purposes we
+ // always go left to right.
+ int i = isRTL ? m_item.num_glyphs - iter - 1 : iter;
+
+ m_glyphs16[i] = m_item.glyphs[i];
+ double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
+ m_xPositions[i] = m_offsetX + position + offsetX;
+
+ double advance = truncateFixedPointToInteger(m_item.advances[i]);
+ // The first half of the conjuction works around the case where
+ // output glyphs aren't associated with any codepoints by the
+ // clusters log.
+ if (logClustersIndex < m_item.item.length
+ && isWordBreak(m_item.item.pos + logClustersIndex, isRTL)) {
+ advance += m_wordSpacingAdjustment;
+
+ if (m_padding > 0) {
+ unsigned toPad = roundf(m_padPerWordBreak + m_padError);
+ m_padError += m_padPerWordBreak - toPad;
+
+ if (m_padding < toPad)
+ toPad = m_padding;
+ m_padding -= toPad;
+ advance += toPad;
+ }
+ }
- void mirrorCharacters(UChar* destination, const UChar* source, int length) const
- {
- int position = 0;
- bool error = false;
- // Iterate characters in source and mirror character if needed.
- while (position < length) {
- UChar32 character;
- int nextPosition = position;
- U16_NEXT(source, nextPosition, length, character);
- character = u_charMirror(character);
- U16_APPEND(destination, position, length, character, error);
- ASSERT(!error);
- position = nextPosition;
+ // We would like to add m_letterSpacing after each cluster, but I
+ // don't know where the cluster information is. This is typically
+ // fine for Roman languages, but breaks more complex languages
+ // terribly.
+ // advance += m_letterSpacing;
+
+ if (isRTL) {
+ while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i)
+ logClustersIndex--;
+ } else {
+ while (logClustersIndex < m_item.item.length && logClusters()[logClustersIndex] == i)
+ logClustersIndex++;
}
+
+ position += advance;
}
- const Font* const m_font;
- HB_ShaperItem m_item;
- uint16_t* m_glyphs16; // A vector of 16-bit glyph ids.
- SkScalar* m_xPositions; // A vector of x positions for each glyph.
- ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|.
- const unsigned m_startingX; // Offset in pixels of the first script run.
- unsigned m_offsetX; // Offset in pixels to the start of the next script run.
- unsigned m_pixelWidth; // Width (in px) of the current script run.
- unsigned m_numCodePoints; // Code points in current script run.
+ m_pixelWidth = position;
+ m_offsetX += m_pixelWidth;
+}
- OwnPtr<TextRun> m_normalizedRun;
- OwnArrayPtr<UChar> m_normalizedBuffer; // A buffer for normalized run.
- const TextRun& m_run;
- bool m_iterateBackwards;
- int m_wordSpacingAdjustment; // delta adjustment (pixels) for each word break.
- float m_padding; // pixels to be distributed over the line at word breaks.
- float m_padPerWordBreak; // pixels to be added to each word break.
- float m_padError; // |m_padPerWordBreak| might have a fractional component.
- // Since we only add a whole number of padding pixels at
- // each word break we accumulate error. This is the
- // number of pixels that we are behind so far.
- unsigned m_letterSpacing; // pixels to be added after each glyph.
-};
+void TextRunWalker::mirrorCharacters(UChar* destination, const UChar* source, int length) const
+{
+ int position = 0;
+ bool error = false;
+ // Iterate characters in source and mirror character if needed.
+ while (position < length) {
+ UChar32 character;
+ int nextPosition = position;
+ U16_NEXT(source, nextPosition, length, character);
+ character = u_charMirror(character);
+ U16_APPEND(destination, position, length, character, error);
+ ASSERT(!error);
+ position = nextPosition;
+ }
+}
static void setupForTextPainting(SkPaint* paint, SkColor color)
{
diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
index 46aecf4..697cf5e 100644
--- a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
+++ b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
@@ -97,7 +97,7 @@ void GLES2Canvas::clearRect(const FloatRect& rect)
} else {
save();
setCompositeOperation(CompositeClear);
- fillRect(rect, Color(RGBA32(0)), DeviceColorSpace);
+ fillRect(rect, Color(RGBA32(0)), ColorSpaceDeviceRGB);
restore();
}
}
@@ -120,7 +120,7 @@ void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace
void GLES2Canvas::fillRect(const FloatRect& rect)
{
- fillRect(rect, m_state->m_fillColor, DeviceColorSpace);
+ fillRect(rect, m_state->m_fillColor, ColorSpaceDeviceRGB);
}
void GLES2Canvas::setFillColor(const Color& color, ColorSpace colorSpace)
diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
index c97be82..afcc98c 100644
--- a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
@@ -75,6 +75,14 @@ void ImageLayerChromium::updateContents()
{
ASSERT(layerRenderer());
+ // FIXME: Remove this test when tiled layers are implemented.
+ if (requiresClippedUpdateRect()) {
+ // Use the base version of updateContents which draws a subset of the
+ // image to a bitmap, as the pixel contents can't be uploaded directly.
+ ContentLayerChromium::updateContents();
+ return;
+ }
+
void* pixels = 0;
IntSize requiredTextureSize;
IntSize bitmapSize;
@@ -136,12 +144,6 @@ void ImageLayerChromium::updateContents()
#else
#error "Need to implement for your platform."
#endif
- // FIXME: Remove this test when tiled layers are implemented.
- m_skipsDraw = false;
- if (!layerRenderer()->checkTextureSize(requiredTextureSize)) {
- m_skipsDraw = true;
- return;
- }
unsigned textureId = m_contentsTexture;
if (!textureId)
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp
index 5dba58d..79f18f0 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -174,6 +174,11 @@ LayerChromium::~LayerChromium()
void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer)
{
+ // If we're changing layer renderers then we need to free up any resources
+ // allocated by the old renderer.
+ if (layerRenderer() && layerRenderer() != renderer)
+ cleanupResources();
+
m_layerRenderer = renderer;
}
@@ -446,15 +451,12 @@ void LayerChromium::drawDebugBorder()
GLC(context, context->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
}
-const FloatRect LayerChromium::getDrawRect() const
+const IntRect LayerChromium::getDrawRect() const
{
// Form the matrix used by the shader to map the corners of the layer's
// bounds into the view space.
- TransformationMatrix renderMatrix = drawTransform();
- renderMatrix.scale3d(bounds().width(), bounds().height(), 1);
-
- FloatRect layerRect(-0.5, -0.5, 1, 1);
- FloatRect mappedRect = renderMatrix.mapRect(layerRect);
+ FloatRect layerRect(-0.5 * bounds().width(), -0.5 * bounds().height(), bounds().width(), bounds().height());
+ IntRect mappedRect = enclosingIntRect(drawTransform().mapRect(layerRect));
return mappedRect;
}
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h
index 0a66318..3956e28 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -156,7 +156,7 @@ public:
bool contentsDirty() { return m_contentsDirty; }
// Returns the rect containtaining this layer in the current view's coordinate system.
- const FloatRect getDrawRect() const;
+ const IntRect getDrawRect() const;
// These methods typically need to be overwritten by derived classes.
virtual bool drawsContent() { return false; }
@@ -202,6 +202,11 @@ protected:
GraphicsLayerChromium* m_owner;
LayerChromium(GraphicsLayerChromium* owner);
+ // This is called to clean up resources being held in the same context as
+ // layerRendererContext(). Subclasses should override this method if they
+ // hold context-dependent resources such as textures.
+ virtual void cleanupResources() { }
+
LayerRendererChromium* layerRenderer() const { return m_layerRenderer.get(); }
GraphicsContext3D* layerRendererContext() const;
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index c4031e5..e93e296 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -73,7 +73,7 @@ static inline bool compareLayerZ(const LayerChromium* a, const LayerChromium* b)
return transformA.m43() < transformB.m43();
}
-PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassOwnPtr<GraphicsContext3D> context)
+PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context)
{
if (!context)
return 0;
@@ -85,7 +85,7 @@ PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassOwnPtr<Graph
return layerRenderer.release();
}
-LayerRendererChromium::LayerRendererChromium(PassOwnPtr<GraphicsContext3D> context)
+LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context)
: m_rootLayerTextureId(0)
, m_rootLayerTextureWidth(0)
, m_rootLayerTextureHeight(0)
@@ -127,7 +127,6 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size)
// the old ones.
m_rootLayerCanvas = new skia::PlatformCanvas(size.width(), size.height(), false);
m_rootLayerSkiaContext = new PlatformContextSkia(m_rootLayerCanvas.get());
- m_rootLayerSkiaContext->setDrawingToImageBuffer(true);
m_rootLayerGraphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_rootLayerSkiaContext.get()));
#elif PLATFORM(CG)
// Release the previous CGBitmapContext before reallocating the backing store as a precaution.
@@ -204,6 +203,8 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons
GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE));
GLC(m_context, m_context->depthFunc(GraphicsContext3D::LEQUAL));
GLC(m_context, m_context->clearStencil(0));
+ // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType.
+ GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
if (m_scrollPosition == IntPoint(-1, -1)) {
m_scrollPosition = scrollPosition;
@@ -284,11 +285,15 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
const ContentLayerChromium::SharedValues* contentLayerValues = contentLayerSharedValues();
useShader(contentLayerValues->contentShaderProgram());
GLC(m_context, m_context->uniform1i(contentLayerValues->shaderSamplerLocation(), 0));
+ // Mask out writes to alpha channel: ClearType via Skia results in invalid
+ // zero alpha values on text glyphs. The root layer is always opaque.
+ GLC(m_context, m_context->colorMask(true, true, true, false));
TransformationMatrix layerMatrix;
layerMatrix.translate3d(visibleRect.width() * 0.5f, visibleRect.height() * 0.5f, 0);
LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, layerMatrix,
visibleRect.width(), visibleRect.height(), 1,
contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation());
+ GLC(m_context, m_context->colorMask(true, true, true, true));
// If culling is enabled then we will cull the backface.
GLC(m_context, m_context->cullFace(GraphicsContext3D::BACK));
@@ -302,8 +307,9 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
- // Set the rootVisibleRect --- used by subsequent drawLayers calls
+ // Set the root visible/content rects --- used by subsequent drawLayers calls.
m_rootVisibleRect = visibleRect;
+ m_rootContentRect = contentRect;
// Traverse the layer tree and update the layer transforms.
float opacity = 1;
@@ -315,7 +321,7 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
// Enable scissoring to avoid rendering composited layers over the scrollbars.
GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
- FloatRect scissorRect(contentRect);
+ IntRect scissorRect(contentRect);
// The scissorRect should not include the scroll offset.
scissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y());
@@ -328,9 +334,10 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
// Traverse the layer tree one more time to draw the layers.
for (size_t i = 0; i < sublayers.size(); i++)
- drawLayersRecursive(sublayers[i].get(), scissorRect);
+ drawLayersRecursive(sublayers[i].get());
GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
}
void LayerRendererChromium::finish()
@@ -494,14 +501,14 @@ void LayerRendererChromium::drawLayerIntoStencilBuffer(LayerChromium* layer, boo
}
// Recursively walk the layer tree and draw the layers.
-void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const FloatRect& scissorRect)
+void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer)
{
static bool depthTestEnabledForSubtree = false;
static int currentStencilValue = 0;
// Check if the layer falls within the visible bounds of the page.
- FloatRect layerRect = layer->getDrawRect();
- bool isLayerVisible = scissorRect.intersects(layerRect);
+ IntRect layerRect = layer->getDrawRect();
+ bool isLayerVisible = m_currentScissorRect.intersects(layerRect);
// Enable depth testing for this layer and all its descendants if preserves3D is set.
bool mustClearDepth = false;
@@ -520,15 +527,16 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const Floa
// FIXME: We should check here if the layer has descendants that draw content
// before we setup for clipping.
- FloatRect currentScissorRect = scissorRect;
+ IntRect previousScissorRect = m_currentScissorRect;
bool mustResetScissorRect = false;
bool didStencilDraw = false;
if (layer->masksToBounds()) {
// If the layer isn't rotated then we can use scissoring otherwise we need
// to clip using the stencil buffer.
if (layer->drawTransform().isIdentityOrTranslation()) {
+ IntRect currentScissorRect = previousScissorRect;
currentScissorRect.intersect(layerRect);
- if (currentScissorRect != scissorRect) {
+ if (currentScissorRect != previousScissorRect) {
scissorToRect(currentScissorRect);
mustResetScissorRect = true;
}
@@ -573,11 +581,11 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const Floa
std::stable_sort(sublayerList.begin(), sublayerList.end(), compareLayerZ);
for (i = 0; i < sublayerList.size(); i++)
- drawLayersRecursive(sublayerList[i], currentScissorRect);
+ drawLayersRecursive(sublayerList[i]);
} else {
const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
for (size_t i = 0; i < sublayers.size(); i++)
- drawLayersRecursive(sublayers[i].get(), currentScissorRect);
+ drawLayersRecursive(sublayers[i].get());
}
if (didStencilDraw) {
@@ -593,7 +601,7 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const Floa
}
if (mustResetScissorRect) {
- scissorToRect(scissorRect);
+ scissorToRect(previousScissorRect);
}
if (mustClearDepth) {
@@ -629,11 +637,12 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer)
// Sets the scissor region to the given rectangle. The coordinate system for the
// scissorRect has its origin at the top left corner of the current visible rect.
-void LayerRendererChromium::scissorToRect(const FloatRect& scissorRect)
+void LayerRendererChromium::scissorToRect(const IntRect& scissorRect)
{
// Compute the lower left corner of the scissor rect.
- float bottom = std::max((float)m_rootVisibleRect.height() - scissorRect.bottom(), 0.f);
+ int bottom = std::max(m_rootVisibleRect.height() - scissorRect.bottom(), 0);
GLC(m_context, m_context->scissor(scissorRect.x(), bottom, scissorRect.width(), scissorRect.height()));
+ m_currentScissorRect = scissorRect;
}
bool LayerRendererChromium::makeContextCurrent()
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
index b714584..6a06105 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -59,9 +59,8 @@ class GraphicsContext3D;
// Class that handles drawing of composited render layers using GL.
class LayerRendererChromium : public RefCounted<LayerRendererChromium> {
public:
- static PassRefPtr<LayerRendererChromium> create(PassOwnPtr<GraphicsContext3D> graphicsContext3D);
+ static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D> graphicsContext3D);
- LayerRendererChromium(PassOwnPtr<GraphicsContext3D> graphicsContext3D);
~LayerRendererChromium();
GraphicsContext3D* context();
@@ -93,6 +92,8 @@ public:
unsigned createLayerTexture();
void deleteLayerTexture(unsigned);
+ IntRect currentScissorRect() const { return m_currentScissorRect; }
+
static void debugGLCall(GraphicsContext3D*, const char* command, const char* file, int line);
const TransformationMatrix& projectionMatrix() const { return m_projectionMatrix; }
@@ -109,12 +110,15 @@ public:
void resizeOnscreenContent(const IntSize&);
IntSize rootLayerTextureSize() const { return IntSize(m_rootLayerTextureWidth, m_rootLayerTextureHeight); }
+ IntRect rootLayerContentRect() const { return m_rootContentRect; }
void getFramebufferPixels(void *pixels, const IntRect& rect);
private:
+ explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D> graphicsContext3D);
+
void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity);
- void drawLayersRecursive(LayerChromium*, const FloatRect& scissorRect);
+ void drawLayersRecursive(LayerChromium*);
void drawLayer(LayerChromium*);
@@ -122,7 +126,7 @@ private:
void drawLayerIntoStencilBuffer(LayerChromium*, bool decrement);
- void scissorToRect(const FloatRect&);
+ void scissorToRect(const IntRect&);
bool makeContextCurrent();
@@ -160,6 +164,8 @@ private:
IntSize m_rootLayerCanvasSize;
IntRect m_rootVisibleRect;
+ IntRect m_rootContentRect;
+ IntRect m_currentScissorRect;
int m_maxTextureSize;
@@ -174,7 +180,7 @@ private:
OwnPtr<CanvasLayerChromium::SharedValues> m_canvasLayerSharedValues;
OwnPtr<VideoLayerChromium::SharedValues> m_videoLayerSharedValues;
- OwnPtr<GraphicsContext3D> m_context;
+ RefPtr<GraphicsContext3D> m_context;
};
// Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL
diff --git a/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/WebCore/platform/graphics/chromium/TransparencyWin.cpp
index 47cc894..4dc2157 100644
--- a/WebCore/platform/graphics/chromium/TransparencyWin.cpp
+++ b/WebCore/platform/graphics/chromium/TransparencyWin.cpp
@@ -275,7 +275,7 @@ void TransparencyWin::setupLayerForWhiteLayer()
if (!m_validLayer)
return;
- m_drawContext->fillRect(IntRect(IntPoint(0, 0), m_layerSize), Color::white, DeviceColorSpace);
+ m_drawContext->fillRect(IntRect(IntPoint(0, 0), m_layerSize), Color::white, ColorSpaceDeviceRGB);
// Layer rect represents the part of the original layer.
}
diff --git a/WebCore/platform/graphics/chromium/VideoFrameChromium.h b/WebCore/platform/graphics/chromium/VideoFrameChromium.h
index 34e922b..e176b0c 100644
--- a/WebCore/platform/graphics/chromium/VideoFrameChromium.h
+++ b/WebCore/platform/graphics/chromium/VideoFrameChromium.h
@@ -63,10 +63,7 @@ public:
enum SurfaceType {
TypeSystemMemory,
- TypeOMXBufferHead,
- TypeEGLImage,
- TypeMFBuffer,
- TypeDirect3DSurface
+ TypeTexture,
};
virtual SurfaceType surfaceType() const = 0;
@@ -76,6 +73,7 @@ public:
virtual unsigned planes() const = 0;
virtual int stride(unsigned plane) const = 0;
virtual const void* data(unsigned plane) const = 0;
+ virtual unsigned texture(unsigned plane) const = 0;
virtual const IntSize requiredTextureSize(unsigned plane) const = 0;
};
diff --git a/WebCore/platform/graphics/chromium/VideoFrameProvider.h b/WebCore/platform/graphics/chromium/VideoFrameProvider.h
index f0bad08..c596f87 100644
--- a/WebCore/platform/graphics/chromium/VideoFrameProvider.h
+++ b/WebCore/platform/graphics/chromium/VideoFrameProvider.h
@@ -37,6 +37,8 @@ namespace WebCore {
class VideoFrameProvider {
public:
+ virtual ~VideoFrameProvider() { }
+
// This function returns a pointer to a VideoFrameChromium, which is
// the WebCore wrapper for a video frame in Chromium. getCurrentFrame()
// places a lock on the frame in Chromium. Calls to this method should
diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index 26641a9..46c73a1 100644
--- a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -175,16 +175,22 @@ VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameP
, m_skipsDraw(true)
, m_frameFormat(VideoFrameChromium::Invalid)
, m_provider(provider)
+ , m_currentFrame(0)
{
- for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) {
- m_textures[plane] = 0;
- m_textureSizes[plane] = IntSize();
- m_frameSizes[plane] = IntSize();
- }
+ resetFrameParameters();
}
VideoLayerChromium::~VideoLayerChromium()
{
+ cleanupResources();
+}
+
+void VideoLayerChromium::cleanupResources()
+{
+ releaseCurrentFrame();
+ if (!layerRenderer())
+ return;
+
GraphicsContext3D* context = layerRendererContext();
for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) {
if (m_textures[plane])
@@ -218,6 +224,14 @@ void VideoLayerChromium::updateContents()
return;
}
+ if (frame->surfaceType() == VideoFrameChromium::TypeTexture) {
+ releaseCurrentFrame();
+ saveCurrentFrame(frame);
+ m_dirtyRect.setSize(FloatSize());
+ m_contentsDirty = false;
+ return;
+ }
+
// Allocate textures for planes if they are not allocated already, or
// reallocate textures that are the wrong size for the frame.
GraphicsContext3D* context = layerRendererContext();
@@ -236,6 +250,7 @@ void VideoLayerChromium::updateContents()
m_dirtyRect.setSize(FloatSize());
m_contentsDirty = false;
+
m_provider->putCurrentFrame(frame);
}
@@ -319,6 +334,17 @@ void VideoLayerChromium::draw()
notImplemented();
break;
}
+ releaseCurrentFrame();
+}
+
+void VideoLayerChromium::releaseCurrentFrame()
+{
+ if (!m_currentFrame)
+ return;
+
+ m_provider->putCurrentFrame(m_currentFrame);
+ m_currentFrame = 0;
+ resetFrameParameters();
}
void VideoLayerChromium::drawYUV(const SharedValues* sv)
@@ -370,6 +396,26 @@ void VideoLayerChromium::drawRGBA(const SharedValues* sv)
sv->rgbaShaderMatrixLocation(), sv->rgbaAlphaLocation());
}
+void VideoLayerChromium::resetFrameParameters()
+{
+ for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) {
+ m_textures[plane] = 0;
+ m_textureSizes[plane] = IntSize();
+ m_frameSizes[plane] = IntSize();
+ }
+}
+
+void VideoLayerChromium::saveCurrentFrame(VideoFrameChromium* frame)
+{
+ ASSERT(!m_currentFrame);
+ m_currentFrame = frame;
+ for (unsigned plane = 0; plane < frame->planes(); plane++) {
+ m_textures[plane] = frame->texture(plane);
+ m_textureSizes[plane] = frame->requiredTextureSize(plane);
+ m_frameSizes[plane] = m_textureSizes[plane];
+ }
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/WebCore/platform/graphics/chromium/VideoLayerChromium.h
index 620d1a7..05b6578 100644
--- a/WebCore/platform/graphics/chromium/VideoLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.h
@@ -49,6 +49,10 @@ public:
virtual bool drawsContent() { return true; }
virtual void draw();
+ // This function is called by VideoFrameProvider. When this method is called
+ // putCurrentFrame() must be called to return the frame currently held.
+ void releaseCurrentFrame();
+
class SharedValues {
public:
explicit SharedValues(GraphicsContext3D*);
@@ -66,7 +70,7 @@ public:
int rgbaAlphaLocation() const { return m_rgbaAlphaLocation; }
int rgbaTextureLocation() const { return m_rgbaTextureLocation; }
int ccMatrixLocation() const { return m_ccMatrixLocation; }
- bool initialized() const { return m_initialized; };
+ bool initialized() const { return m_initialized; }
private:
GraphicsContext3D* m_context;
unsigned m_yuvShaderProgram;
@@ -85,8 +89,12 @@ public:
bool m_initialized;
};
+protected:
+ virtual void cleanupResources();
+
private:
VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider*);
+
static unsigned determineTextureFormat(VideoFrameChromium*);
bool allocateTexturesIfNeeded(GraphicsContext3D*, VideoFrameChromium*, unsigned textureFormat);
void updateYUVContents(GraphicsContext3D*, const VideoFrameChromium*);
@@ -95,12 +103,16 @@ private:
void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data);
void drawYUV(const SharedValues*);
void drawRGBA(const SharedValues*);
+ void resetFrameParameters();
+ void saveCurrentFrame(VideoFrameChromium*);
static const float yuv2RGB[9];
bool m_skipsDraw;
VideoFrameChromium::Format m_frameFormat;
- OwnPtr<VideoFrameProvider> m_provider;
+ VideoFrameProvider* m_provider;
+ VideoFrameChromium* m_currentFrame;
+
unsigned m_textures[3];
IntSize m_textureSizes[3];
IntSize m_frameSizes[3];
diff --git a/WebCore/platform/graphics/efl/ImageEfl.cpp b/WebCore/platform/graphics/efl/ImageEfl.cpp
index 112770f..a86ba4e 100644
--- a/WebCore/platform/graphics/efl/ImageEfl.cpp
+++ b/WebCore/platform/graphics/efl/ImageEfl.cpp
@@ -32,6 +32,7 @@
#include "BitmapImage.h"
#include "SharedBuffer.h"
+#include <wtf/text/StringConcatenate.h>
#include <cairo.h>
namespace WebCore {
@@ -51,7 +52,7 @@ static PassRefPtr<SharedBuffer> loadResourceSharedBufferFallback()
static PassRefPtr<SharedBuffer> loadResourceSharedBuffer(const char* name)
{
- RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(String::format(DATA_DIR "/webkit-1.0/images/%s.png", name));
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(makeString(DATA_DIR "/webkit-1.0/images/", name, ".png"));
if (buffer)
return buffer.release();
return loadResourceSharedBufferFallback();
diff --git a/WebCore/platform/graphics/filters/ImageBufferFilter.cpp b/WebCore/platform/graphics/efl/IntRectEfl.cpp
index 12407f8..0c92f63 100644
--- a/WebCore/platform/graphics/filters/ImageBufferFilter.cpp
+++ b/WebCore/platform/graphics/efl/IntRectEfl.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
- * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 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
@@ -19,25 +19,22 @@
*/
#include "config.h"
+#include "IntRect.h"
-#if ENABLE(FILTERS)
-#include "ImageBufferFilter.h"
-
-#include "FloatSize.h"
+#include <Eina.h>
namespace WebCore {
-ImageBufferFilter::ImageBufferFilter()
- : Filter()
+IntRect::IntRect(const Eina_Rectangle& r)
+ : m_location(IntPoint(r.x, r.y))
+ , m_size(r.w, r.h)
{
- setFilterResolution(FloatSize(1.f, 1.f));
}
-PassRefPtr<ImageBufferFilter> ImageBufferFilter::create()
+IntRect::operator Eina_Rectangle() const
{
- return adoptRef(new ImageBufferFilter());
+ Eina_Rectangle r = {x(), y(), width(), height()};
+ return r;
}
-} // namespace WebCore
-
-#endif // ENABLE(FILTERS)
+}
diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp
index 4185f61..1a40027 100644
--- a/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -98,13 +98,13 @@ void FEBlend::apply(Filter* filter)
if (m_mode == FEBLEND_MODE_UNKNOWN)
return;
- if (!effectContext())
+ if (!effectContext(filter))
return;
- IntRect effectADrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+ IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
- IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->repaintRectInLocalCoordinates());
+ IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
RefPtr<CanvasPixelArray> srcPixelArrayB(in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data());
IntRect imageRect(IntPoint(), resultImage()->size());
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index 86c37c2..b41d5ad 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -160,11 +160,11 @@ void FEColorMatrix::apply(Filter* filter)
if (!in->resultImage())
return;
- GraphicsContext* filterContext = effectContext();
+ GraphicsContext* filterContext = effectContext(filter);
if (!filterContext)
return;
- filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
+ filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
IntRect imageRect(IntPoint(), resultImage()->size());
PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect));
diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index 6fe38e4..08d0b1f 100644
--- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -154,7 +154,7 @@ void FEComponentTransfer::apply(Filter* filter)
if (!in->resultImage())
return;
- if (!effectContext())
+ if (!effectContext(filter))
return;
unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
@@ -167,7 +167,7 @@ void FEComponentTransfer::apply(Filter* filter)
for (unsigned channel = 0; channel < 4; channel++)
(*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
- IntRect drawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+ IntRect drawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
RefPtr<ImageData> imageData(in->resultImage()->getUnmultipliedImageData(drawingRect));
CanvasPixelArray* srcPixelArray(imageData->data());
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index 94e2524..2326966 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 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
@@ -112,6 +113,27 @@ inline void arithmetic(const RefPtr<CanvasPixelArray>& srcPixelArrayA, CanvasPix
}
}
}
+
+void FEComposite::determineAbsolutePaintRect(Filter* filter)
+{
+ switch (m_type) {
+ case FECOMPOSITE_OPERATOR_IN:
+ case FECOMPOSITE_OPERATOR_ATOP:
+ // For In and Atop the first effect just influences the result of
+ // the second effect. So just use the absolute paint rect of the second effect here.
+ setAbsolutePaintRect(inputEffect(1)->absolutePaintRect());
+ return;
+ case FECOMPOSITE_OPERATOR_ARITHMETIC:
+ // Arithmetic may influnce the compele filter primitive region. So we can't
+ // optimize the paint region here.
+ setAbsolutePaintRect(maxEffectRect());
+ return;
+ default:
+ // Take the union of both input effects.
+ FilterEffect::determineAbsolutePaintRect(filter);
+ return;
+ }
+}
void FEComposite::apply(Filter* filter)
{
@@ -122,39 +144,39 @@ void FEComposite::apply(Filter* filter)
if (!in->resultImage() || !in2->resultImage())
return;
- GraphicsContext* filterContext = effectContext();
+ GraphicsContext* filterContext = effectContext(filter);
if (!filterContext)
return;
FloatRect srcRect = FloatRect(0, 0, -1, -1);
switch (m_type) {
case FECOMPOSITE_OPERATOR_OVER:
- filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()));
- filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
+ filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
break;
case FECOMPOSITE_OPERATOR_IN:
filterContext->save();
- filterContext->clipToImageBuffer(in2->resultImage(), drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()));
- filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
+ filterContext->clipToImageBuffer(in2->resultImage(), drawingRegionOfInputImage(in2->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
filterContext->restore();
break;
case FECOMPOSITE_OPERATOR_OUT:
- filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
- filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()), srcRect, CompositeDestinationOut);
+ filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
+ filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()), srcRect, CompositeDestinationOut);
break;
case FECOMPOSITE_OPERATOR_ATOP:
- filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()));
- filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()), srcRect, CompositeSourceAtop);
+ filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeSourceAtop);
break;
case FECOMPOSITE_OPERATOR_XOR:
- filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()));
- filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()), srcRect, CompositeXOR);
+ filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeXOR);
break;
case FECOMPOSITE_OPERATOR_ARITHMETIC: {
- IntRect effectADrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+ IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
- IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->repaintRectInLocalCoordinates());
+ IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
RefPtr<ImageData> imageData(in2->resultImage()->getPremultipliedImageData(effectBDrawingRect));
CanvasPixelArray* srcPixelArrayB(imageData->data());
diff --git a/WebCore/platform/graphics/filters/FEComposite.h b/WebCore/platform/graphics/filters/FEComposite.h
index 82a3b06..ecdb037 100644
--- a/WebCore/platform/graphics/filters/FEComposite.h
+++ b/WebCore/platform/graphics/filters/FEComposite.h
@@ -61,6 +61,8 @@ public:
virtual void apply(Filter*);
virtual void dump();
+
+ virtual void determineAbsolutePaintRect(Filter*);
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
diff --git a/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
index dd66c6a..d487a47 100644
--- a/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
@@ -377,11 +377,11 @@ void FEConvolveMatrix::apply(Filter* filter)
if (!in->resultImage())
return;
- if (!effectContext())
+ if (!effectContext(filter))
return;
IntRect imageRect(IntPoint(), resultImage()->size());
- IntRect effectDrawingRect = requestedRegionOfInputImageData(in->filterPrimitiveSubregion());
+ IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
RefPtr<CanvasPixelArray> srcPixelArray;
if (m_preserveAlpha)
diff --git a/WebCore/platform/graphics/filters/FEConvolveMatrix.h b/WebCore/platform/graphics/filters/FEConvolveMatrix.h
index 2fe634f..8d3439e 100644
--- a/WebCore/platform/graphics/filters/FEConvolveMatrix.h
+++ b/WebCore/platform/graphics/filters/FEConvolveMatrix.h
@@ -75,6 +75,8 @@ public:
virtual void apply(Filter*);
virtual void dump();
+ virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
private:
diff --git a/WebCore/platform/graphics/filters/FEDisplacementMap.cpp b/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
index 6b5dbaa..0c53241 100644
--- a/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
+++ b/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 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
@@ -88,13 +89,13 @@ void FEDisplacementMap::apply(Filter* filter)
if (m_xChannelSelector == CHANNEL_UNKNOWN || m_yChannelSelector == CHANNEL_UNKNOWN)
return;
- if (!effectContext())
+ if (!effectContext(filter))
return;
- IntRect effectADrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+ IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
- IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->repaintRectInLocalCoordinates());
+ IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
RefPtr<CanvasPixelArray> srcPixelArrayB(in2->resultImage()->getUnmultipliedImageData(effectBDrawingRect)->data());
IntRect imageRect(IntPoint(), resultImage()->size());
@@ -102,10 +103,10 @@ void FEDisplacementMap::apply(Filter* filter)
ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
- float scaleX = m_scale / 255.f * filter->filterResolution().width();
- float scaleY = m_scale / 255.f * filter->filterResolution().height();
- float scaleAdjustmentX = (0.5f - 0.5f * m_scale) * filter->filterResolution().width();
- float scaleAdjustmentY = (0.5f - 0.5f * m_scale) * filter->filterResolution().height();
+ float scaleX = filter->applyHorizontalScale(m_scale / 255);
+ float scaleY = filter->applyVerticalScale(m_scale / 255);
+ float scaleAdjustmentX = filter->applyHorizontalScale(0.5f - 0.5f * m_scale);
+ float scaleAdjustmentY = filter->applyVerticalScale(0.5f - 0.5f * m_scale);
int stride = imageRect.width() * 4;
for (int y = 0; y < imageRect.height(); ++y) {
int line = y * stride;
diff --git a/WebCore/platform/graphics/filters/FEDisplacementMap.h b/WebCore/platform/graphics/filters/FEDisplacementMap.h
index dc87b90..c5b97a7 100644
--- a/WebCore/platform/graphics/filters/FEDisplacementMap.h
+++ b/WebCore/platform/graphics/filters/FEDisplacementMap.h
@@ -53,6 +53,8 @@ public:
virtual void apply(Filter*);
virtual void dump();
+ virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
private:
diff --git a/WebCore/platform/graphics/filters/FEFlood.cpp b/WebCore/platform/graphics/filters/FEFlood.cpp
index 7804d89..b51a422 100644
--- a/WebCore/platform/graphics/filters/FEFlood.cpp
+++ b/WebCore/platform/graphics/filters/FEFlood.cpp
@@ -62,14 +62,14 @@ void FEFlood::setFloodOpacity(float floodOpacity)
m_floodOpacity = floodOpacity;
}
-void FEFlood::apply(Filter*)
+void FEFlood::apply(Filter* filter)
{
- GraphicsContext* filterContext = effectContext();
+ GraphicsContext* filterContext = effectContext(filter);
if (!filterContext)
return;
Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity());
- filterContext->fillRect(FloatRect(FloatPoint(), repaintRectInLocalCoordinates().size()), color, DeviceColorSpace);
+ filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), color, ColorSpaceDeviceRGB);
}
void FEFlood::dump()
diff --git a/WebCore/platform/graphics/filters/FEFlood.h b/WebCore/platform/graphics/filters/FEFlood.h
index b615531..e6a9574 100644
--- a/WebCore/platform/graphics/filters/FEFlood.h
+++ b/WebCore/platform/graphics/filters/FEFlood.h
@@ -42,6 +42,8 @@ public:
virtual void apply(Filter*);
virtual void dump();
+ virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
private:
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
index fd9a3d8..1f36ba7 100644
--- a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -4,6 +4,7 @@
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2010 Igalia, S.L.
+ * Copyright (C) Research In Motion Limited 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
@@ -34,7 +35,8 @@
using std::max;
-static const float gGaussianKernelFactor = (3 * sqrtf(2 * piFloat) / 4.f);
+static const float gGaussianKernelFactor = 3 / 4.f * sqrtf(2 * piFloat);
+static const unsigned gMaxKernelSize = 1000;
namespace WebCore {
@@ -97,7 +99,7 @@ static void boxBlur(CanvasPixelArray*& srcPixelArray, CanvasPixelArray*& dstPixe
}
}
-void FEGaussianBlur::kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight)
+inline void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight)
{
// check http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement for details
switch (boxBlur) {
@@ -125,6 +127,41 @@ void FEGaussianBlur::kernelPosition(int boxBlur, unsigned& std, int& dLeft, int&
}
}
+inline void calculateKernelSize(Filter* filter, unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY)
+{
+ stdX = filter->applyHorizontalScale(stdX);
+ stdY = filter->applyVerticalScale(stdY);
+
+ kernelSizeX = 0;
+ if (stdX)
+ kernelSizeX = max<unsigned>(2, static_cast<unsigned>(floorf(stdX * gGaussianKernelFactor + 0.5f)));
+ kernelSizeY = 0;
+ if (stdY)
+ kernelSizeY = max<unsigned>(2, static_cast<unsigned>(floorf(stdY * gGaussianKernelFactor + 0.5f)));
+
+ // Limit the kernel size to 1000. A bigger radius won't make a big difference for the result image but
+ // inflates the absolute paint rect to much. This is compatible with Firefox' behavior.
+ if (kernelSizeX > gMaxKernelSize)
+ kernelSizeX = gMaxKernelSize;
+ if (kernelSizeY > gMaxKernelSize)
+ kernelSizeY = gMaxKernelSize;
+}
+
+void FEGaussianBlur::determineAbsolutePaintRect(Filter* filter)
+{
+ FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
+ absolutePaintRect.intersect(maxEffectRect());
+
+ unsigned kernelSizeX = 0;
+ unsigned kernelSizeY = 0;
+ calculateKernelSize(filter, kernelSizeX, kernelSizeY, m_stdX, m_stdY);
+
+ // We take the half kernel size and multiply it with three, because we run box blur three times.
+ absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f);
+ absolutePaintRect.inflateY(3 * kernelSizeY * 0.5f);
+ setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
+}
+
void FEGaussianBlur::apply(Filter* filter)
{
FilterEffect* in = inputEffect(0);
@@ -132,12 +169,12 @@ void FEGaussianBlur::apply(Filter* filter)
if (!in->resultImage())
return;
- if (!effectContext())
+ if (!effectContext(filter))
return;
setIsAlphaImage(in->isAlphaImage());
- IntRect effectDrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+ IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
RefPtr<ImageData> srcImageData(in->resultImage()->getPremultipliedImageData(effectDrawingRect));
IntRect imageRect(IntPoint(), resultImage()->size());
@@ -147,12 +184,8 @@ void FEGaussianBlur::apply(Filter* filter)
}
unsigned kernelSizeX = 0;
- if (m_stdX)
- kernelSizeX = max(2U, static_cast<unsigned>(floor(m_stdX * filter->filterResolution().width() * gGaussianKernelFactor + 0.5f)));
-
unsigned kernelSizeY = 0;
- if (m_stdY)
- kernelSizeY = max(2U, static_cast<unsigned>(floor(m_stdY * filter->filterResolution().height() * gGaussianKernelFactor + 0.5f)));
+ calculateKernelSize(filter, kernelSizeX, kernelSizeY, m_stdX, m_stdY);
CanvasPixelArray* srcPixelArray(srcImageData->data());
RefPtr<ImageData> tmpImageData = ImageData::create(imageRect.width(), imageRect.height());
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.h b/WebCore/platform/graphics/filters/FEGaussianBlur.h
index 745bcc8..50fc610 100644
--- a/WebCore/platform/graphics/filters/FEGaussianBlur.h
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.h
@@ -42,12 +42,13 @@ public:
virtual void apply(Filter*);
virtual void dump();
+
+ virtual void determineAbsolutePaintRect(Filter*);
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
private:
FEGaussianBlur(float, float);
- static void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight);
float m_stdX;
float m_stdY;
diff --git a/WebCore/platform/graphics/filters/FELighting.cpp b/WebCore/platform/graphics/filters/FELighting.cpp
index f49b67d..e1df580 100644
--- a/WebCore/platform/graphics/filters/FELighting.cpp
+++ b/WebCore/platform/graphics/filters/FELighting.cpp
@@ -247,12 +247,12 @@ void FELighting::apply(Filter* filter)
if (!in->resultImage())
return;
- if (!effectContext())
+ if (!effectContext(filter))
return;
setIsAlphaImage(false);
- IntRect effectDrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+ IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
RefPtr<ImageData> srcImageData(in->resultImage()->getUnmultipliedImageData(effectDrawingRect));
CanvasPixelArray* srcPixelArray(srcImageData->data());
@@ -261,8 +261,9 @@ void FELighting::apply(Filter* filter)
// output for various kernelUnitLengths, and I am not sure they are reliable.
// Anyway, feConvolveMatrix should also use the implementation
- if (drawLighting(srcPixelArray, effectDrawingRect.width(), effectDrawingRect.height()))
- resultImage()->putUnmultipliedImageData(srcImageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
+ IntSize absolutePaintSize = absolutePaintRect().size();
+ if (drawLighting(srcPixelArray, absolutePaintSize.width(), absolutePaintSize.height()))
+ resultImage()->putUnmultipliedImageData(srcImageData.get(), IntRect(IntPoint(), absolutePaintSize), IntPoint());
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/filters/FELighting.h b/WebCore/platform/graphics/filters/FELighting.h
index 28c00c4..bd56cee 100644
--- a/WebCore/platform/graphics/filters/FELighting.h
+++ b/WebCore/platform/graphics/filters/FELighting.h
@@ -44,6 +44,8 @@ class FELighting : public FilterEffect {
public:
virtual void apply(Filter*);
+ virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
protected:
enum LightingType {
DiffuseLighting,
diff --git a/WebCore/platform/graphics/filters/FEMerge.cpp b/WebCore/platform/graphics/filters/FEMerge.cpp
index 19c832a..b136af3 100644
--- a/WebCore/platform/graphics/filters/FEMerge.cpp
+++ b/WebCore/platform/graphics/filters/FEMerge.cpp
@@ -50,13 +50,13 @@ void FEMerge::apply(Filter* filter)
return;
}
- GraphicsContext* filterContext = effectContext();
+ GraphicsContext* filterContext = effectContext(filter);
if (!filterContext)
return;
for (unsigned i = 0; i < size; ++i) {
FilterEffect* in = inputEffect(i);
- filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
+ filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
}
}
diff --git a/WebCore/platform/graphics/filters/FEMorphology.cpp b/WebCore/platform/graphics/filters/FEMorphology.cpp
index 7329e1e..ac26441 100644
--- a/WebCore/platform/graphics/filters/FEMorphology.cpp
+++ b/WebCore/platform/graphics/filters/FEMorphology.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 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
@@ -74,6 +75,15 @@ float FEMorphology::radiusY() const
return m_radiusY;
}
+void FEMorphology::determineAbsolutePaintRect(Filter* filter)
+{
+ FloatRect paintRect = inputEffect(0)->absolutePaintRect();
+ paintRect.inflateX(filter->applyHorizontalScale(m_radiusX));
+ paintRect.inflateY(filter->applyVerticalScale(m_radiusY));
+ paintRect.intersect(maxEffectRect());
+ setAbsolutePaintRect(enclosingIntRect(paintRect));
+}
+
void FEMorphology::setRadiusY(float radiusY)
{
m_radiusY = radiusY;
@@ -86,18 +96,18 @@ void FEMorphology::apply(Filter* filter)
if (!in->resultImage())
return;
- if (!effectContext())
+ if (!effectContext(filter))
return;
setIsAlphaImage(in->isAlphaImage());
-
- int radiusX = static_cast<int>(m_radiusX * filter->filterResolution().width());
- int radiusY = static_cast<int>(m_radiusY * filter->filterResolution().height());
- if (radiusX <= 0 || radiusY <= 0)
+ if (m_radiusX <= 0 || m_radiusY <= 0)
return;
+ int radiusX = static_cast<int>(floorf(filter->applyHorizontalScale(m_radiusX)));
+ int radiusY = static_cast<int>(floorf(filter->applyVerticalScale(m_radiusY)));
+
IntRect imageRect(IntPoint(), resultImage()->size());
- IntRect effectDrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+ IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
RefPtr<CanvasPixelArray> srcPixelArray(in->resultImage()->getPremultipliedImageData(effectDrawingRect)->data());
RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
diff --git a/WebCore/platform/graphics/filters/FEMorphology.h b/WebCore/platform/graphics/filters/FEMorphology.h
index c8ce058..913671d 100644
--- a/WebCore/platform/graphics/filters/FEMorphology.h
+++ b/WebCore/platform/graphics/filters/FEMorphology.h
@@ -49,6 +49,8 @@ public:
virtual void apply(Filter*);
virtual void dump();
+ virtual void determineAbsolutePaintRect(Filter*);
+
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
private:
diff --git a/WebCore/platform/graphics/filters/FEOffset.cpp b/WebCore/platform/graphics/filters/FEOffset.cpp
index ea84cf0..6ca56aa 100644
--- a/WebCore/platform/graphics/filters/FEOffset.cpp
+++ b/WebCore/platform/graphics/filters/FEOffset.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 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
@@ -62,6 +63,14 @@ void FEOffset::setDy(float dy)
m_dy = dy;
}
+void FEOffset::determineAbsolutePaintRect(Filter* filter)
+{
+ FloatRect paintRect = inputEffect(0)->absolutePaintRect();
+ paintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
+ paintRect.intersect(maxEffectRect());
+ setAbsolutePaintRect(enclosingIntRect(paintRect));
+}
+
void FEOffset::apply(Filter* filter)
{
FilterEffect* in = inputEffect(0);
@@ -69,28 +78,15 @@ void FEOffset::apply(Filter* filter)
if (!in->resultImage())
return;
- GraphicsContext* filterContext = effectContext();
+ GraphicsContext* filterContext = effectContext(filter);
if (!filterContext)
return;
setIsAlphaImage(in->isAlphaImage());
- FloatRect sourceImageRect = filter->sourceImageRect();
- sourceImageRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
-
- if (filter->effectBoundingBoxMode()) {
- m_dx *= sourceImageRect.width();
- m_dy *= sourceImageRect.height();
- }
- m_dx *= filter->filterResolution().width();
- m_dy *= filter->filterResolution().height();
-
- FloatRect dstRect = FloatRect(m_dx + in->repaintRectInLocalCoordinates().x() - repaintRectInLocalCoordinates().x(),
- m_dy + in->repaintRectInLocalCoordinates().y() - repaintRectInLocalCoordinates().y(),
- in->repaintRectInLocalCoordinates().width(),
- in->repaintRectInLocalCoordinates().height());
-
- filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, dstRect);
+ FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
+ drawingRegion.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
+ filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegion);
}
void FEOffset::dump()
diff --git a/WebCore/platform/graphics/filters/FEOffset.h b/WebCore/platform/graphics/filters/FEOffset.h
index 052ba74..36575c5 100644
--- a/WebCore/platform/graphics/filters/FEOffset.h
+++ b/WebCore/platform/graphics/filters/FEOffset.h
@@ -40,6 +40,8 @@ public:
virtual void apply(Filter*);
virtual void dump();
+
+ virtual void determineAbsolutePaintRect(Filter*);
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
diff --git a/WebCore/platform/graphics/filters/FETile.cpp b/WebCore/platform/graphics/filters/FETile.cpp
index 41abd34..a695d3b 100644
--- a/WebCore/platform/graphics/filters/FETile.cpp
+++ b/WebCore/platform/graphics/filters/FETile.cpp
@@ -27,6 +27,7 @@
#include "Filter.h"
#include "GraphicsContext.h"
#include "Pattern.h"
+#include "SVGImageBufferTools.h"
namespace WebCore {
@@ -44,45 +45,51 @@ FloatRect FETile::determineFilterPrimitiveSubregion(Filter* filter)
{
inputEffect(0)->determineFilterPrimitiveSubregion(filter);
- filter->determineFilterPrimitiveSubregion(this, filter->filterRegion());
+ filter->determineFilterPrimitiveSubregion(this, filter->filterRegionInUserSpace());
return filterPrimitiveSubregion();
}
void FETile::apply(Filter* filter)
{
+// FIXME: See bug 47315. This is a hack to work around a compile failure, but is incorrect behavior otherwise.
+#if ENABLE(SVG)
FilterEffect* in = inputEffect(0);
in->apply(filter);
if (!in->resultImage())
return;
- GraphicsContext* filterContext = effectContext();
+ GraphicsContext* filterContext = effectContext(filter);
if (!filterContext)
return;
setIsAlphaImage(in->isAlphaImage());
- IntRect tileRect = enclosingIntRect(in->repaintRectInLocalCoordinates());
-
// Source input needs more attention. It has the size of the filterRegion but gives the
// size of the cutted sourceImage back. This is part of the specification and optimization.
- if (in->isSourceInput()) {
- FloatRect filterRegion = filter->filterRegion();
- filterRegion.scale(filter->filterResolution().width(), filter->filterResolution().height());
- tileRect = enclosingIntRect(filterRegion);
+ FloatRect tileRect = in->maxEffectRect();
+ FloatPoint inMaxEffectLocation = tileRect.location();
+ FloatPoint maxEffectLocation = maxEffectRect().location();
+ if (in->filterEffectType() == FilterEffectTypeSourceInput) {
+ tileRect = filter->filterRegion();
+ tileRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
}
- OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(tileRect.size());
+ OwnPtr<ImageBuffer> tileImage;
+ if (!SVGImageBufferTools::createImageBuffer(tileRect, tileRect, tileImage, ColorSpaceDeviceRGB))
+ return;
+
GraphicsContext* tileImageContext = tileImage->context();
- tileImageContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, IntPoint());
- RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);
+ tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
+ tileImageContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, in->absolutePaintRect().location());
- AffineTransform matrix;
- matrix.translate(in->repaintRectInLocalCoordinates().x() - repaintRectInLocalCoordinates().x(),
- in->repaintRectInLocalCoordinates().y() - repaintRectInLocalCoordinates().y());
- pattern.get()->setPatternSpaceTransform(matrix);
+ RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);
+ AffineTransform patternTransform;
+ patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y());
+ pattern->setPatternSpaceTransform(patternTransform);
filterContext->setFillPattern(pattern);
- filterContext->fillRect(FloatRect(FloatPoint(), repaintRectInLocalCoordinates().size()));
+ filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()));
+#endif
}
void FETile::dump()
@@ -103,4 +110,3 @@ TextStream& FETile::externalRepresentation(TextStream& ts, int indent) const
} // namespace WebCore
#endif // ENABLE(FILTERS)
-
diff --git a/WebCore/platform/graphics/filters/FETile.h b/WebCore/platform/graphics/filters/FETile.h
index 20efbcd..8562c90 100644
--- a/WebCore/platform/graphics/filters/FETile.h
+++ b/WebCore/platform/graphics/filters/FETile.h
@@ -35,6 +35,8 @@ public:
virtual void apply(Filter*);
virtual void dump();
+ virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
virtual FloatRect determineFilterPrimitiveSubregion(Filter*);
diff --git a/WebCore/platform/graphics/filters/FETurbulence.cpp b/WebCore/platform/graphics/filters/FETurbulence.cpp
index bb24362..b1494a5 100644
--- a/WebCore/platform/graphics/filters/FETurbulence.cpp
+++ b/WebCore/platform/graphics/filters/FETurbulence.cpp
@@ -321,7 +321,7 @@ unsigned char FETurbulence::calculateTurbulenceValueForPoint(PaintingData& paint
void FETurbulence::apply(Filter* filter)
{
- if (!effectContext())
+ if (!effectContext(filter))
return;
IntRect imageRect(IntPoint(), resultImage()->size());
@@ -329,10 +329,10 @@ void FETurbulence::apply(Filter* filter)
return;
RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
- PaintingData paintingData(m_seed, imageRect.size());
+ PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size()));
initPaint(paintingData);
- FloatRect filterRegion = filter->filterRegion();
+ FloatRect filterRegion = absolutePaintRect();
FloatPoint point;
point.setY(filterRegion.y());
int indexOfPixelChannel = 0;
@@ -342,7 +342,7 @@ void FETurbulence::apply(Filter* filter)
for (int x = 0; x < imageRect.width(); ++x) {
point.setX(point.x() + 1);
for (paintingData.channel = 0; paintingData.channel < 4; ++paintingData.channel, ++indexOfPixelChannel)
- imageData->data()->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(paintingData, point));
+ imageData->data()->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(paintingData, filter->mapAbsolutePointToLocalPoint(point)));
}
}
resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
diff --git a/WebCore/platform/graphics/filters/FETurbulence.h b/WebCore/platform/graphics/filters/FETurbulence.h
index 1a5a28a..c15d7d1 100644
--- a/WebCore/platform/graphics/filters/FETurbulence.h
+++ b/WebCore/platform/graphics/filters/FETurbulence.h
@@ -60,6 +60,8 @@ public:
virtual void apply(Filter*);
virtual void dump();
+
+ virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
diff --git a/WebCore/platform/graphics/filters/Filter.h b/WebCore/platform/graphics/filters/Filter.h
index bce4be3..121e389 100644
--- a/WebCore/platform/graphics/filters/Filter.h
+++ b/WebCore/platform/graphics/filters/Filter.h
@@ -44,11 +44,18 @@ namespace WebCore {
FloatSize filterResolution() const { return m_filterResolution; }
void setFilterResolution(const FloatSize& filterResolution) { m_filterResolution = filterResolution; }
+ virtual float applyHorizontalScale(float value) const { return value * m_filterResolution.width(); }
+ virtual float applyVerticalScale(float value) const { return value * m_filterResolution.height(); }
+
virtual FloatRect sourceImageRect() const = 0;
virtual FloatRect filterRegion() const = 0;
+
+ virtual FloatPoint mapAbsolutePointToLocalPoint(const FloatPoint&) const { return FloatPoint(); }
// SVG specific
virtual void determineFilterPrimitiveSubregion(FilterEffect*, const FloatRect&) { }
+
+ virtual FloatRect filterRegionInUserSpace() const { return FloatRect(); }
virtual FloatSize maxImageSize() const = 0;
virtual bool effectBoundingBoxMode() const = 0;
diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp
index 461b22a..121b921 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -46,7 +46,7 @@ FloatRect FilterEffect::determineFilterPrimitiveSubregion(Filter* filter)
// FETurbulence, FEImage and FEFlood don't have input effects, take the filter region as unite rect.
if (!size)
- uniteRect = filter->filterRegion();
+ uniteRect = filter->filterRegionInUserSpace();
else {
for (unsigned i = 0; i < size; ++i)
uniteRect.unite(m_inputEffects.at(i)->determineFilterPrimitiveSubregion(filter));
@@ -56,18 +56,29 @@ FloatRect FilterEffect::determineFilterPrimitiveSubregion(Filter* filter)
return m_filterPrimitiveSubregion;
}
-IntRect FilterEffect::requestedRegionOfInputImageData(const FloatRect& effectRect) const
+void FilterEffect::determineAbsolutePaintRect(Filter*)
+{
+ m_absolutePaintRect = IntRect();
+ unsigned size = m_inputEffects.size();
+ for (unsigned i = 0; i < size; ++i)
+ m_absolutePaintRect.unite(m_inputEffects.at(i)->absolutePaintRect());
+
+ // SVG specification wants us to clip to primitive subregion.
+ m_absolutePaintRect.intersect(m_maxEffectRect);
+}
+
+IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect) const
{
ASSERT(m_effectBuffer);
- FloatPoint location = m_repaintRectInLocalCoordinates.location();
+ IntPoint location = m_absolutePaintRect.location();
location.move(-effectRect.x(), -effectRect.y());
- return IntRect(roundedIntPoint(location), m_effectBuffer->size());
+ return IntRect(location, m_effectBuffer->size());
}
-FloatRect FilterEffect::drawingRegionOfInputImage(const FloatRect& srcRect) const
+IntRect FilterEffect::drawingRegionOfInputImage(const IntRect& srcRect) const
{
- return FloatRect(FloatPoint(srcRect.x() - m_repaintRectInLocalCoordinates.x(),
- srcRect.y() - m_repaintRectInLocalCoordinates.y()), srcRect.size());
+ return IntRect(IntPoint(srcRect.x() - m_absolutePaintRect.x(),
+ srcRect.y() - m_absolutePaintRect.y()), srcRect.size());
}
FilterEffect* FilterEffect::inputEffect(unsigned number) const
@@ -76,10 +87,12 @@ FilterEffect* FilterEffect::inputEffect(unsigned number) const
return m_inputEffects.at(number).get();
}
-GraphicsContext* FilterEffect::effectContext()
+GraphicsContext* FilterEffect::effectContext(Filter* filter)
{
- IntRect bufferRect = enclosingIntRect(m_repaintRectInLocalCoordinates);
- m_effectBuffer = ImageBuffer::create(bufferRect.size(), LinearRGB);
+ determineAbsolutePaintRect(filter);
+ if (m_absolutePaintRect.isEmpty())
+ return 0;
+ m_effectBuffer = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB);
if (!m_effectBuffer)
return 0;
return m_effectBuffer->context();
diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h
index ebe1880..a614b59 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/WebCore/platform/graphics/filters/FilterEffect.h
@@ -39,6 +39,13 @@ namespace WebCore {
typedef Vector<RefPtr<FilterEffect> > FilterEffectVector;
+enum FilterEffectType {
+ FilterEffectTypeUnknown,
+ FilterEffectTypeImage,
+ FilterEffectTypeTile,
+ FilterEffectTypeSourceInput
+};
+
class FilterEffect : public RefCounted<FilterEffect> {
public:
virtual ~FilterEffect();
@@ -49,26 +56,31 @@ public:
// Creates the ImageBuffer for the current filter primitive result in the size of the
// repaintRect. Gives back the GraphicsContext of the own ImageBuffer.
- GraphicsContext* effectContext();
+ GraphicsContext* effectContext(Filter*);
FilterEffectVector& inputEffects() { return m_inputEffects; }
FilterEffect* inputEffect(unsigned) const;
unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
- FloatRect drawingRegionOfInputImage(const FloatRect&) const;
- IntRect requestedRegionOfInputImageData(const FloatRect&) const;
+ IntRect drawingRegionOfInputImage(const IntRect&) const;
+ IntRect requestedRegionOfInputImageData(const IntRect&) const;
// Solid black image with different alpha values.
bool isAlphaImage() const { return m_alphaImage; }
void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; }
- FloatRect repaintRectInLocalCoordinates() const { return m_repaintRectInLocalCoordinates; }
- void setRepaintRectInLocalCoordinates(const FloatRect& repaintRectInLocalCoordinates) { m_repaintRectInLocalCoordinates = repaintRectInLocalCoordinates; }
+ IntRect absolutePaintRect() const { return m_absolutePaintRect; }
+ void setAbsolutePaintRect(const IntRect& absolutePaintRect) { m_absolutePaintRect = absolutePaintRect; }
+
+ IntRect maxEffectRect() const { return m_maxEffectRect; }
+ void setMaxEffectRect(const IntRect& maxEffectRect) { m_maxEffectRect = maxEffectRect; }
virtual void apply(Filter*) = 0;
virtual void dump() = 0;
- virtual bool isSourceInput() const { return false; }
+ virtual void determineAbsolutePaintRect(Filter*);
+
+ virtual FilterEffectType filterEffectType() const { return FilterEffectTypeUnknown; }
virtual TextStream& externalRepresentation(TextStream&, int indention = 0) const;
@@ -87,7 +99,7 @@ public:
bool hasHeight() const { return m_hasHeight; }
void setHasHeight(bool value) { m_hasHeight = value; }
- // FIXME: Pseudo primitives like SourceGraphic and SourceAlpha as well as FETile still need special handling.
+ // FIXME: FETile still needs special handling.
virtual FloatRect determineFilterPrimitiveSubregion(Filter*);
FloatRect filterPrimitiveSubregion() const { return m_filterPrimitiveSubregion; }
@@ -105,8 +117,11 @@ private:
bool m_alphaImage;
- // FIXME: Should be the paint region of the filter primitive, instead of the scaled subregion on use of filterRes.
- FloatRect m_repaintRectInLocalCoordinates;
+ IntRect m_absolutePaintRect;
+
+ // The maximum size of a filter primitive. In SVG this is the primitive subregion in absolute coordinate space.
+ // The absolute paint rect should never be bigger than m_maxEffectRect.
+ IntRect m_maxEffectRect;
private:
// The following member variables are SVG specific and will move to RenderSVGResourceFilterPrimitive.
diff --git a/WebCore/platform/graphics/filters/ImageBufferFilter.h b/WebCore/platform/graphics/filters/ImageBufferFilter.h
deleted file mode 100644
index cd4bc2f..0000000
--- a/WebCore/platform/graphics/filters/ImageBufferFilter.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
- * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * 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 ImageBufferFilter_h
-#define ImageBufferFilter_h
-
-#if ENABLE(FILTERS)
-#include "Filter.h"
-#include "FilterEffect.h"
-#include "FloatRect.h"
-#include "FloatSize.h"
-
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-#include <wtf/RefPtr.h>
-
-namespace WebCore {
-
-class ImageBufferFilter : public Filter {
-public:
- static PassRefPtr<ImageBufferFilter> create();
-
- virtual FloatRect filterRegion() const { return FloatRect(); }
- virtual FloatRect sourceImageRect() const { return FloatRect(); }
-
- // SVG specific
- virtual bool effectBoundingBoxMode() const { return false; }
-
- virtual FloatSize maxImageSize() const { return FloatSize(); }
- virtual void calculateEffectSubRegion(FilterEffect*) { }
-
-private:
- ImageBufferFilter();
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(FILTERS)
-
-#endif // ImageBufferFilter_h
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp
index beaf2e7..7dc56d9 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.cpp
+++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -42,31 +42,25 @@ const AtomicString& SourceAlpha::effectName()
return s_effectName;
}
-FloatRect SourceAlpha::determineFilterPrimitiveSubregion(Filter* filter)
+void SourceAlpha::determineAbsolutePaintRect(Filter* filter)
{
- FloatRect clippedSourceRect = filter->sourceImageRect();
- if (filter->sourceImageRect().x() < filter->filterRegion().x())
- clippedSourceRect.setX(filter->filterRegion().x());
- if (filter->sourceImageRect().y() < filter->filterRegion().y())
- clippedSourceRect.setY(filter->filterRegion().y());
- setFilterPrimitiveSubregion(clippedSourceRect);
- clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
- setRepaintRectInLocalCoordinates(clippedSourceRect);
- return filter->filterRegion();
+ FloatRect paintRect = filter->sourceImageRect();
+ paintRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
+ setAbsolutePaintRect(enclosingIntRect(paintRect));
}
void SourceAlpha::apply(Filter* filter)
{
- GraphicsContext* filterContext = effectContext();
- if (!filterContext)
+ GraphicsContext* filterContext = effectContext(filter);
+ if (!filterContext || !filter->sourceImage())
return;
setIsAlphaImage(true);
- FloatRect imageRect(FloatPoint(), filter->sourceImage()->size());
+ FloatRect imageRect(FloatPoint(), absolutePaintRect().size());
filterContext->save();
filterContext->clipToImageBuffer(filter->sourceImage(), imageRect);
- filterContext->fillRect(imageRect, Color::black, DeviceColorSpace);
+ filterContext->fillRect(imageRect, Color::black, ColorSpaceDeviceRGB);
filterContext->restore();
}
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.h b/WebCore/platform/graphics/filters/SourceAlpha.h
index f0fa319..83704e5 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.h
+++ b/WebCore/platform/graphics/filters/SourceAlpha.h
@@ -34,12 +34,12 @@ public:
static const AtomicString& effectName();
- virtual FloatRect determineFilterPrimitiveSubregion(Filter*);
-
virtual void apply(Filter*);
virtual void dump();
- virtual bool isSourceInput() const { return true; }
+ virtual void determineAbsolutePaintRect(Filter*);
+
+ virtual FilterEffectType filterEffectType() const { return FilterEffectTypeSourceInput; }
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp
index c014e68..fbb711a 100644
--- a/WebCore/platform/graphics/filters/SourceGraphic.cpp
+++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp
@@ -41,26 +41,20 @@ const AtomicString& SourceGraphic::effectName()
return s_effectName;
}
-FloatRect SourceGraphic::determineFilterPrimitiveSubregion(Filter* filter)
+void SourceGraphic::determineAbsolutePaintRect(Filter* filter)
{
- FloatRect clippedSourceRect = filter->sourceImageRect();
- if (filter->sourceImageRect().x() < filter->filterRegion().x())
- clippedSourceRect.setX(filter->filterRegion().x());
- if (filter->sourceImageRect().y() < filter->filterRegion().y())
- clippedSourceRect.setY(filter->filterRegion().y());
- setFilterPrimitiveSubregion(clippedSourceRect);
- clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
- setRepaintRectInLocalCoordinates(clippedSourceRect);
- return filter->filterRegion();
+ FloatRect paintRect = filter->sourceImageRect();
+ paintRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
+ setAbsolutePaintRect(enclosingIntRect(paintRect));
}
void SourceGraphic::apply(Filter* filter)
{
- GraphicsContext* filterContext = effectContext();
- if (!filterContext)
+ GraphicsContext* filterContext = effectContext(filter);
+ if (!filterContext || !filter->sourceImage())
return;
- filterContext->drawImageBuffer(filter->sourceImage(), DeviceColorSpace, IntPoint());
+ filterContext->drawImageBuffer(filter->sourceImage(), ColorSpaceDeviceRGB, IntPoint());
}
void SourceGraphic::dump()
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.h b/WebCore/platform/graphics/filters/SourceGraphic.h
index 2378798..a13337d 100644
--- a/WebCore/platform/graphics/filters/SourceGraphic.h
+++ b/WebCore/platform/graphics/filters/SourceGraphic.h
@@ -35,12 +35,12 @@ public:
static const AtomicString& effectName();
- virtual FloatRect determineFilterPrimitiveSubregion(Filter*);
-
virtual void apply(Filter*);
virtual void dump();
- virtual bool isSourceInput() const { return true; }
+ virtual void determineAbsolutePaintRect(Filter*);
+
+ virtual FilterEffectType filterEffectType() const { return FilterEffectTypeSourceInput; }
virtual TextStream& externalRepresentation(TextStream&, int indention) const;
diff --git a/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
index dc80954..2dc0517 100644
--- a/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
@@ -30,31 +30,40 @@
#include "config.h"
-#include "DrawingBuffer.h"
+#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(3D_CANVAS)
-#include "GraphicsContext3D.h"
-#include "SharedGraphicsContext3D.h"
+#include "DrawingBuffer.h"
namespace WebCore {
-PassOwnPtr<DrawingBuffer> DrawingBuffer::create(SharedGraphicsContext3D* context, const IntSize& size)
+PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size)
{
- unsigned framebuffer = context->createFramebuffer();
- ASSERT(framebuffer);
- if (!framebuffer)
- return 0;
- return adoptPtr(new DrawingBuffer(context, size, framebuffer));
+ RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, size));
+ return (drawingBuffer->m_context) ? drawingBuffer.release() : 0;
}
-void DrawingBuffer::bind()
+void DrawingBuffer::clear()
{
- m_context->bindFramebuffer(m_framebuffer);
- m_context->setViewport(m_size);
+ if (!m_context)
+ return;
+
+ m_context->makeContextCurrent();
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
+ m_context->deleteFramebuffer(m_fbo);
+ m_fbo = 0;
+
+ m_context.clear();
}
-void DrawingBuffer::setWillPublishCallback(PassOwnPtr<WillPublishCallback> callback)
+void DrawingBuffer::bind()
{
- m_callback = callback;
+ if (!m_context)
+ return;
+
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
+ m_context->viewport(0, 0, m_size.width(), m_size.height());
}
} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/DrawingBuffer.h b/WebCore/platform/graphics/gpu/DrawingBuffer.h
index 23e6f4a..75c7f99 100644
--- a/WebCore/platform/graphics/gpu/DrawingBuffer.h
+++ b/WebCore/platform/graphics/gpu/DrawingBuffer.h
@@ -31,30 +31,39 @@
#ifndef DrawingBuffer_h
#define DrawingBuffer_h
+#include "GraphicsContext3D.h"
#include "GraphicsLayer.h"
#include "IntSize.h"
#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
+#if PLATFORM(MAC)
+#include <wtf/RetainPtr.h>
+#endif
namespace WebCore {
-class SharedGraphicsContext3D;
-
+#if PLATFORM(CHROMIUM)
struct DrawingBufferInternal;
+#endif
// Manages a rendering target (framebuffer + attachment) for a canvas. Can publish its rendering
// results to a PlatformLayer for compositing.
-class DrawingBuffer : public Noncopyable {
+class DrawingBuffer : public RefCounted<DrawingBuffer> {
public:
- static PassOwnPtr<DrawingBuffer> create(SharedGraphicsContext3D*, const IntSize&);
+ friend class GraphicsContext3D;
+
~DrawingBuffer();
void reset(const IntSize&);
void bind();
IntSize size() const { return m_size; }
+ // Clear all resources from this object, as well as context. Called when context is destroyed
+ // to prevent invalid accesses to the resources.
+ void clear();
+
#if USE(ACCELERATED_COMPOSITING)
PlatformLayer* platformLayer();
void publishToPlatformLayer();
@@ -62,21 +71,36 @@ public:
unsigned getRenderingResultsAsTexture();
+#if PLATFORM(CHROMIUM)
class WillPublishCallback : public Noncopyable {
public:
+ virtual ~WillPublishCallback() { }
+
virtual void willPublish() = 0;
};
- void setWillPublishCallback(PassOwnPtr<WillPublishCallback>);
+ void setWillPublishCallback(PassOwnPtr<WillPublishCallback> callback) { m_callback = callback; }
+#endif
+
+ PassRefPtr<GraphicsContext3D> graphicsContext3D() const { return m_context; }
+
private:
- DrawingBuffer(SharedGraphicsContext3D*, const IntSize&, unsigned framebuffer);
+ static PassRefPtr<DrawingBuffer> create(GraphicsContext3D*, const IntSize&);
+
+ DrawingBuffer(GraphicsContext3D*, const IntSize&);
- SharedGraphicsContext3D* m_context;
+ RefPtr<GraphicsContext3D> m_context;
IntSize m_size;
- unsigned m_framebuffer;
+ Platform3DObject m_fbo;
+#if PLATFORM(CHROMIUM)
OwnPtr<WillPublishCallback> m_callback;
OwnPtr<DrawingBufferInternal> m_internal;
+#endif
+
+#if PLATFORM(MAC)
+ RetainPtr<WebGLLayer> m_platformLayer;
+#endif
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnClassifier.cpp b/WebCore/platform/graphics/gpu/LoopBlinnClassifier.cpp
index e43dc37..672b4d7 100644
--- a/WebCore/platform/graphics/gpu/LoopBlinnClassifier.cpp
+++ b/WebCore/platform/graphics/gpu/LoopBlinnClassifier.cpp
@@ -25,6 +25,8 @@
#include "config.h"
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "LoopBlinnClassifier.h"
#include "LoopBlinnMathUtils.h"
@@ -120,3 +122,5 @@ LoopBlinnClassifier::Result LoopBlinnClassifier::classify(const FloatPoint& c0,
}
} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.cpp b/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.cpp
index 3b73ff6..1517a67 100644
--- a/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.cpp
+++ b/WebCore/platform/graphics/gpu/LoopBlinnLocalTriangulator.cpp
@@ -25,6 +25,8 @@
#include "config.h"
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "LoopBlinnLocalTriangulator.h"
#include "LoopBlinnMathUtils.h"
@@ -273,3 +275,5 @@ bool LoopBlinnLocalTriangulator::isSharedEdge(Vertex* v0, Vertex* v1)
}
} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp b/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp
index 61ebc9b..5b155a5 100644
--- a/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp
+++ b/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp
@@ -25,12 +25,13 @@
#include "config.h"
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "LoopBlinnMathUtils.h"
#include "FloatPoint.h"
-#include "MathExtras.h"
#include <algorithm>
-#include <string.h> // for memcpy
+#include <wtf/MathExtras.h>
namespace WebCore {
namespace LoopBlinnMathUtils {
@@ -563,3 +564,5 @@ int numXRayCrossingsForCubic(const XRay& xRay, const FloatPoint cubic[4], bool&
} // namespace LoopBlinnMathUtils
} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.cpp b/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.cpp
index ac82637..d272fe1 100644
--- a/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.cpp
+++ b/WebCore/platform/graphics/gpu/LoopBlinnTextureCoords.cpp
@@ -25,6 +25,8 @@
#include "config.h"
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "LoopBlinnTextureCoords.h"
#include <math.h>
@@ -169,3 +171,5 @@ LoopBlinnTextureCoords::Result LoopBlinnTextureCoords::compute(const LoopBlinnCl
}
} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/PODInterval.h b/WebCore/platform/graphics/gpu/PODInterval.h
index 9df69ba..5c1dcc2 100644
--- a/WebCore/platform/graphics/gpu/PODInterval.h
+++ b/WebCore/platform/graphics/gpu/PODInterval.h
@@ -27,7 +27,7 @@
#define PODInterval_h
#ifndef NDEBUG
-#include "StringBuilder.h"
+#include <wtf/text/StringBuilder.h>
#endif
namespace WebCore {
@@ -57,14 +57,24 @@ namespace WebCore {
// constructor and assignment operator.
//
// In debug mode, printing of intervals and the data they contain is
-// enabled. This requires the following functions to be available:
+// enabled. This requires the following template specializations to be
+// available:
//
-// String valueToString(const T&);
-// String valueToString(const UserData&);
+// template<> struct WebCore::ValueToString<T> {
+// static String string(const T& t);
+// };
+// template<> struct WebCore::ValueToString<UserData> {
+// static String string(const UserData& t);
+// };
//
// Note that this class requires a copy constructor and assignment
// operator in order to be stored in the red-black tree.
+#ifndef NDEBUG
+template<class T>
+struct ValueToString;
+#endif
+
template<class T, class UserData = void*>
class PODInterval {
public:
@@ -131,13 +141,13 @@ public:
{
StringBuilder builder;
builder.append("[PODInterval (");
- builder.append(valueToString(low()));
+ builder.append(ValueToString<T>::string(low()));
builder.append(", ");
- builder.append(valueToString(high()));
+ builder.append(ValueToString<T>::string(high()));
builder.append("), data=");
- builder.append(valueToString(data()));
+ builder.append(ValueToString<UserData>::string(data()));
builder.append(", maxHigh=");
- builder.append(valueToString(maxHigh()));
+ builder.append(ValueToString<T>::string(maxHigh()));
builder.append("]");
return builder.toString();
}
diff --git a/WebCore/platform/graphics/gpu/PODIntervalTree.h b/WebCore/platform/graphics/gpu/PODIntervalTree.h
index c0a86aa..320ce60 100644
--- a/WebCore/platform/graphics/gpu/PODIntervalTree.h
+++ b/WebCore/platform/graphics/gpu/PODIntervalTree.h
@@ -35,6 +35,11 @@
namespace WebCore {
+#ifndef NDEBUG
+template<class T>
+struct ValueToString;
+#endif
+
// An interval tree, which is a form of augmented red-black tree. It
// supports efficient (O(lg n)) insertion, removal and querying of
// intervals in the tree.
@@ -191,7 +196,7 @@ private:
localMaxValue = node->data().high();
if (!(localMaxValue == node->data().maxHigh())) {
#ifndef NDEBUG
- String localMaxValueString = valueToString(localMaxValue);
+ String localMaxValueString = ValueToString<T>::string(localMaxValue);
LOG_ERROR("PODIntervalTree verification failed at node 0x%p: localMaxValue=%s and data=%s",
node, localMaxValueString.utf8().data(), node->data().toString().utf8().data());
#endif
@@ -206,10 +211,12 @@ private:
#ifndef NDEBUG
// Support for printing PODIntervals at the PODRedBlackTree level.
template<class T, class UserData>
-String valueToString(const PODInterval<T, UserData>& interval)
-{
- return interval.toString();
-}
+struct ValueToString<PODInterval<T, UserData> > {
+ static String string(const PODInterval<T, UserData>& interval)
+ {
+ return interval.toString();
+ }
+};
#endif
} // namespace WebCore
diff --git a/WebCore/platform/graphics/gpu/PODRedBlackTree.h b/WebCore/platform/graphics/gpu/PODRedBlackTree.h
index 9b02037..6d5954c 100644
--- a/WebCore/platform/graphics/gpu/PODRedBlackTree.h
+++ b/WebCore/platform/graphics/gpu/PODRedBlackTree.h
@@ -42,9 +42,11 @@
// the "<" and "==" operators.
//
// In debug mode, printing of the data contained in the tree is
-// enabled. This requires the following function to be available:
+// enabled. This requires the template specialization to be available:
//
-// String valueToString(const T&);
+// template<> struct WebCore::ValueToString<T> {
+// static String string(const T& t);
+// };
//
// Note that when complex types are stored in this red/black tree, it
// is possible that single invocations of the "<" and "==" operators
@@ -76,13 +78,18 @@
#include <wtf/RefPtr.h>
#ifndef NDEBUG
#include "Logging.h"
-#include "PlatformString.h"
-#include "StringBuilder.h"
#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
#endif
namespace WebCore {
+#ifndef NDEBUG
+template<class T>
+struct ValueToString;
+#endif
+
template<class T>
class PODRedBlackTree {
public:
@@ -723,7 +730,7 @@ private:
builder.append("-");
if (node) {
builder.append(" ");
- builder.append(valueToString(node->data()));
+ builder.append(ValueToString<T>::string(node->data()));
builder.append((node->color() == Black) ? " (black)" : " (red)");
}
LOG_ERROR("%s", builder.toString().ascii().data());
diff --git a/WebCore/platform/graphics/gpu/Shader.cpp b/WebCore/platform/graphics/gpu/Shader.cpp
index 59c50a7..8983adc 100644
--- a/WebCore/platform/graphics/gpu/Shader.cpp
+++ b/WebCore/platform/graphics/gpu/Shader.cpp
@@ -29,6 +29,9 @@
*/
#include "config.h"
+
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "Shader.h"
#include "AffineTransform.h"
@@ -109,3 +112,5 @@ Shader::~Shader()
}
}
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
index 7629735..87a0b69 100644
--- a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
+++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
@@ -30,6 +30,8 @@
#include "config.h"
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "SharedGraphicsContext3D.h"
#include "AffineTransform.h"
@@ -47,16 +49,26 @@
namespace WebCore {
// static
-PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(PassOwnPtr<GraphicsContext3D> context)
-{
- return adoptRef(new SharedGraphicsContext3D(context));
-}
-
-SharedGraphicsContext3D::SharedGraphicsContext3D(PassOwnPtr<GraphicsContext3D> context)
+PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(HostWindow* hostWindow)
+{
+ GraphicsContext3D::Attributes attr;
+ RefPtr<GraphicsContext3D> context = GraphicsContext3D::create(attr, hostWindow);
+ if (!context)
+ return 0;
+ OwnPtr<SolidFillShader> solidFillShader = SolidFillShader::create(context.get());
+ if (!solidFillShader)
+ return 0;
+ OwnPtr<TexShader> texShader = TexShader::create(context.get());
+ if (!texShader)
+ return 0;
+ return adoptRef(new SharedGraphicsContext3D(context.release(), solidFillShader.release(), texShader.release()));
+}
+
+SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader)
: m_context(context)
, m_quadVertices(0)
- , m_solidFillShader(SolidFillShader::create(m_context.get()))
- , m_texShader(TexShader::create(m_context.get()))
+ , m_solidFillShader(solidFillShader)
+ , m_texShader(texShader)
{
allContexts()->add(this);
}
@@ -215,8 +227,8 @@ void SharedGraphicsContext3D::removeTexturesFor(NativeImagePtr ptr)
// static
HashSet<SharedGraphicsContext3D*>* SharedGraphicsContext3D::allContexts()
{
- static OwnPtr<HashSet<SharedGraphicsContext3D*> > set(new HashSet<SharedGraphicsContext3D*>);
- return set.get();
+ DEFINE_STATIC_LOCAL(HashSet<SharedGraphicsContext3D*>, allContextsSet, ());
+ return &allContextsSet;
}
@@ -334,3 +346,5 @@ bool SharedGraphicsContext3D::paintsIntoCanvasBuffer() const
}
} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
index 3ba3c52..05008c2 100644
--- a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
+++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
@@ -47,6 +47,7 @@ class AffineTransform;
class Color;
class GraphicsContext3D;
class FloatRect;
+class HostWindow;
class IntSize;
class SolidFillShader;
class TexShader;
@@ -55,7 +56,7 @@ typedef HashMap<NativeImagePtr, RefPtr<Texture> > TextureHashMap;
class SharedGraphicsContext3D : public RefCounted<SharedGraphicsContext3D> {
public:
- static PassRefPtr<SharedGraphicsContext3D> create(PassOwnPtr<GraphicsContext3D>);
+ static PassRefPtr<SharedGraphicsContext3D> create(HostWindow*);
~SharedGraphicsContext3D();
// Functions that delegate directly to GraphicsContext3D, with caching
@@ -117,14 +118,16 @@ public:
// the texture.
PassRefPtr<Texture> createTexture(Texture::Format, int width, int height);
+ GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
+
private:
- explicit SharedGraphicsContext3D(PassOwnPtr<GraphicsContext3D> context);
+ SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D>, PassOwnPtr<SolidFillShader>, PassOwnPtr<TexShader>);
// Used to implement removeTexturesFor(), see the comment above.
static HashSet<SharedGraphicsContext3D*>* allContexts();
void removeTextureFor(NativeImagePtr);
- OwnPtr<GraphicsContext3D> m_context;
+ RefPtr<GraphicsContext3D> m_context;
unsigned m_quadVertices;
diff --git a/WebCore/platform/graphics/gpu/SolidFillShader.cpp b/WebCore/platform/graphics/gpu/SolidFillShader.cpp
index ff1b1fa..86079be 100644
--- a/WebCore/platform/graphics/gpu/SolidFillShader.cpp
+++ b/WebCore/platform/graphics/gpu/SolidFillShader.cpp
@@ -29,6 +29,9 @@
*/
#include "config.h"
+
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "SolidFillShader.h"
#include "Color.h"
@@ -86,3 +89,5 @@ void SolidFillShader::use(const AffineTransform& transform, const Color& color)
}
}
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/TexShader.cpp b/WebCore/platform/graphics/gpu/TexShader.cpp
index 01f4306..d7ffa17 100644
--- a/WebCore/platform/graphics/gpu/TexShader.cpp
+++ b/WebCore/platform/graphics/gpu/TexShader.cpp
@@ -29,6 +29,9 @@
*/
#include "config.h"
+
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "TexShader.h"
#include "GraphicsContext3D.h"
@@ -93,3 +96,5 @@ void TexShader::use(const AffineTransform& transform, const AffineTransform& tex
}
}
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/Texture.cpp b/WebCore/platform/graphics/gpu/Texture.cpp
index 6023fe9..74807dc 100644
--- a/WebCore/platform/graphics/gpu/Texture.cpp
+++ b/WebCore/platform/graphics/gpu/Texture.cpp
@@ -30,6 +30,8 @@
#include "config.h"
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "Texture.h"
#include "FloatRect.h"
@@ -206,3 +208,5 @@ void Texture::bindTile(int tile)
}
}
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/Texture.h b/WebCore/platform/graphics/gpu/Texture.h
index eda475e..92b6d0a 100644
--- a/WebCore/platform/graphics/gpu/Texture.h
+++ b/WebCore/platform/graphics/gpu/Texture.h
@@ -31,11 +31,11 @@
#ifndef Texture_h
#define Texture_h
-#include "RefCounted.h"
-#include "RefPtr.h"
#include "TilingData.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/gpu/TilingData.cpp b/WebCore/platform/graphics/gpu/TilingData.cpp
index 4da242b..a98add7 100644
--- a/WebCore/platform/graphics/gpu/TilingData.cpp
+++ b/WebCore/platform/graphics/gpu/TilingData.cpp
@@ -29,6 +29,9 @@
*/
#include "config.h"
+
+#if ENABLE(ACCELERATED_2D_CANVAS)
+
#include "TilingData.h"
#include "FloatRect.h"
@@ -220,3 +223,5 @@ void TilingData::intersectDrawQuad(const FloatRect& srcRect, const FloatRect& ds
}
}
+
+#endif
diff --git a/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm b/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm
new file mode 100644
index 0000000..7a8c501
--- /dev/null
+++ b/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(3D_CANVAS)
+
+#include "DrawingBuffer.h"
+
+#include "WebGLLayer.h"
+
+#import "BlockExceptions.h"
+
+namespace WebCore {
+
+DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size)
+ : m_context(context)
+ , m_size(size)
+ , m_fbo(context->createFramebuffer())
+{
+ ASSERT(m_fbo);
+ if (!m_fbo) {
+ clear();
+ return;
+ }
+
+ // Create the WebGLLayer
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ m_platformLayer.adoptNS([[WebGLLayer alloc] initWithGraphicsContext3D:m_context.get()]);
+#ifndef NDEBUG
+ [m_platformLayer.get() setName:@"DrawingBuffer Layer"];
+#endif
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+DrawingBuffer::~DrawingBuffer()
+{
+ clear();
+}
+
+void DrawingBuffer::reset(const IntSize& newSize)
+{
+ if (!m_context)
+ return;
+
+ if (m_size == newSize)
+ return;
+ m_size = newSize;
+
+ m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_size.width(), m_size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+PlatformLayer* DrawingBuffer::platformLayer()
+{
+ return m_platformLayer.get();
+}
+#endif
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
index 539d92a..1cb561e 100644
--- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
+++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
@@ -194,12 +194,14 @@ void GStreamerGWorld::setWindowOverlay(GstMessage* message)
if (g_object_class_find_property(G_OBJECT_GET_CLASS(sink), "force-aspect-ratio"))
g_object_set(sink, "force-aspect-ratio", TRUE, NULL);
- if (m_videoWindow)
+ if (m_videoWindow) {
+ m_videoWindow->prepareForOverlay(message);
#if GST_CHECK_VERSION(0, 10, 31) || GST_VERSION_NANO
gst_x_overlay_set_window_handle(GST_X_OVERLAY(sink), m_videoWindow->videoWindowId());
#else
gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(sink), m_videoWindow->videoWindowId());
#endif
+ }
}
}
diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index da9255b..7012c9f 100644
--- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -1212,7 +1212,7 @@ void MediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect&
if (!gstImage)
return;
- context->drawImage(reinterpret_cast<Image*>(gstImage->image().get()), sRGBColorSpace,
+ context->drawImage(reinterpret_cast<Image*>(gstImage->image().get()), ColorSpaceSRGB,
rect, CompositeCopy, false);
}
diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h
index f3df207..f2a3ff2 100644
--- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h
+++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h
@@ -25,6 +25,8 @@
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
+typedef struct _GstMessage GstMessage;
+
namespace WebCore {
class PlatformVideoWindow : public RefCounted<PlatformVideoWindow> {
@@ -34,6 +36,8 @@ class PlatformVideoWindow : public RefCounted<PlatformVideoWindow> {
PlatformVideoWindow();
~PlatformVideoWindow();
+
+ void prepareForOverlay(GstMessage*);
PlatformWidget window() const { return m_window; }
unsigned long videoWindowId() const { return m_videoWindowId; }
diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp
index c55b9cc..0097716 100644
--- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp
+++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp
@@ -35,4 +35,8 @@ PlatformVideoWindow::~PlatformVideoWindow()
notImplemented();
}
+void PlatformVideoWindow::prepareForOverlay(GstMessage*)
+{
+}
+
#endif // USE(GSTREAMER)
diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp
index 77343ae..c2f76cd 100644
--- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp
+++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp
@@ -61,4 +61,9 @@ PlatformVideoWindow::~PlatformVideoWindow()
m_videoWindowId = 0;
}
+
+void PlatformVideoWindow::prepareForOverlay(GstMessage*)
+{
+}
#endif // USE(GSTREAMER)
+
diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp
index 27f48fc..328ec4a 100644
--- a/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -181,31 +181,15 @@ bool Font::canReturnFallbackFontsForComplexText()
return false;
}
-#ifndef GTK_API_VERSION_2
-static void cairo_region_shrink(cairo_region_t* region, int dx, int dy)
+void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
- int nRects = cairo_region_num_rectangles(region);
- // Clear region.
- cairo_region_subtract(region, region);
-
- for (int i = 0; i < nRects; i++) {
- cairo_rectangle_int_t rect;
- cairo_region_get_rectangle(region, i, &rect);
-
- if (rect.width <= 2 * dx || rect.height <= 2 * dy)
- continue;
-
- rect.x += dx;
- rect.y += dy;
- rect.width -= 2 * dx;
- rect.height -= 2 * dy;
- cairo_region_union_rectangle(region, &rect);
+#if defined(USE_FREETYPE)
+ if (!primaryFont()->platformData().m_pattern) {
+ drawSimpleText(context, run, point, from, to);
+ return;
}
-}
#endif
-void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
cairo_t* cr = context->platformContext();
cairo_save(cr);
cairo_translate(cr, point.x(), point.y());
@@ -224,17 +208,13 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
#else
cairo_region_t* partialRegion = 0;
#endif
+
if (to - from != run.length()) {
// Clip the region of the run to be rendered
char* start = g_utf8_offset_to_pointer(utf8, from);
char* end = g_utf8_offset_to_pointer(start, to - from);
int ranges[] = {start - utf8, end - utf8};
partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1);
-#ifdef GTK_API_VERSION_2
- gdk_region_shrink(partialRegion, 0, -pixelSize());
-#else
- cairo_region_shrink(partialRegion, 0, -pixelSize());
-#endif
}
Color fillColor = context->fillColor();
@@ -290,7 +270,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
// Re-enable the platform shadow we disabled earlier
if (hasShadow)
- context->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace);
+ context->setShadow(shadowOffset, shadowBlur, shadowColor, ColorSpaceDeviceRGB);
// Pango sometimes leaves behind paths we don't want
cairo_new_path(cr);
@@ -323,8 +303,13 @@ static PangoLayout* getDefaultPangoLayout(const TextRun& run)
return layout;
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow*) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* overflow) const
{
+#if defined(USE_FREETYPE)
+ if (!primaryFont()->platformData().m_pattern)
+ return floatWidthForSimpleText(run, 0, fallbackFonts, overflow);
+#endif
+
if (run.length() == 0)
return 0.0f;
@@ -345,6 +330,10 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const
{
+#if defined(USE_FREETYPE)
+ if (!primaryFont()->platformData().m_pattern)
+ return offsetForPositionForSimpleText(run, xFloat, includePartialGlyphs);
+#endif
// FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
// to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
int x = static_cast<int>(xFloat);
@@ -369,6 +358,11 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
{
+#if defined(USE_FREETYPE)
+ if (!primaryFont()->platformData().m_pattern)
+ return selectionRectForSimpleText(run, point, h, from, to);
+#endif
+
PangoLayout* layout = getDefaultPangoLayout(run);
setPangoAttributes(this, run, layout);
diff --git a/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp b/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
index edb26f0..486a317 100644
--- a/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
+++ b/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
@@ -28,6 +28,7 @@
#include <cairo.h>
#include <gtk/gtk.h>
#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
namespace WebCore {
@@ -67,7 +68,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
base64Encode(reinterpret_cast<const char*>(buffer.get()), bufferSize, out);
out.append('\0');
- return String::format("data:%s;base64,%s", mimeType.utf8().data(), out.data());
+ return makeString("data:", mimeType, ";base64,", out.data());
}
}
diff --git a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
index c5de485..d1b06f3 100644
--- a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
@@ -33,6 +33,7 @@
#include "MIMETypeRegistry.h"
#include "StillImageHaiku.h"
#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
#include <BitmapStream.h>
#include <String.h>
#include <TranslatorRoster.h>
@@ -367,8 +368,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double*) const
base64Encode(reinterpret_cast<const char*>(translatedStream.Buffer()),
translatedStream.BufferLength(), encodedBuffer);
- return String::format("data:%s;base64,%s", mimeType.utf8().data(),
- encodedBuffer.data());
+ return makeString("data:", mimeType, ";base64,", encodedBuffer.data());
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/haiku/PathHaiku.cpp b/WebCore/platform/graphics/haiku/PathHaiku.cpp
index c5b8c98..5377e10 100644
--- a/WebCore/platform/graphics/haiku/PathHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/PathHaiku.cpp
@@ -144,12 +144,6 @@ bool Path::isEmpty() const
return !m_path->Frame().IsValid();
}
-String Path::debugString() const
-{
- notImplemented();
- return String();
-}
-
void Path::apply(void* info, PathApplierFunction function) const
{
notImplemented();
diff --git a/WebCore/platform/graphics/mac/ColorMac.mm b/WebCore/platform/graphics/mac/ColorMac.mm
index c8ea9b1..07d6353 100644
--- a/WebCore/platform/graphics/mac/ColorMac.mm
+++ b/WebCore/platform/graphics/mac/ColorMac.mm
@@ -88,14 +88,15 @@ NSColor *nsColor(const Color& color)
static unsigned cachedRGBAValues[cacheSize];
static RetainPtr<NSColor>* cachedColors = new RetainPtr<NSColor>[cacheSize];
- for (int i = 0; i != cacheSize; ++i)
+ for (int i = 0; i != cacheSize; ++i) {
if (cachedRGBAValues[i] == c)
return cachedColors[i].get();
+ }
NSColor *result = [NSColor colorWithDeviceRed:static_cast<CGFloat>(color.red()) / 255
green:static_cast<CGFloat>(color.green()) / 255
blue:static_cast<CGFloat>(color.blue()) / 255
- alpha:static_cast<CGFloat>(color.alpha()) /255];
+ alpha:static_cast<CGFloat>(color.alpha()) / 255];
static int cursor;
cachedRGBAValues[cursor] = c;
@@ -107,24 +108,5 @@ NSColor *nsColor(const Color& color)
}
}
-static CGColorRef CGColorFromNSColor(NSColor *color)
-{
- // This needs to always use device colorspace so it can de-calibrate the color for
- // CGColor to possibly recalibrate it.
- CGFloat components[4];
- NSColor *deviceColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- [deviceColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
- static CGColorSpaceRef deviceRGBColorSpace = CGColorSpaceCreateDeviceRGB();
- CGColorRef cgColor = CGColorCreate(deviceRGBColorSpace, components);
- return cgColor;
-}
-
-CGColorRef createCGColor(const Color& c)
-{
- // We could directly create a CGColor here, but that would
- // skip any RGB caching the nsColor method does. A direct
- // creation could be investigated for a possible performance win.
- return CGColorFromNSColor(nsColor(c));
-}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
index a4919d8..e079b44 100644
--- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
@@ -77,12 +77,12 @@ static void setPixelFormat(Vector<CGLPixelFormatAttribute>& attribs, int colorBi
attribs.append(static_cast<CGLPixelFormatAttribute>(0));
}
-PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle)
+PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle)
{
// This implementation doesn't currently support rendering directly to the HostWindow.
if (renderStyle == RenderDirectlyToHostWindow)
return 0;
- OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs, hostWindow, false));
+ RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attrs, hostWindow, false));
return context->m_contextObj ? context.release() : 0;
}
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index f3301d8..aa754f2 100644
--- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +30,7 @@
#import <AppKit/AppKit.h>
#import <wtf/StdLibExtras.h>
+#import "LocalCurrentGraphicsContext.h"
#import "WebCoreSystemInterface.h"
@class NSColor;
@@ -43,14 +44,14 @@ namespace WebCore {
// calls in this file are all exception-safe, so we don't block
// exceptions for those.
-static void drawFocusRingToContext(CGContextRef context, RetainPtr<CGPathRef> focusRingPath, RetainPtr<CGColorRef> colorRef, int radius)
+static void drawFocusRingToContext(CGContextRef context, CGPathRef focusRingPath, CGColorRef color, int radius)
{
#ifdef BUILDING_ON_TIGER
CGContextBeginTransparencyLayer(context, 0);
#endif
CGContextBeginPath(context);
- CGContextAddPath(context, focusRingPath.get());
- wkDrawFocusRing(context, colorRef.get(), radius);
+ CGContextAddPath(context, focusRingPath);
+ wkDrawFocusRing(context, color, radius);
#ifdef BUILDING_ON_TIGER
CGContextEndTransparencyLayer(context);
#endif
@@ -63,16 +64,14 @@ void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int of
int radius = (width - 1) / 2;
offset += radius;
- RetainPtr<CGColorRef> colorRef;
- if (color.isValid())
- colorRef.adoptCF(createCGColor(color));
-
+ CGColorRef colorRef = color.isValid() ? cachedCGColor(color, ColorSpaceDeviceRGB) : 0;
+
RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable());
unsigned pathCount = paths.size();
for (unsigned i = 0; i < pathCount; i++)
CGPathAddPath(focusRingPath.get(), 0, paths[i].platformPath());
- drawFocusRingToContext(platformContext(), focusRingPath, colorRef, radius);
+ drawFocusRingToContext(platformContext(), focusRingPath.get(), colorRef, radius);
}
void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
@@ -82,16 +81,14 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
int radius = (width - 1) / 2;
offset += radius;
- RetainPtr<CGColorRef> colorRef;
- if (color.isValid())
- colorRef.adoptCF(createCGColor(color));
+ CGColorRef colorRef = color.isValid() ? cachedCGColor(color, ColorSpaceDeviceRGB) : 0;
RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable());
unsigned rectCount = rects.size();
for (unsigned i = 0; i < rectCount; i++)
CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rects[i], -offset, -offset));
- drawFocusRingToContext(platformContext(), focusRingPath, colorRef, radius);
+ drawFocusRingToContext(platformContext(), focusRingPath.get(), colorRef, radius);
}
#ifdef BUILDING_ON_TIGER // Post-Tiger's setCompositeOperation() is defined in GraphicsContextCG.cpp.
@@ -182,6 +179,7 @@ void GraphicsContext::drawLineForTextChecking(const IntPoint& point, int width,
// for transforms.
// Draw underline.
+ LocalCurrentGraphicsContext localContext(this);
NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
CGContextRef context = (CGContextRef)[currentContext graphicsPort];
CGContextSaveGState(context);
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index d4cd851..c4128ef 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -38,7 +38,6 @@
#import <QuartzCore/QuartzCore.h>
#import "RotateTransformOperation.h"
#import "ScaleTransformOperation.h"
-#import "StringBuilder.h"
#import "SystemTime.h"
#import "TranslateTransformOperation.h"
#import "WebLayer.h"
@@ -48,6 +47,7 @@
#import <wtf/CurrentTime.h>
#import <wtf/UnusedParam.h>
#import <wtf/RetainPtr.h>
+#import <wtf/text/StringConcatenate.h>
using namespace std;
@@ -248,7 +248,7 @@ static String propertyIdToString(AnimatedPropertyID property)
static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index)
{
- return animationName + String::format("_%d_%d", property, index);
+ return makeString(animationName, '_', String::number(property), '_', String::number(index));
}
static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction* timingFunction)
@@ -265,9 +265,7 @@ static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction* tim
static void setLayerBorderColor(PlatformLayer* layer, const Color& color)
{
- CGColorRef borderColor = createCGColor(color);
- [layer setBorderColor:borderColor];
- CGColorRelease(borderColor);
+ [layer setBorderColor:cachedCGColor(color, ColorSpaceDeviceRGB)];
}
static void clearBorderColor(PlatformLayer* layer)
@@ -277,9 +275,7 @@ static void clearBorderColor(PlatformLayer* layer)
static void setLayerBackgroundColor(PlatformLayer* layer, const Color& color)
{
- CGColorRef bgColor = createCGColor(color);
- [layer setBackgroundColor:bgColor];
- CGColorRelease(bgColor);
+ [layer setBackgroundColor:cachedCGColor(color, ColorSpaceDeviceRGB)];
}
static void clearLayerBackgroundColor(PlatformLayer* layer)
diff --git a/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
index 53d9b86..daf3b12 100644
--- a/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
+++ b/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
@@ -1161,11 +1161,11 @@ String GraphicsContext3D::getProgramInfoLog(Platform3DObject program)
makeContextCurrent();
GLint length;
::glGetProgramiv((GLuint) program, GL_INFO_LOG_LENGTH, &length);
-
+ if (!length)
+ return "";
+
GLsizei size;
GLchar* info = (GLchar*) fastMalloc(length);
- if (!info)
- return "";
::glGetProgramInfoLog((GLuint) program, length, &size, info);
String s(info);
@@ -1227,8 +1227,6 @@ String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
ASSERT(shader);
makeContextCurrent();
- GLint length;
- ::glGetShaderiv((GLuint) shader, GL_INFO_LOG_LENGTH, &length);
HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
@@ -1240,21 +1238,19 @@ String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
if (entry.isValid) {
GLint length;
::glGetShaderiv((GLuint) shader, GL_INFO_LOG_LENGTH, &length);
+ if (!length)
+ return "";
GLsizei size;
GLchar* info = (GLchar*) fastMalloc(length);
- if (!info)
- return "";
::glGetShaderInfoLog((GLuint) shader, length, &size, info);
String s(info);
fastFree(info);
return s;
- }
- else {
+ } else
return entry.log;
- }
}
String GraphicsContext3D::getShaderSource(Platform3DObject shader)
@@ -1449,6 +1445,11 @@ void GraphicsContext3D::synthesizeGLError(unsigned long error)
m_syntheticErrors.add(error);
}
+int GraphicsContext3D::getGraphicsResetStatusARB()
+{
+ return NO_ERROR;
+}
+
}
#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/platform/graphics/openvg/PathOpenVG.cpp b/WebCore/platform/graphics/openvg/PathOpenVG.cpp
index e74ea57..39a4b06 100644
--- a/WebCore/platform/graphics/openvg/PathOpenVG.cpp
+++ b/WebCore/platform/graphics/openvg/PathOpenVG.cpp
@@ -436,18 +436,6 @@ bool Path::hasCurrentPoint() const
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.
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index e7566eb..b049181 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -137,7 +137,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
dy1 = -ctxShadow->offset().y();
// expand the clip rect to include the text shadow as well
clip.adjust(dx1, dx2, dy1, dy2);
- clip.adjust(-ctxShadow->m_blurRadius, -ctxShadow->m_blurRadius, ctxShadow->m_blurRadius, ctxShadow->m_blurRadius);
+ clip.adjust(-ctxShadow->m_blurDistance, -ctxShadow->m_blurDistance, ctxShadow->m_blurDistance, ctxShadow->m_blurDistance);
}
p->save();
p->setClipRect(clip.toRect(), Qt::IntersectClip);
diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index 0756aa7..cda8606 100644
--- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -286,6 +286,11 @@ bool GraphicsContext3D::isErrorGeneratedOnOutOfBoundsAccesses() const
return false;
}
+int GraphicsContext3D::getGraphicsResetStatusARB()
+{
+ return NO_ERROR;
+}
+
GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow)
: m_attrs(attrs)
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index 7e4af40..8b34f51 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -204,6 +204,13 @@ public:
return shadow.m_type != ContextShadow::NoShadow;
}
+ inline void clearCurrentPath()
+ {
+ if (!currentPath.elementCount())
+ return;
+ currentPath = QPainterPath();
+ }
+
QRectF clipBoundingRect() const
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
@@ -248,8 +255,8 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
setPaintingDisabled(!context);
if (context) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor(), DeviceColorSpace);
- setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
+ setPlatformFillColor(fillColor(), ColorSpaceDeviceRGB);
+ setPlatformStrokeColor(strokeColor(), ColorSpaceDeviceRGB);
// Make sure we start with the correct join mode.
setLineJoin(MiterJoin);
@@ -533,7 +540,7 @@ void GraphicsContext::fillPath()
} else
p->fillPath(path, p->brush());
- m_data->currentPath = QPainterPath();
+ m_data->clearCurrentPath();
}
void GraphicsContext::strokePath()
@@ -566,7 +573,7 @@ void GraphicsContext::strokePath()
p->strokePath(path, pen);
} else
p->strokePath(path, pen);
- m_data->currentPath = QPainterPath();
+ m_data->clearCurrentPath();
}
static inline void drawRepeatPattern(QPainter* p, QPixmap* image, const FloatRect& rect, const bool repeatX, const bool repeatY)
@@ -722,7 +729,8 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
if (paintingDisabled() || !color.isValid())
return;
- Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight);
+ Path path;
+ path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
QPainter* p = m_data->p();
if (m_data->hasShadow()) {
p->translate(m_data->shadow.offset());
@@ -734,7 +742,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
void GraphicsContext::beginPath()
{
- m_data->currentPath = QPainterPath();
+ m_data->clearCurrentPath();
}
void GraphicsContext::addPath(const Path& path)
@@ -777,7 +785,7 @@ void GraphicsContext::clipPath(WindRule clipRule)
QPainter* p = m_data->p();
QPainterPath newPath = m_data->currentPath;
newPath.setFillRule(clipRule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
- p->setClipPath(newPath);
+ p->setClipPath(newPath, Qt::IntersectClip);
}
void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
@@ -835,8 +843,28 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool)
if (paintingDisabled())
return;
+ IntPoint startPoint = origin;
IntPoint endPoint = origin + IntSize(width, 0);
- drawLine(origin, endPoint);
+
+ // If paintengine type is X11 to avoid artifacts
+ // like bug https://bugs.webkit.org/show_bug.cgi?id=42248
+#if defined(Q_WS_X11)
+ QPainter* p = m_data->p();
+ if (p->paintEngine()->type() == QPaintEngine::X11) {
+ // If stroke thickness is odd we need decrease Y coordinate by 1 pixel,
+ // because inside method adjustLineToPixelBoundaries(...), which
+ // called from drawLine(...), Y coordinate will be increased by 0.5f
+ // and then inside Qt painting engine will be rounded to next greater
+ // integer value.
+ float strokeWidth = strokeThickness();
+ if (static_cast<int>(strokeWidth) % 2) {
+ startPoint.setY(startPoint.y() - 1);
+ endPoint.setY(endPoint.y() - 1);
+ }
+ }
+#endif // defined(Q_WS_X11)
+
+ drawLine(startPoint, endPoint);
}
void GraphicsContext::drawLineForTextChecking(const IntPoint&, int, TextCheckingLineStyle)
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
index 079d8ba..e0941f5 100644
--- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
@@ -37,6 +37,7 @@
#include <QtGui/qgraphicseffect.h>
#include <QtGui/qgraphicsitem.h>
#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicswidget.h>
#include <QtGui/qpainter.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qpixmapcache.h>
@@ -320,7 +321,7 @@ GraphicsLayerQtImpl::~GraphicsLayerQtImpl()
// our items automatically.
const QList<QGraphicsItem*> children = childItems();
QList<QGraphicsItem*>::const_iterator cit;
- for (cit = children.begin(); cit != children.end(); ++cit) {
+ for (cit = children.constBegin(); cit != children.constEnd(); ++cit) {
if (QGraphicsItem* item = *cit) {
if (scene())
scene()->removeItem(item);
@@ -523,7 +524,7 @@ void GraphicsLayerQtImpl::updateTransform()
const QList<QGraphicsItem*> children = childItems();
QList<QGraphicsItem*>::const_iterator it;
- for (it = children.begin(); it != children.end(); ++it)
+ for (it = children.constBegin(); it != children.constEnd(); ++it)
if (GraphicsLayerQtImpl* layer= toGraphicsLayerQtImpl(*it))
layer->updateTransform();
}
@@ -610,13 +611,13 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
if (!m_layer || m_changeMask == NoChanges)
goto afterLayerChanges;
- if (m_currentContent.contentType == HTMLContentType && (m_changeMask & ParentChange)) {
+ if (m_changeMask & ParentChange) {
// The WebCore compositor manages item ownership. We have to make sure graphicsview doesn't
// try to snatch that ownership.
if (!m_layer->parent() && !parentItem())
setParentItem(0);
else if (m_layer && m_layer->parent() && m_layer->parent()->nativeLayer() != parentItem())
- setParentItem(m_layer->parent()->nativeLayer());
+ setParentItem(m_layer->parent()->platformLayer());
}
if (m_changeMask & ChildrenChange) {
@@ -634,13 +635,13 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
const QSet<QGraphicsItem*> childrenToRemove = currentChildren - newChildren;
QSet<QGraphicsItem*>::const_iterator it;
- for (it = childrenToAdd.begin(); it != childrenToAdd.end(); ++it) {
+ for (it = childrenToAdd.constBegin(); it != childrenToAdd.constEnd(); ++it) {
if (QGraphicsItem* w = *it)
w->setParentItem(this);
}
QSet<QGraphicsItem*>::const_iterator rit;
- for (rit = childrenToRemove.begin(); rit != childrenToRemove.end(); ++rit) {
+ for (rit = childrenToRemove.constBegin(); rit != childrenToRemove.constEnd(); ++rit) {
if (GraphicsLayerQtImpl* w = toGraphicsLayerQtImpl(*rit))
w->setParentItem(0);
}
@@ -680,7 +681,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
if (scene())
scene()->update();
- if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | BackfaceVisibilityChange | PositionChange)) {
+ if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | BackfaceVisibilityChange | PositionChange | ParentChange)) {
// Due to the differences between the way WebCore handles transforms and the way Qt handles transforms,
// all these elements affect the transforms of all the descendants.
forceUpdateTransform = true;
@@ -737,6 +738,11 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
const QRect rect(m_layer->contentsRect());
if (m_state.contentsRect != rect) {
m_state.contentsRect = rect;
+ if (m_pendingContent.mediaLayer) {
+ QGraphicsWidget* widget = qobject_cast<QGraphicsWidget*>(m_pendingContent.mediaLayer.data());
+ if (widget)
+ widget->setGeometry(rect);
+ }
update();
}
}
@@ -804,7 +810,7 @@ afterLayerChanges:
children.append(m_state.maskLayer->platformLayer());
QList<QGraphicsItem*>::const_iterator it;
- for (it = children.begin(); it != children.end(); ++it) {
+ for (it = children.constBegin(); it != children.constEnd(); ++it) {
if (QGraphicsItem* item = *it) {
if (GraphicsLayerQtImpl* layer = toGraphicsLayerQtImpl(item))
layer->flushChanges(true, forceUpdateTransform);
@@ -850,6 +856,20 @@ void GraphicsLayerQt::setNeedsDisplayInRect(const FloatRect& rect)
m_impl->notifyChange(GraphicsLayerQtImpl::DisplayChange);
}
+void GraphicsLayerQt::setContentsNeedsDisplay()
+{
+ switch (m_impl->m_pendingContent.contentType) {
+ case GraphicsLayerQtImpl::MediaContentType:
+ if (!m_impl->m_pendingContent.mediaLayer)
+ return;
+ m_impl->m_pendingContent.mediaLayer.data()->update();
+ break;
+ default:
+ setNeedsDisplay();
+ break;
+ }
+}
+
/* \reimp (GraphicsLayer.h)
*/
void GraphicsLayerQt::setName(const String& name)
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
index 75ca498..ed535eb 100644
--- a/WebCore/platform/graphics/qt/GraphicsLayerQt.h
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
@@ -75,6 +75,7 @@ public:
virtual void resumeAnimations();
#endif // QT_NO_ANIMATION
virtual void setContentsToImage(Image*);
+ virtual void setContentsNeedsDisplay();
virtual void setContentsToMedia(PlatformLayer*);
virtual void setContentsBackgroundColor(const Color&);
#if ENABLE(3D_CANVAS)
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index ee01222..0cdc894 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -35,6 +35,7 @@
#include "StillImageQt.h"
#include "TransparencyLayer.h"
#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
#include <QBuffer>
#include <QColor>
@@ -68,7 +69,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
pen.setColor(Qt::black);
pen.setWidth(1);
pen.setCapStyle(Qt::FlatCap);
- pen.setJoinStyle(Qt::MiterJoin);
+ pen.setJoinStyle(Qt::SvgMiterJoin);
pen.setMiterLimit(10);
painter->setPen(pen);
QBrush brush = painter->brush();
@@ -79,7 +80,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
m_image = StillImage::createForRendering(&m_pixmap);
}
-ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, bool& success)
: m_data(size)
, m_size(size)
{
@@ -117,7 +118,7 @@ void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace,
if (destContext == context()) {
// We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first.
RefPtr<Image> copy = copyImage();
- destContext->drawImage(copy.get(), DeviceColorSpace, destRect, srcRect, op, useLowQualityScale);
+ destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale);
} else
destContext->drawImage(m_data.m_image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
}
@@ -139,7 +140,7 @@ void ImageBuffer::clip(GraphicsContext* context, const FloatRect& floatRect) con
if (!nativeImage)
return;
- IntRect rect(floatRect);
+ IntRect rect = enclosingIntRect(floatRect);
QPixmap alphaMask = *nativeImage;
if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height())
alphaMask = alphaMask.scaled(rect.width(), rect.height());
@@ -216,7 +217,7 @@ PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& i
const uchar* bits = image.bits();
#endif
- quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() + destx]);
+ quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() * 4 + destx * 4]);
if (multiplied == Unmultiplied) {
for (int y = 0; y < numRows; ++y) {
@@ -401,7 +402,8 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
}
buffer.close();
- return String::format("data:%s;base64,%s", mimeType.utf8().data(), data.toBase64().data());
+
+ return makeString("data:", mimeType, ";base64,", data.toBase64().data());
}
}
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
index 1a31d1e..962c931 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
@@ -27,6 +27,7 @@
#include "HTMLVideoElement.h"
#include "NetworkingContext.h"
#include "NotImplemented.h"
+#include "RenderVideo.h"
#include "TimeRanges.h"
#include "Widget.h"
#include "qwebframe.h"
@@ -42,6 +43,7 @@
#include <QPainter>
#include <QPoint>
#include <QRect>
+#include <QStyleOptionGraphicsItem>
#include <QTime>
#include <QTimer>
#include <QUrl>
@@ -49,6 +51,10 @@
#include <wtf/HashSet.h>
#include <wtf/text/CString.h>
+#if USE(ACCELERATED_COMPOSITING)
+#include "texmap/TextureMapperPlatformLayer.h"
+#endif
+
using namespace WTF;
namespace WebCore {
@@ -93,6 +99,8 @@ MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player)
, m_videoScene(new QGraphicsScene)
, m_networkState(MediaPlayer::Empty)
, m_readyState(MediaPlayer::HaveNothing)
+ , m_currentSize(0, 0)
+ , m_naturalSize(RenderVideo::defaultSize())
, m_isVisible(false)
, m_isSeeking(false)
, m_composited(false)
@@ -125,8 +133,7 @@ MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player)
this, SLOT(nativeSizeChanged(QSizeF)));
// Grab the player control
- QMediaService* service = m_mediaPlayer->service();
- if (service) {
+ if (QMediaService* service = m_mediaPlayer->service()) {
m_mediaPlayerControl = qobject_cast<QMediaPlayerControl *>(
service->requestControl(QMediaPlayerControl_iid));
}
@@ -134,6 +141,10 @@ MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player)
MediaPlayerPrivateQt::~MediaPlayerPrivateQt()
{
+ m_mediaPlayer->disconnect(this);
+ m_mediaPlayer->stop();
+ m_mediaPlayer->setMedia(QMediaContent());
+
delete m_mediaPlayer;
delete m_videoScene;
}
@@ -330,8 +341,7 @@ float MediaPlayerPrivateQt::duration() const
float MediaPlayerPrivateQt::currentTime() const
{
- float currentTime = m_mediaPlayer->position() / 1000.0f;
- return currentTime;
+ return m_mediaPlayer->position() / 1000.0f;
}
PassRefPtr<TimeRanges> MediaPlayerPrivateQt::buffered() const
@@ -437,8 +447,15 @@ void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State state)
}
}
-void MediaPlayerPrivateQt::nativeSizeChanged(const QSizeF&)
+void MediaPlayerPrivateQt::nativeSizeChanged(const QSizeF& size)
{
+ LOG(Media, "MediaPlayerPrivateQt::naturalSizeChanged(%dx%d)",
+ size.toSize().width(), size.toSize().height());
+
+ if (!size.isValid())
+ return;
+
+ m_naturalSize = size.toSize();
m_webCorePlayer->sizeChanged();
}
@@ -466,7 +483,7 @@ void MediaPlayerPrivateQt::seekTimeout()
void MediaPlayerPrivateQt::positionChanged(qint64)
{
- // Only propogate this event if we are seeking
+ // Only propagate this event if we are seeking
if (m_isSeeking && m_queuedSeek == -1) {
m_webCorePlayer->timeChanged();
m_isSeeking = false;
@@ -546,6 +563,9 @@ void MediaPlayerPrivateQt::updateStates()
void MediaPlayerPrivateQt::setSize(const IntSize& size)
{
+ LOG(Media, "MediaPlayerPrivateQt::setSize(%dx%d)",
+ size.width(), size.height());
+
if (size == m_currentSize)
return;
@@ -555,10 +575,15 @@ void MediaPlayerPrivateQt::setSize(const IntSize& size)
IntSize MediaPlayerPrivateQt::naturalSize() const
{
- if (!hasVideo() || m_readyState < MediaPlayer::HaveMetadata)
+ if (!hasVideo() || m_readyState < MediaPlayer::HaveMetadata) {
+ LOG(Media, "MediaPlayerPrivateQt::naturalSize() -> 0x0 (!hasVideo || !haveMetaData)");
return IntSize();
+ }
- return IntSize(m_videoItem->nativeSize().toSize());
+ LOG(Media, "MediaPlayerPrivateQt::naturalSize() -> %dx%d (m_naturalSize)",
+ m_naturalSize.width(), m_naturalSize.height());
+
+ return m_naturalSize;
}
void MediaPlayerPrivateQt::paint(GraphicsContext* context, const IntRect& rect)
@@ -573,10 +598,7 @@ void MediaPlayerPrivateQt::paint(GraphicsContext* context, const IntRect& rect)
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());
}
@@ -585,7 +607,41 @@ void MediaPlayerPrivateQt::repaint()
m_webCorePlayer->repaint();
}
-#if USE(ACCELERATED_COMPOSITING)
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+
+class TextureMapperVideoLayerQt : public virtual TextureMapperVideoLayer {
+public:
+ TextureMapperVideoLayerQt(QGraphicsVideoItem* videoItem)
+ : m_videoItem(videoItem)
+ {
+ }
+
+ virtual void setPlatformLayerClient(TextureMapperLayerClient* client)
+ {
+ m_client = client;
+ }
+
+ virtual void paint(GraphicsContext* context)
+ {
+ if (!m_videoItem)
+ return;
+
+ QStyleOptionGraphicsItem opt;
+ opt.exposedRect = m_videoItem.data()->sceneBoundingRect();
+ opt.rect = opt.exposedRect.toRect();
+ m_videoItem.data()->paint(context->platformContext(), &opt);
+ }
+
+ virtual IntSize size() const
+ {
+ return m_videoItem ? IntSize(m_videoItem.data()->size().width(), m_videoItem.data()->size().height()) : IntSize();
+ }
+
+ QWeakPointer<QGraphicsVideoItem> m_videoItem;
+ TextureMapperLayerClient* m_client;
+};
+
+
void MediaPlayerPrivateQt::acceleratedRenderingStateChanged()
{
MediaPlayerClient* client = m_webCorePlayer->mediaPlayerClient();
@@ -595,14 +651,12 @@ void MediaPlayerPrivateQt::acceleratedRenderingStateChanged()
m_composited = composited;
if (composited)
- m_videoScene->removeItem(m_videoItem);
- else
- m_videoScene->addItem(m_videoItem);
+ m_platformLayer = new TextureMapperVideoLayerQt(m_videoItem);
}
PlatformLayer* MediaPlayerPrivateQt::platformLayer() const
{
- return m_composited ? m_videoItem : 0;
+ return m_composited ? m_platformLayer.get() : 0;
}
#endif
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
index 179bf2a..93c9d1c 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
@@ -33,6 +33,8 @@ QT_END_NAMESPACE
namespace WebCore {
+class TextureMapperVideoLayer;
+
class MediaPlayerPrivateQt : public QObject, public MediaPlayerPrivateInterface {
Q_OBJECT
@@ -91,12 +93,18 @@ public:
bool supportsFullscreen() const { return false; }
#if USE(ACCELERATED_COMPOSITING)
+#if USE(TEXTURE_MAPPER)
// 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;
+#else
+ virtual bool supportsAcceleratedRendering() const { return false; }
+ virtual void acceleratedRenderingStateChanged() { }
+ virtual PlatformLayer* platformLayer() const { return 0; }
+#endif
#endif
virtual PlatformMedia platformMedia() const;
@@ -125,11 +133,15 @@ private:
QMediaPlayerControl* m_mediaPlayerControl;
QGraphicsVideoItem* m_videoItem;
QGraphicsScene* m_videoScene;
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+ OwnPtr<TextureMapperVideoLayer> m_platformLayer;
+#endif
mutable MediaPlayer::NetworkState m_networkState;
mutable MediaPlayer::ReadyState m_readyState;
IntSize m_currentSize;
+ IntSize m_naturalSize;
bool m_isVisible;
bool m_isSeeking;
bool m_composited;
diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp
index b8b9d5e..508ba6a 100644
--- a/WebCore/platform/graphics/qt/PathQt.cpp
+++ b/WebCore/platform/graphics/qt/PathQt.cpp
@@ -335,6 +335,8 @@ void Path::addEllipse(const FloatRect& r)
void Path::clear()
{
+ if (!m_path.elementCount())
+ return;
m_path = QPainterPath();
}
@@ -355,41 +357,6 @@ FloatPoint Path::currentPoint() const
return m_path.currentPosition();
}
-String Path::debugString() const
-{
- QString ret;
- for (int i = 0; i < m_path.elementCount(); ++i) {
- const QPainterPath::Element &cur = m_path.elementAt(i);
-
- switch (cur.type) {
- case QPainterPath::MoveToElement:
- ret += QString(QLatin1String("M%1,%2 ")).arg(cur.x, 0, 'f', 2).arg(cur.y, 0, 'f', 2);
- break;
- case QPainterPath::LineToElement:
- ret += QString(QLatin1String("L%1,%2 ")).arg(cur.x, 0, 'f', 2).arg(cur.y, 0, 'f', 2);
- break;
- case QPainterPath::CurveToElement:
- {
- const QPainterPath::Element &c1 = m_path.elementAt(i + 1);
- const QPainterPath::Element &c2 = m_path.elementAt(i + 2);
-
- Q_ASSERT(c1.type == QPainterPath::CurveToDataElement);
- Q_ASSERT(c2.type == QPainterPath::CurveToDataElement);
-
- ret += QString(QLatin1String("C%1,%2,%3,%4,%5,%6 ")).arg(cur.x, 0, 'f', 2).arg(cur.y, 0, 'f', 2).arg(c1.x, 0, 'f', 2)
- .arg(c1.y, 0, 'f', 2).arg(c2.x, 0, 'f', 2).arg(c2.y, 0, 'f', 2);
- i += 2;
- break;
- }
- case QPainterPath::CurveToDataElement:
- Q_ASSERT(false);
- break;
- }
- }
-
- return ret.trimmed();
-}
-
void Path::apply(void* info, PathApplierFunction function) const
{
PathElement pelement;
diff --git a/WebCore/platform/graphics/qt/TextureMapperQt.cpp b/WebCore/platform/graphics/qt/TextureMapperQt.cpp
new file mode 100644
index 0000000..9236dae
--- /dev/null
+++ b/WebCore/platform/graphics/qt/TextureMapperQt.cpp
@@ -0,0 +1,225 @@
+/*
+ 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 "texmap/TextureMapper.h"
+
+#include <QtCore/qdebug.h>
+#include <QtGui/qpaintengine.h>
+#include <QtGui/qpixmap.h>
+
+#ifdef QT_OPENGL_LIB
+# include "opengl/TextureMapperGL.h"
+#endif
+
+namespace WebCore {
+
+class BitmapTextureQt : public BitmapTexture {
+ friend class TextureMapperQt;
+public:
+ BitmapTextureQt() {}
+ virtual void destroy();
+ virtual IntSize size() const { return IntSize(m_pixmap.width(), m_pixmap.height()); }
+ virtual void reset(const IntSize&, bool opaque);
+ virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect);
+ virtual void endPaint();
+ virtual void setContentsToImage(Image*);
+ virtual bool save(const String& path);
+ virtual bool isValid() const { return !m_pixmap.isNull(); }
+ virtual bool allowOfflineTextureUpload() const { return true; }
+ IntRect sourceRect() const { return IntRect(0, 0, contentSize().width(), contentSize().height()); }
+private:
+ QPainter m_painter;
+ QPixmap m_pixmap;
+};
+
+class TextureMapperQt : public TextureMapper {
+public:
+ virtual void drawTexture(const BitmapTexture& texture, const IntRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture);
+ virtual void bindSurface(BitmapTexture* surface);
+ virtual void setClip(const IntRect&);
+ virtual bool allowSurfaceForRoot() const { return false; }
+ TextureMapperQt(GraphicsContext* context);
+ virtual const char* type() const { return "TextureMapperQt"; }
+ virtual PassRefPtr<BitmapTexture> createTexture();
+
+ static void initialize(QPainter* painter)
+ {
+ painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
+ }
+
+private:
+ QPainter* m_painter;
+ RefPtr<BitmapTextureQt> m_currentSurface;
+};
+
+void BitmapTextureQt::destroy()
+{
+ if (m_pixmap.paintingActive())
+ qFatal("Destroying an active pixmap");
+ m_pixmap = QPixmap();
+}
+
+void BitmapTextureQt::reset(const IntSize& size, bool isOpaque)
+{
+ BitmapTexture::reset(size, isOpaque);
+
+ if (size.width() > m_pixmap.size().width() || size.height() > m_pixmap.size().height() || m_pixmap.isNull())
+ m_pixmap = QPixmap(size.width(), size.height());
+ if (!isOpaque)
+ m_pixmap.fill(Qt::transparent);
+}
+
+PlatformGraphicsContext* BitmapTextureQt::beginPaint(const IntRect& dirtyRect)
+{
+ m_painter.begin(&m_pixmap);
+ TextureMapperQt::initialize(&m_painter);
+ m_painter.setCompositionMode(QPainter::CompositionMode_Clear);
+ m_painter.fillRect(QRect(dirtyRect), Qt::transparent);
+ m_painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ return &m_painter;
+}
+
+void BitmapTextureQt::endPaint()
+{
+ m_painter.end();
+}
+
+bool BitmapTextureQt::save(const String& path)
+{
+ return m_pixmap.save(path, "PNG");
+}
+
+void BitmapTextureQt::setContentsToImage(Image* image)
+{
+ if (!image)
+ return;
+ const QPixmap* pixmap = image->nativeImageForCurrentFrame();
+ if (!pixmap)
+ return;
+ BitmapTexture::reset(pixmap->size(), !pixmap->hasAlphaChannel());
+ m_pixmap = *pixmap;
+}
+
+void TextureMapperQt::setClip(const IntRect& rect)
+{
+ QPainter* painter = m_currentSurface ? &m_currentSurface->m_painter : m_painter;
+ painter->setClipRect(rect);
+}
+
+TextureMapperQt::TextureMapperQt(GraphicsContext* context)
+ : TextureMapper(context)
+ , m_painter(context->platformContext())
+ , m_currentSurface(0)
+{
+ TextureMapperQt::initialize(m_painter);
+}
+
+void TextureMapperQt::bindSurface(BitmapTexture* surface)
+{
+ if (m_currentSurface == surface)
+ return;
+ if (m_currentSurface)
+ m_currentSurface->m_painter.end();
+ if (!surface) {
+ m_currentSurface = 0;
+ return;
+ }
+ BitmapTextureQt* surfaceQt = static_cast<BitmapTextureQt*>(surface);
+ if (!surfaceQt->m_painter.isActive())
+ surfaceQt->m_painter.begin(&surfaceQt->m_pixmap);
+ m_currentSurface = surfaceQt;
+}
+
+
+void TextureMapperQt::drawTexture(const BitmapTexture& texture, const IntRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture)
+{
+ const BitmapTextureQt& textureQt = static_cast<const BitmapTextureQt&>(texture);
+ QPainter* painter = m_painter;
+ QPixmap pixmap = textureQt.m_pixmap;
+ if (m_currentSurface)
+ painter = &m_currentSurface->m_painter;
+
+ if (maskTexture && maskTexture->isValid()) {
+ const BitmapTextureQt* mask = static_cast<const BitmapTextureQt*>(maskTexture);
+ QPixmap intermediatePixmap(pixmap.size());
+ intermediatePixmap.fill(Qt::transparent);
+ QPainter maskPainter(&intermediatePixmap);
+ maskPainter.setCompositionMode(QPainter::CompositionMode_Source);
+ maskPainter.drawPixmap(0, 0, pixmap);
+ maskPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ maskPainter.drawPixmap(QRect(0, 0, pixmap.width(), pixmap.height()), mask->m_pixmap, mask->sourceRect());
+ maskPainter.end();
+ pixmap = intermediatePixmap;
+ }
+
+ const qreal prevOpacity = painter->opacity();
+ const QTransform prevTransform = painter->transform();
+ painter->setOpacity(opacity);
+ painter->setTransform(matrix, true);
+ painter->drawPixmap(targetRect, pixmap, textureQt.sourceRect());
+ painter->setTransform(prevTransform);
+ painter->setOpacity(prevOpacity);
+}
+
+PassRefPtr<TextureMapper> TextureMapper::create(GraphicsContext* context)
+{
+#ifdef QT_OPENGL_LIB
+ if (context->platformContext()->paintEngine()->type() == QPaintEngine::OpenGL2)
+ return adoptRef(new TextureMapperGL(context));
+#endif
+ return adoptRef(new TextureMapperQt(context));
+}
+
+
+PassRefPtr<BitmapTexture> TextureMapperQt::createTexture()
+{
+ return adoptRef(new BitmapTextureQt());
+}
+
+#ifdef QT_OPENGL_LIB
+class RGBA32PremultimpliedBufferQt : public RGBA32PremultimpliedBuffer {
+public:
+ virtual PlatformGraphicsContext* beginPaint(const IntRect& rect, bool opaque)
+ {
+ // m_image is only using during paint, it's safe to override it.
+ m_image = QImage(rect.size().width(), rect.size().height(), QImage::Format_ARGB32_Premultiplied);
+ if (!opaque)
+ m_image.fill(0);
+ m_painter.begin(&m_image);
+ TextureMapperQt::initialize(&m_painter);
+ m_painter.translate(-rect.x(), -rect.y());
+ return &m_painter;
+ }
+
+ virtual void endPaint() { m_painter.end(); }
+ virtual const void* data() const { return m_image.constBits(); }
+
+private:
+ QPainter m_painter;
+ QImage m_image;
+};
+
+PassRefPtr<RGBA32PremultimpliedBuffer> RGBA32PremultimpliedBuffer::create()
+{
+ return adoptRef(new RGBA32PremultimpliedBufferQt());
+}
+
+#endif
+};
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index 2be7dc5..143d667 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -45,6 +45,8 @@
#include "SkColorPriv.h"
#include "SkiaUtils.h"
+#include <wtf/text/StringConcatenate.h>
+
using namespace std;
namespace WebCore {
@@ -58,7 +60,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
{
}
-ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, bool& success)
: m_data(size)
, m_size(size)
{
@@ -290,6 +292,7 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint&
void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
{
+ context()->platformContext()->prepareForSoftwareDraw();
putImageData<Unmultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
}
@@ -311,7 +314,7 @@ String ImageBuffer::toDataURL(const String&, const double*) const
base64EncodedData.append('\0');
// And the resulting string.
- return String::format("data:image/png;base64,%s", base64EncodedData.data());
+ return makeString("data:image/png;base64,", base64EncodedData.data());
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp
index e123256..23e7be6 100644
--- a/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -143,9 +143,7 @@ static ResamplingMode computeResamplingMode(PlatformContextSkia* platformContext
// Everything else gets resampled.
// If the platform context permits high quality interpolation, use it.
- // High quality interpolation only enabled for scaling and translation.
- if (platformContext->interpolationQuality() == InterpolationHigh
- && !(platformContext->canvas()->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)))
+ if (platformContext->interpolationQuality() == InterpolationHigh)
return RESAMPLE_AWESOME;
return RESAMPLE_LINEAR;
@@ -175,12 +173,8 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm
&& srcIRect.height() == bitmap.height();
// We will always draw in integer sizes, so round the destination rect.
- // First we need to apply canvas transformation matrix to get desired size of
- // resampled image.
- SkRect destRectTransformed;
- canvas.getTotalMatrix().mapRect(&destRectTransformed, destRect);
SkIRect destRectRounded;
- destRectTransformed.round(&destRectRounded);
+ destRect.round(&destRectRounded);
SkIRect resizedImageRect = // Represents the size of the resized image.
{ 0, 0, destRectRounded.width(), destRectRounded.height() };
@@ -194,10 +188,7 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm
// Compute the visible portion of our rect.
SkRect destBitmapSubsetSk;
ClipRectToCanvas(canvas, destRect, &destBitmapSubsetSk);
- // Determine size of resampled image based on clipped destination rect.
- SkRect destBitmapSubsetSkTransformed;
- canvas.getTotalMatrix().mapRect(&destBitmapSubsetSkTransformed, destBitmapSubsetSk);
- destBitmapSubsetSkTransformed.offset(-destBitmapSubsetSkTransformed.fLeft, -destBitmapSubsetSkTransformed.fTop);
+ destBitmapSubsetSk.offset(-destRect.fLeft, -destRect.fTop);
// The matrix inverting, etc. could have introduced rounding error which
// causes the bounds to be outside of the resized bitmap. We round outward
@@ -205,7 +196,7 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm
// need, and then clamp to the bitmap bounds so we don't get any invalid
// data.
SkIRect destBitmapSubsetSkI;
- destBitmapSubsetSkTransformed.roundOut(&destBitmapSubsetSkI);
+ destBitmapSubsetSk.roundOut(&destBitmapSubsetSkI);
if (!destBitmapSubsetSkI.intersect(resizedImageRect))
return; // Resized image does not intersect.
diff --git a/WebCore/platform/graphics/skia/PathSkia.cpp b/WebCore/platform/graphics/skia/PathSkia.cpp
index 12241f8..89323c4 100644
--- a/WebCore/platform/graphics/skia/PathSkia.cpp
+++ b/WebCore/platform/graphics/skia/PathSkia.cpp
@@ -227,62 +227,6 @@ void Path::transform(const AffineTransform& xform)
m_path->transform(xform);
}
-String Path::debugString() const
-{
- String result;
-
- SkPath::Iter iter(*m_path, false);
- SkPoint pts[4];
-
- int numPoints = m_path->getPoints(0, 0);
- SkPath::Verb verb;
-
- do {
- verb = iter.next(pts);
- switch (verb) {
- case SkPath::kMove_Verb:
- result += String::format("M%.2f,%.2f ", pts[0].fX, pts[0].fY);
- numPoints -= 1;
- break;
- case SkPath::kLine_Verb:
- if (!iter.isCloseLine()) {
- result += String::format("L%.2f,%.2f ", pts[1].fX, pts[1].fY);
- numPoints -= 1;
- }
- break;
- case SkPath::kQuad_Verb:
- result += String::format("Q%.2f,%.2f,%.2f,%.2f ",
- pts[1].fX, pts[1].fY,
- pts[2].fX, pts[2].fY);
- numPoints -= 2;
- break;
- case SkPath::kCubic_Verb:
- result += String::format("C%.2f,%.2f,%.2f,%.2f,%.2f,%.2f ",
- pts[1].fX, pts[1].fY,
- pts[2].fX, pts[2].fY,
- pts[3].fX, pts[3].fY);
- numPoints -= 3;
- break;
- case SkPath::kClose_Verb:
- result += "Z ";
- break;
- case SkPath::kDone_Verb:
- break;
- }
- } while (verb != SkPath::kDone_Verb);
-
- // If you have a path that ends with an M, Skia will not iterate the
- // trailing M. That's nice of it, but Apple's paths output the trailing M
- // and we want out layout dumps to look like theirs
- if (numPoints) {
- ASSERT(numPoints==1);
- m_path->getLastPt(pts);
- result += String::format("M%.2f,%.2f ", pts[0].fX, pts[0].fY);
- }
-
- return result.stripWhiteSpace();
-}
-
// Computes the bounding box for the stroke and style currently selected into
// the given bounding box. This also takes into account the stroke width.
static FloatRect boundingBoxForCurrentStroke(const GraphicsContext* context)
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index b469312..3f9e4c1 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -34,12 +34,10 @@
#include "AffineTransform.h"
#include "DrawingBuffer.h"
-#include "GLES2Canvas.h"
#include "GraphicsContext.h"
#include "GraphicsContext3D.h"
#include "ImageBuffer.h"
#include "NativeImageSkia.h"
-#include "SharedGraphicsContext3D.h"
#include "SkiaUtils.h"
#include "Texture.h"
#include "TilingData.h"
@@ -56,6 +54,11 @@
#include <wtf/OwnArrayPtr.h>
#include <wtf/Vector.h>
+#if ENABLE(ACCELERATED_2D_CANVAS)
+#include "GLES2Canvas.h"
+#include "SharedGraphicsContext3D.h"
+#endif
+
namespace WebCore {
extern bool isPathSkiaSafe(const SkMatrix& transform, const SkPath& path);
@@ -207,7 +210,9 @@ PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas)
: m_canvas(canvas)
, m_drawingToImageBuffer(false)
, m_useGPU(false)
+#if ENABLE(ACCELERATED_2D_CANVAS)
, m_gpuCanvas(0)
+#endif
, m_backingStoreState(None)
{
m_stateStack.append(State());
@@ -216,8 +221,10 @@ PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas)
PlatformContextSkia::~PlatformContextSkia()
{
+#if ENABLE(ACCELERATED_2D_CANVAS)
if (m_gpuCanvas)
m_gpuCanvas->drawingBuffer()->setWillPublishCallback(0);
+#endif
}
void PlatformContextSkia::setCanvas(skia::PlatformCanvas* canvas)
@@ -705,6 +712,7 @@ private:
void PlatformContextSkia::setSharedGraphicsContext3D(SharedGraphicsContext3D* context, DrawingBuffer* drawingBuffer, const WebCore::IntSize& size)
{
+#if ENABLE(ACCELERATED_2D_CANVAS)
if (context && drawingBuffer) {
m_useGPU = true;
m_gpuCanvas = new GLES2Canvas(context, drawingBuffer, size);
@@ -716,6 +724,7 @@ void PlatformContextSkia::setSharedGraphicsContext3D(SharedGraphicsContext3D* co
m_gpuCanvas.clear();
m_useGPU = false;
}
+#endif
}
void PlatformContextSkia::prepareForSoftwareDraw() const
@@ -808,6 +817,7 @@ void PlatformContextSkia::markDirtyRect(const IntRect& rect)
void PlatformContextSkia::uploadSoftwareToHardware(CompositeOperator op) const
{
+#if ENABLE(ACCELERATED_2D_CANVAS)
const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(false);
SkAutoLockPixels lock(bitmap);
SharedGraphicsContext3D* context = m_gpuCanvas->context();
@@ -816,7 +826,7 @@ void PlatformContextSkia::uploadSoftwareToHardware(CompositeOperator op) const
m_uploadTexture->updateSubRect(bitmap.getPixels(), m_softwareDirtyRect);
AffineTransform identity;
- gpuCanvas()->drawTexturedRect(m_uploadTexture.get(), m_softwareDirtyRect, m_softwareDirtyRect, identity, 1.0, DeviceColorSpace, op);
+ gpuCanvas()->drawTexturedRect(m_uploadTexture.get(), m_softwareDirtyRect, m_softwareDirtyRect, identity, 1.0, ColorSpaceDeviceRGB, op);
// Clear out the region of the software canvas we just uploaded.
m_canvas->save();
m_canvas->resetMatrix();
@@ -825,10 +835,12 @@ void PlatformContextSkia::uploadSoftwareToHardware(CompositeOperator op) const
m_canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
m_canvas->restore();
m_softwareDirtyRect.setWidth(0); // Clear dirty rect.
+#endif
}
void PlatformContextSkia::readbackHardwareToSoftware() const
{
+#if ENABLE(ACCELERATED_2D_CANVAS)
const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(true);
SkAutoLockPixels lock(bitmap);
int width = bitmap.width(), height = bitmap.height();
@@ -850,6 +862,7 @@ void PlatformContextSkia::readbackHardwareToSoftware() const
}
}
m_softwareDirtyRect.unite(IntRect(0, 0, width, height)); // Mark everything as dirty.
+#endif
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h
index eb03224..84e5d78 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -183,8 +183,11 @@ public:
bool canvasClipApplied() const;
bool useGPU() { return m_useGPU; }
void setSharedGraphicsContext3D(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&);
+#if ENABLE(ACCELERATED_2D_CANVAS)
GLES2Canvas* gpuCanvas() const { return m_gpuCanvas.get(); }
-
+#else
+ GLES2Canvas* gpuCanvas() const { return 0; }
+#endif
// Call these before making a call that manipulates the underlying
// skia::PlatformCanvas or WebCore::GLES2Canvas
void prepareForSoftwareDraw() const;
@@ -224,9 +227,11 @@ private:
FloatSize m_imageResamplingHintDstSize;
bool m_drawingToImageBuffer;
bool m_useGPU;
+#if ENABLE(ACCELERATED_2D_CANVAS)
OwnPtr<GLES2Canvas> m_gpuCanvas;
- mutable enum { None, Software, Mixed, Hardware } m_backingStoreState;
mutable RefPtr<Texture> m_uploadTexture;
+#endif
+ mutable enum { None, Software, Mixed, Hardware } m_backingStoreState;
mutable IntRect m_softwareDirtyRect;
};
diff --git a/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
new file mode 100644
index 0000000..cf90cb1
--- /dev/null
+++ b/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
@@ -0,0 +1,1444 @@
+/*
+ Copyright (C) 2009 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 "GraphicsLayerTextureMapper.h"
+
+#include "CurrentTime.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "HashMap.h"
+#include "Image.h"
+#include "RefCounted.h"
+#include "TextureMapper.h"
+#include "TextureMapperPlatformLayer.h"
+#include "Timer.h"
+#include "TransformOperations.h"
+#include "TranslateTransformOperation.h"
+#include "UnitBezier.h"
+
+#define DEBUG_TEXMAP_FPS 0
+
+namespace WebCore {
+
+struct TexmapPaintOptions {
+ BitmapTexture* surface;
+ TextureMapper* textureMapper;
+ GraphicsContext* context;
+ TextureMapperNode* rootLayer;
+ float opacity;
+ IntRect scissorRect;
+ IntRect visibleRect;
+ bool isSurface;
+};
+class TextureMapperCache {
+public:
+ void mark(BitmapTexture* texture);
+
+ class Entry {
+ public:
+ RefPtr<BitmapTexture> texture;
+ Entry() : previousCost(0) { }
+ inline int calculateCost() const
+ {
+ if (!texture || !texture->isValid())
+ return 0;
+ const IntSize textureSize = texture->size();
+ // an image's cost in bytes is width * height * bytes per pixel (4).
+ return textureSize.width() * textureSize.height() * 4;
+ }
+ Entry(BitmapTexture* newTexture)
+ : texture(newTexture)
+ {
+ }
+ bool operator==(const Entry& other) const { return texture == other.texture; }
+ int previousCost;
+ };
+
+ TextureMapperCache() : m_totalCost(0) {}
+
+ void purge();
+ Vector<Entry> m_data;
+ int m_totalCost;
+#ifndef TEXMAP_TEXTURE_CACHE_KBS
+#define TEXMAP_TEXTURE_CACHE_KBS 24 * 1024
+#endif
+ static const int MaxCost = TEXMAP_TEXTURE_CACHE_KBS * 1024;
+ static const int PurgeAmount = MaxCost / 4;
+};
+
+
+void TextureMapperCache::purge()
+{
+ // If this is in the GL implementation, we need an active GL context, because we might call glDeleteTextures.
+ const int size = m_data.size();
+
+ if (m_totalCost <= TextureMapperCache::MaxCost)
+ return;
+
+ // Ensure that we have the right count. It might be inaccurate if content changed size.
+ // We only do this when we're actually ready to purge.
+ m_totalCost = 0;
+ for (int i = 0; i < size; ++i)
+ m_totalCost += m_data[i].calculateCost();
+
+ for (int i = size-1; i >= 0 && m_totalCost > TextureMapperCache::MaxCost - TextureMapperCache::PurgeAmount; --i) {
+ Entry& entry = m_data[i];
+ if (entry.texture->isLocked() || !entry.texture->isValid())
+ continue;
+ m_totalCost -= entry.previousCost;
+ entry.texture->destroy();
+ m_data.remove(i);
+ }
+}
+
+void TextureMapperCache::mark(BitmapTexture* texture)
+{
+ if (!texture || !texture->isValid())
+ return;
+
+ Entry entry(texture);
+ size_t index = m_data.find(entry);
+ if (!index)
+ return;
+
+ if (index < m_data.size())
+ m_data.remove(index);
+ const int cost = entry.calculateCost();
+ m_totalCost -= entry.previousCost;
+ m_totalCost += (entry.previousCost = cost);
+ m_data.prepend(entry);
+}
+
+TextureMapperCache gTextureMapperCache;
+
+class TextureMapperCacheLock {
+public:
+ TextureMapperCacheLock(BitmapTexture* texture) : m_texture(texture)
+ {
+ if (m_texture)
+ m_texture->lock();
+ }
+ ~TextureMapperCacheLock()
+ {
+ if (m_texture)
+ m_texture->unlock();
+ }
+
+private:
+ RefPtr<BitmapTexture> m_texture;
+};
+
+class TextureMapperNode : public TextureMapperContentLayer {
+
+public:
+ // This set of flags help us defer which properties of the layer have been
+ // 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),
+
+ 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),
+
+ ReplicaLayerChange = (1L << 20)
+ };
+
+ // The compositor lets us special-case images and colors, so we try to do so.
+ enum StaticContentType { HTMLContentType, DirectImageContentType, ColorContentType, MediaContentType, Canvas3DContentType};
+
+ TextureMapperNode* rootLayer();
+
+ TextureMapperNode(GraphicsLayerTextureMapper* newLayer);
+ virtual ~TextureMapperNode();
+
+ void clearDirectImage();
+ void computeTransformations();
+ IntSize nearestSurfaceSize() const;
+ void computeReplicaTransform();
+ void computeLayerType();
+ void computeLocalTransform();
+ void flattenTo2DSpaceIfNecessary();
+ void initializeTextureMapper(TextureMapper*);
+ void invalidateTransform();
+ void notifyChange(ChangeMask);
+ void syncCompositingState(bool recurse);
+ void performPostSyncOperations();
+ void setNeedsDisplay();
+ void setNeedsDisplayInRect(IntRect);
+ virtual void cleanupTextureMapper();
+
+ void paintRecursive(TexmapPaintOptions options);
+ void paintSelf(const TexmapPaintOptions& options);
+ void uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect);
+
+ int countDescendantsWithContent() const;
+ bool hasSurfaceDescendants() const;
+
+ IntSize size() const { return m_size; }
+
+ virtual void setPlatformLayerClient(TextureMapperLayerClient*);
+ virtual void paint(GraphicsContext*, const IntSize&, const IntRect& targetRect, const IntRect& exposedRect, const TransformationMatrix& transform, float opacity);
+
+ static TextureMapperNode* toTextureMapperNode(GraphicsLayer*);
+public:
+ GraphicsLayerTextureMapper* m_layer;
+ const char* m_lastTextureMapperType;
+ RefPtr<TextureMapper> m_lastTextureMapper;
+ struct TransformData {
+ TransformationMatrix base, target, replica, forDescendants, perspective, local;
+ IntRect targetBoundingRect;
+ float centerZ;
+ bool dirty, localDirty, perspectiveDirty;
+ IntRect boundingRectFromRoot;
+ TransformData() : dirty(true), localDirty(true), perspectiveDirty(true) { }
+ };
+
+ TransformData m_transforms;
+
+ enum LayerType {
+ DefaultLayer,
+ RootLayer,
+ ScissorLayer,
+ ClipLayer,
+ TransparencyLayer
+ };
+
+ LayerType m_layerType;
+
+ struct ContentData {
+ IntRect needsDisplayRect;
+ bool needsDisplay;
+ Color backgroundColor;
+
+ StaticContentType contentType;
+ RefPtr<Image> image;
+ TextureMapperVideoLayer* media;
+
+ ContentData()
+ : needsDisplay(false)
+ , contentType(HTMLContentType)
+ , image(0)
+ , media(0)
+ {
+ }
+
+ };
+
+ inline IntRect targetRect() const
+ {
+ return m_currentContent.contentType == HTMLContentType ? entireRect() : m_state.contentsRect;
+ }
+
+ inline IntRect entireRect() const
+ {
+ return IntRect(0, 0, m_size.width(), m_size.height());
+ }
+
+ inline IntRect replicaRect() const
+ {
+ return m_layerType == TransparencyLayer ? IntRect(0, 0, m_nearestSurfaceSize.width(), m_nearestSurfaceSize.height()) : entireRect();
+ }
+
+ RefPtr<BitmapTexture> m_texture;
+ RefPtr<BitmapTexture> m_surface, m_replicaSurface;
+
+ ContentData m_pendingContent;
+ ContentData m_currentContent;
+
+ Vector<TextureMapperNode*> m_children;
+ TextureMapperNode* m_parent;
+ TextureMapperNode* m_effectTarget;
+ int m_changeMask;
+ IntSize m_size, m_nearestSurfaceSize;
+ String m_name;
+ TextureMapperLayerClient* m_platformClient;
+
+ struct State {
+ FloatPoint pos;
+ FloatPoint3D anchorPoint;
+ FloatSize size;
+ TransformationMatrix transform;
+ TransformationMatrix childrenTransform;
+ Color backgroundColor;
+ Color currentColor;
+ GraphicsLayer::CompositingCoordinatesOrientation geoOrientation;
+ GraphicsLayer::CompositingCoordinatesOrientation contentsOrientation;
+ float opacity;
+ IntRect contentsRect;
+ int descendantsWithContent;
+ TextureMapperNode* maskLayer;
+ TextureMapperNode* replicaLayer;
+ bool preserves3D;
+ bool masksToBounds;
+ bool drawsContent;
+ bool contentsOpaque;
+ bool backfaceVisibility;
+ bool visible;
+ bool dirty;
+ bool tiled;
+ bool hasSurfaceDescendants;
+
+ State()
+ : opacity(1.f)
+ , descendantsWithContent(0)
+ , maskLayer(0)
+ , replicaLayer(0)
+ , preserves3D(false)
+ , masksToBounds(false)
+ , drawsContent(false)
+ , contentsOpaque(false)
+ , backfaceVisibility(false)
+ , visible(true)
+ , dirty(true)
+ , tiled(false)
+ , hasSurfaceDescendants(false)
+ {
+ }
+ };
+ State m_state;
+};
+
+void TextureMapperNode::setNeedsDisplayInRect(IntRect rect)
+{
+ if (m_platformClient) {
+ if (m_state.hasSurfaceDescendants) {
+ m_platformClient->setNeedsDisplay();
+ return;
+ }
+ rect.intersect(IntRect(0, 0, m_size.width(), m_size.height()));
+ if (rect.isEmpty())
+ return;
+ m_platformClient->setNeedsDisplayInRect(rect);
+ return;
+ }
+
+ if (!m_parent)
+ return;
+
+ m_parent->setNeedsDisplayInRect(rect);
+}
+
+void TextureMapperNode::setNeedsDisplay()
+{
+ if (m_effectTarget)
+ m_effectTarget->setNeedsDisplay();
+ if (m_transforms.targetBoundingRect.isEmpty())
+ return;
+ if (m_state.drawsContent || m_currentContent.contentType != HTMLContentType)
+ setNeedsDisplayInRect(m_transforms.targetBoundingRect);
+}
+
+
+void TextureMapperNode::setPlatformLayerClient(TextureMapperLayerClient* client)
+{
+ m_platformClient = client;
+}
+
+static int compareGraphicsLayersZValue(const void* a, const void* b)
+{
+ typedef const TextureMapperNode* NodePtr;
+ const NodePtr* nodeA = static_cast<const NodePtr*>(a);
+ const NodePtr* nodeB = static_cast<const NodePtr*>(b);
+ return int(((*nodeA)->m_transforms.centerZ - (*nodeB)->m_transforms.centerZ) * 1000);
+}
+inline static void sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last)
+{
+ qsort(array.data(), array.size(), sizeof(TextureMapperNode*), compareGraphicsLayersZValue);
+}
+
+bool TextureMapperNode::hasSurfaceDescendants() const
+{
+ if (m_layerType == ClipLayer || m_layerType == TransparencyLayer || m_state.replicaLayer)
+ return true;
+ const int size = m_children.size();
+ for (int i = 0; i < size; ++i) {
+ if (TextureMapperNode* child = m_children[i]) {
+ if (child->hasSurfaceDescendants())
+ return true;
+ }
+ }
+ return false;
+
+}
+
+void TextureMapperNode::paint(GraphicsContext* context, const IntSize& size, const IntRect& targetRect, const IntRect& exposedRect, const TransformationMatrix& transform, float opacity)
+{
+ ASSERT(m_layerType == RootLayer);
+ if (m_size.isEmpty())
+ return;
+
+#if 0
+ WTF::StopWatch stopWatch;
+ ("[TextureMapper] RootPaint!!\n");
+#endif
+
+ RefPtr<TextureMapper> textureMapper = TextureMapper::create(context);
+
+ if (textureMapper->type() != m_lastTextureMapperType)
+ gTextureMapperCache.m_data.clear();
+
+ m_lastTextureMapper = textureMapper;
+ TexmapPaintOptions opt;
+ opt.opacity = 1;
+ opt.rootLayer = this;
+ opt.scissorRect = targetRect;
+ opt.visibleRect = exposedRect;
+ opt.textureMapper = textureMapper.get();
+ opt.context = textureMapper->graphicsContext();
+ opt.surface = 0;
+ paintRecursive(opt);
+
+ if (textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants) {
+ textureMapper->bindSurface(0);
+ textureMapper->paintToTarget(*m_surface.get(), size, transform, opacity * m_state.opacity, targetRect);
+ }
+ gTextureMapperCache.purge();
+}
+
+int TextureMapperNode::countDescendantsWithContent() const
+{
+ if (!m_state.visible || m_state.opacity < 0.001)
+ return 0;
+ int descendantsWithContent = (m_state.drawsContent || m_currentContent.contentType != HTMLContentType) ? 1 : 0;
+
+ const int size = m_children.size();
+ for (int i = 0; i < size; ++i) {
+ if (TextureMapperNode* child = m_children[i])
+ descendantsWithContent += child->countDescendantsWithContent();
+ }
+
+ return descendantsWithContent;
+}
+
+inline TextureMapperNode* TextureMapperNode::toTextureMapperNode(GraphicsLayer* layer)
+{
+ return layer ? static_cast<GraphicsLayerTextureMapper*>(layer)->m_node.get() : 0;
+}
+
+void TextureMapperNode::computeLayerType()
+{
+ // calculate layer type. A layer can be one of the following:
+ // RootLayer: the top level. Draws to a framebuffer, and the target texture draws into the viewport.
+ // only one layer is the root layer.
+ // ScissorLayer: draws to the current framebuffer, and applies an extra scissor before drawing its children.
+ // A scissor layer is a layer with children that masks to bounds, is not a transparency layer, and has a rectangular clip.
+ // ClipLayer: creates a new framebuffer, the size of the layer, and then paints it to the enclosing BitmapTexture with the layer's transform/opacity.
+ // A clip layer is a layer that masks to bounds, doesn't preserve 3D, has children, and has a transparency/mask or a non-rectangular transform.
+ // TransparencyLayer: creates a new framebuffer idetical in size to the current framebuffer. Then draws the fb's texture to the current framebuffer with identity transform.
+ // Used for layers with children and transparency/mask that preserve 3D or don't mask to bounds.
+ // DefaultLayer: draws itself and its children directly to the current framebuffer.
+ // any layer that doesn't conform to the other rules is a DefaultLayer.
+
+ const bool selfHasContent = m_state.drawsContent || (m_currentContent.contentType != HTMLContentType);
+ const bool hasDescendantsWithContent = m_state.descendantsWithContent - (selfHasContent ? 1 : 0);
+ const bool hasTransparency = m_state.opacity < 0.99 || m_state.maskLayer;
+ const bool hasReplica = m_state.replicaLayer;
+ m_layerType = DefaultLayer;
+
+ // Layer has no parent, it must be a root layer.
+ if (!m_parent && !m_effectTarget) {
+ m_layerType = RootLayer;
+ return;
+ }
+
+ // A layer with no contents is always a default layer.
+ if (!m_state.descendantsWithContent)
+ return;
+
+ // A layer with content-descendants and a mask is always a clip layer.
+ if (hasDescendantsWithContent && m_state.maskLayer) {
+ m_layerType = ClipLayer;
+ return;
+ }
+
+ // A masks-to bounds layer can be a clip or a scissor layer. It's a scissor layer only if it has a trivial clip (identity or translation), or if it has transparency.
+ // That's because a ClipLayer would create an intermediate drawing surface (FB) - we want to limit it to when it's actually necessary, i.e. transparency or non-trivial clip.
+ if (m_state.masksToBounds && hasDescendantsWithContent) {
+ if (hasTransparency || !m_state.transform.isIdentityOrTranslation() || m_parent->m_state.preserves3D)
+ m_layerType = ClipLayer;
+ else
+ m_layerType = ScissorLayer;
+ return;
+ }
+
+ // We use a transparency layer when we have two of the following 3: replica, transparency, descendants with contents.
+ if ((hasReplica && hasDescendantsWithContent) || (hasReplica && hasTransparency) || (hasTransparency && m_state.descendantsWithContent > 1))
+ m_layerType = TransparencyLayer;
+}
+void TextureMapperNode::initializeTextureMapper(TextureMapper* textureMapper)
+{
+ if (textureMapper->type() == m_lastTextureMapperType)
+ return;
+ m_surface = textureMapper->createTexture();
+ m_replicaSurface = textureMapper->createTexture();
+ m_texture = textureMapper->createTexture();
+ gTextureMapperCache.mark(m_texture.get());
+ m_lastTextureMapperType = textureMapper->type();
+}
+
+TextureMapperNode::TextureMapperNode(GraphicsLayerTextureMapper* newLayer)
+ : m_layer(newLayer)
+ , m_lastTextureMapperType(0)
+ , m_lastTextureMapper(0)
+ , m_layerType(DefaultLayer)
+ , m_surface(0)
+ , m_parent(0)
+ , m_effectTarget(0)
+ , m_changeMask(NoChanges)
+ , m_platformClient(0)
+{
+
+}
+
+TextureMapperNode* TextureMapperNode::rootLayer()
+{
+ if (m_effectTarget)
+ return m_effectTarget->rootLayer();
+ if (m_parent)
+ return m_parent->rootLayer();
+ return this;
+}
+
+void TextureMapperNode::invalidateTransform()
+{
+ m_transforms.dirty = true;
+ if (m_layerType != ClipLayer)
+ m_state.dirty = true;
+ if (m_state.replicaLayer)
+ m_state.replicaLayer->invalidateTransform();
+ const int size = m_children.size();
+ for (int i = 0; i < size; ++i) {
+ if (TextureMapperNode* layer = m_children[i])
+ layer->invalidateTransform();
+ }
+}
+
+void TextureMapperNode::computeLocalTransform()
+{
+ if (!m_transforms.localDirty)
+ return;
+ const float originX = m_state.anchorPoint.x() * m_size.width();
+ const float originY = m_state.anchorPoint.y() * m_size.height();
+ m_transforms.local =
+ TransformationMatrix()
+ .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z())
+ .multLeft(m_state.transform)
+ .translate3d(-originX, -originY, -m_state.anchorPoint.z());
+ m_transforms.localDirty = false;
+}
+
+void TextureMapperNode::flattenTo2DSpaceIfNecessary()
+{
+ if (m_state.preserves3D)
+ return;
+ m_transforms.forDescendants.setM13(0);
+ m_transforms.forDescendants.setM23(0);
+ m_transforms.forDescendants.setM31(0);
+ m_transforms.forDescendants.setM32(0);
+ m_transforms.forDescendants.setM33(1);
+ m_transforms.forDescendants.setM34(0);
+ m_transforms.forDescendants.setM43(0);
+}
+
+IntSize TextureMapperNode::nearestSurfaceSize() const
+{
+ if (m_layerType == ClipLayer || m_layerType == RootLayer)
+ return m_surface && !m_surface->size().isEmpty() ? m_surface->size() : m_size;
+ return m_parent->nearestSurfaceSize();
+}
+
+void TextureMapperNode::computeReplicaTransform()
+{
+ if (!m_state.replicaLayer)
+ return;
+
+ m_nearestSurfaceSize = nearestSurfaceSize();
+
+ if (m_layerType != TransparencyLayer) {
+ m_transforms.replica = TransformationMatrix(m_transforms.target).multLeft(m_state.replicaLayer->m_transforms.local);
+ return;
+ }
+
+ const float originX = m_transforms.target.m41();
+ const float originY = m_transforms.target.m42();
+ m_transforms.replica =
+ TransformationMatrix()
+ .translate(originX, originY)
+ .multLeft(m_state.replicaLayer->m_transforms.local)
+ .translate(-originX, -originY);
+}
+
+void TextureMapperNode::computeTransformations()
+{
+ if (!m_transforms.dirty)
+ return;
+
+ m_transforms.dirty = false;
+ if ((m_size.isEmpty() && m_state.masksToBounds))
+ return;
+
+ TextureMapperNode* parent = m_parent;
+ computeLocalTransform();
+
+ m_transforms.target = TransformationMatrix(parent ? parent->m_transforms.forDescendants : TransformationMatrix()).multLeft(m_transforms.local);
+ m_transforms.forDescendants = (m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target);
+
+ if (m_effectTarget)
+ return;
+
+ m_transforms.targetBoundingRect = IntRect(m_transforms.target.mapRect(entireRect()));
+ if (m_state.replicaLayer)
+ m_state.replicaLayer->computeTransformations();
+
+ flattenTo2DSpaceIfNecessary();
+
+ if (!m_state.backfaceVisibility && m_transforms.target.inverse().m33() < 0) {
+ m_state.visible = false;
+ return;
+ }
+ m_state.visible = true;
+
+ if (parent && parent->m_state.preserves3D)
+ m_transforms.centerZ = m_transforms.target.mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z();
+
+ if (!m_children.size())
+ return;
+
+ if (m_state.childrenTransform.isIdentity())
+ return;
+
+ const FloatPoint centerPoint = FloatPoint(m_size.width() / 2, m_size.height() / 2);
+ if (m_transforms.perspectiveDirty)
+ m_transforms.perspective = TransformationMatrix()
+ .translate(centerPoint.x(), centerPoint.y())
+ .multLeft(m_state.childrenTransform)
+ .translate(-centerPoint.x(), -centerPoint.y());
+ m_transforms.perspectiveDirty = false;
+ m_transforms.forDescendants.multLeft(m_transforms.perspective);
+}
+
+void TextureMapperNode::uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect)
+{
+ if (m_size.isEmpty() || !m_layer) {
+ m_texture->destroy();
+ return;
+ }
+
+ if (m_currentContent.contentType == DirectImageContentType) {
+ if (m_currentContent.image)
+ m_texture->setContentsToImage(m_currentContent.image.get());
+ return;
+ }
+
+ if (m_currentContent.contentType == MediaContentType) {
+ if (!m_currentContent.media)
+ return;
+ m_texture->reset(m_size, true);
+ PlatformGraphicsContext* platformContext = m_texture->beginPaintMedia();
+ GraphicsContext context(platformContext);
+ m_currentContent.media->paint(&context);
+ m_texture->endPaint();
+ return;
+ }
+
+ const bool needsReset = (m_texture->contentSize() != m_size) || !m_texture->isValid();
+ if ((m_currentContent.contentType != HTMLContentType)
+ || (!m_currentContent.needsDisplay && m_currentContent.needsDisplayRect.isEmpty() && !needsReset))
+ return;
+
+ WTF::StopWatch stopWatch;
+ IntRect dirtyRect = IntRect(0, 0, m_size.width(), m_size.height());
+ if (!needsReset && !m_currentContent.needsDisplay)
+ dirtyRect.intersect(m_currentContent.needsDisplayRect);
+ if (needsReset)
+ m_texture->reset(m_size, m_state.contentsOpaque);
+ m_pendingContent.needsDisplayRect = IntRect();
+
+ {
+ GraphicsContext context(m_texture->beginPaint(dirtyRect));
+ if (textureMapper && textureMapper->graphicsContext()) {
+ GraphicsContext* originalContext = textureMapper->graphicsContext();
+ context.setImageInterpolationQuality(originalContext->imageInterpolationQuality());
+ context.setTextDrawingMode(originalContext->textDrawingMode());
+ }
+ m_layer->paintGraphicsLayerContents(context, dirtyRect);
+ }
+ m_texture->endPaint();
+ {
+#if 0
+ LOG("[TextureMapper] Re-render(%d) layer(%p) %d::%d::%d (%dx%d) [%dms]\n", ++renderCount, this,
+ needsReset, m_currentContent.needsDisplay, !m_currentContent.needsDisplayRect.isEmpty(),
+ dirtyRect.width(), dirtyRect.height(), int(stopWatch.elapsed() * 1000));
+ static int renderCount = 0;
+ m_texture->save(String().format("/tmp/layer_%d.png", renderCount));
+#endif
+ }
+ m_currentContent.needsDisplay = false;
+
+}
+
+void TextureMapperNode::paintSelf(const TexmapPaintOptions& options)
+{
+ if (!m_layer || m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType))
+ return;
+
+ RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->m_texture : 0;
+ RefPtr<BitmapTexture> replicaMaskTexture = 0;
+ if (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)
+ replicaMaskTexture = m_state.replicaLayer->m_state.maskLayer->m_texture;
+
+ const float opacity = options.isSurface ? 1 : options.opacity;
+
+ uploadTextureFromContent(options.textureMapper, options.visibleRect);
+ if (m_state.replicaLayer && !options.isSurface)
+ options.textureMapper->drawTexture(*m_texture.get(), replicaRect(), m_transforms.replica,
+ opacity * m_state.replicaLayer->m_state.opacity,
+ replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
+
+ const IntRect rect = m_layerType == ClipLayer ? entireRect() : targetRect();
+ const TransformationMatrix transform = m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target;
+ options.textureMapper->drawTexture(*m_texture.get(), rect, transform, opacity, options.isSurface ? 0 : maskTexture.get());
+}
+
+void TextureMapperNode::paintRecursive(TexmapPaintOptions options)
+{
+ WTF::StopWatch stopWatch;
+
+ bool isDirty = m_state.dirty;
+ m_state.dirty = false;
+
+ if ((m_size.isEmpty() && (m_state.masksToBounds
+ || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_state.opacity < 0.01)
+ return;
+
+ initializeTextureMapper(options.textureMapper);
+ computeReplicaTransform();
+
+ if (m_state.maskLayer) {
+ m_state.maskLayer->initializeTextureMapper(options.textureMapper);
+ m_state.maskLayer->m_state.dirty = false;
+ }
+
+ if (m_state.replicaLayer) {
+ m_state.replicaLayer->initializeTextureMapper(options.textureMapper);
+ m_state.replicaLayer->m_state.dirty = false;
+ if (m_state.replicaLayer->m_state.maskLayer) {
+ m_state.replicaLayer->m_state.maskLayer->initializeTextureMapper(options.textureMapper);
+ m_state.replicaLayer->m_state.maskLayer->m_state.dirty = false;
+ }
+ }
+
+ TextureMapperNode* replica = m_state.replicaLayer;
+ const bool isSurface = (m_layerType == ClipLayer
+ || m_layerType == TransparencyLayer
+ || (m_layerType == RootLayer
+ && (options.textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants)
+ ));
+ if (isSurface)
+ uploadTextureFromContent(options.textureMapper, options.visibleRect);
+ const IntRect boundingRectfromNearestSurface = m_transforms.targetBoundingRect;
+
+ options.opacity *= m_state.opacity;
+
+ TexmapPaintOptions optionsForDescendants(options);
+ optionsForDescendants.opacity = isSurface ? 1 : options.opacity;
+ options.isSurface = isSurface;
+
+ if (m_layerType == ClipLayer) {
+ optionsForDescendants.visibleRect = TransformationMatrix().translate(-boundingRectfromNearestSurface.x(), -boundingRectfromNearestSurface.y()).mapRect(options.visibleRect);
+ optionsForDescendants.scissorRect = IntRect(0, 0, m_size.width(), m_size.height());
+ }
+
+ if (m_layerType == ScissorLayer)
+ optionsForDescendants.scissorRect.intersect(m_transforms.targetBoundingRect);
+ options.textureMapper->setClip(optionsForDescendants.scissorRect);
+
+ TextureMapperCacheLock(m_texture.get());
+ TextureMapperCacheLock(m_surface.get());
+ TextureMapperCacheLock(m_replicaSurface.get());
+
+ gTextureMapperCache.purge();
+
+ if (isSurface) {
+ ASSERT(m_surface);
+ if (!m_surface->isValid())
+ isDirty = true;
+ if (m_state.tiled) {
+ m_surface->reset(options.visibleRect.size());
+ m_surface->setOffset(options.visibleRect.location());
+ } else if (isDirty)
+ m_surface->reset(m_layerType == TransparencyLayer ? options.surface->size() : m_size);
+ gTextureMapperCache.mark(m_surface.get());
+ options.textureMapper->bindSurface(m_surface.get());
+
+ optionsForDescendants.surface = m_surface.get();
+ } else if (m_surface)
+ m_surface->destroy();
+
+ RefPtr<BitmapTexture> maskTexture;
+ RefPtr<BitmapTexture> replicaMaskTexture;
+ if (TextureMapperNode* mask = m_state.maskLayer) {
+ mask->uploadTextureFromContent(options.textureMapper, options.visibleRect);
+ maskTexture = mask->m_texture;
+ }
+
+ if (replica && replica->m_state.maskLayer) {
+ replica->m_state.maskLayer->uploadTextureFromContent(options.textureMapper, options.visibleRect);
+ replicaMaskTexture = replica->m_state.maskLayer->m_texture;
+ }
+
+ int childrenSize = m_children.size();
+ if (isDirty || !isSurface || m_state.tiled || !m_surface->isValid()) {
+ bool didPaintSelf = false;
+ if (!m_state.preserves3D || m_children.isEmpty()) {
+ paintSelf(options);
+ didPaintSelf = true;
+ }
+
+ if (m_children.isEmpty() && !isSurface)
+ return;
+
+ if (m_layerType == ScissorLayer)
+ optionsForDescendants.scissorRect.intersect(m_transforms.target.mapRect(IntRect(0, 0, m_size.width(), m_size.height())));
+
+ for (int i = 0; i < childrenSize; ++i) {
+ TextureMapperNode* layer = m_children[i];
+ if (!layer)
+ continue;
+
+ if (!didPaintSelf && layer->m_transforms.centerZ >= 0) {
+ paintSelf(options);
+ didPaintSelf = true;
+ }
+ layer->paintRecursive(optionsForDescendants);
+ if (isSurface) {
+ ASSERT(m_surface);
+ gTextureMapperCache.mark(m_surface.get());
+ options.textureMapper->bindSurface(m_surface.get());
+ }
+ }
+ if (!didPaintSelf) {
+ paintSelf(options);
+ didPaintSelf = true;
+ }
+ }
+
+ if (m_layerType == RootLayer || m_layerType == DefaultLayer || m_layerType == ScissorLayer)
+ return;
+
+ ASSERT(m_surface);
+ BitmapTexture& texture = *m_surface.get();
+ if (replica) {
+ ASSERT(m_replicaSurface);
+ m_replicaSurface->reset(options.surface->size());
+ m_replicaSurface->setOffset(options.surface->offset());
+ gTextureMapperCache.mark(m_replicaSurface.get());
+ options.textureMapper->bindSurface(m_replicaSurface.get());
+ options.textureMapper->drawTexture(texture, replicaRect(), m_transforms.replica, replica->m_state.opacity, replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
+ options.textureMapper->drawTexture(texture, IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), 1.0f, maskTexture.get());
+ options.textureMapper->bindSurface(options.surface);
+ gTextureMapperCache.mark(options.surface);
+ options.textureMapper->drawTexture(*m_replicaSurface.get(), IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), options.opacity, 0);
+ return;
+ }
+
+ options.textureMapper->bindSurface(options.surface);
+ options.textureMapper->drawTexture(texture,
+ m_layerType == TransparencyLayer ? IntRect(IntPoint(0, 0), options.surface->size()) :
+ targetRect(),
+ m_layerType == TransparencyLayer ? TransformationMatrix() : m_transforms.target,
+ options.opacity, maskTexture.get());
+ gTextureMapperCache.mark(&texture);
+}
+
+void TextureMapperNode::cleanupTextureMapper()
+{
+ if (m_texture)
+ m_texture->destroy();
+ if (m_surface)
+ m_surface->destroy();
+ if (m_replicaSurface)
+ m_replicaSurface->destroy();
+ for (int i = 0; i < m_children.size(); ++i) {
+ if (m_children[i])
+ m_children[i]->cleanupTextureMapper();
+ }
+ if (m_lastTextureMapper)
+ m_lastTextureMapper->cleanup();
+}
+
+TextureMapperNode::~TextureMapperNode()
+{
+ setNeedsDisplay();
+ {
+ const int childrenSize = m_children.size();
+ for (int i = childrenSize-1; i >= 0; --i) {
+ ASSERT(m_children[i]->m_parent == this);
+ m_children[i]->m_parent = 0;
+ }
+ }
+ if (m_parent)
+ m_parent->m_children.remove(m_parent->m_children.find(this));
+}
+
+void TextureMapperNode::notifyChange(ChangeMask changeMask)
+{
+ m_changeMask |= changeMask;
+ if (!m_layer->client())
+ return;
+ m_layer->client()->notifySyncRequired(m_layer);
+}
+
+void TextureMapperNode::performPostSyncOperations()
+{
+ const LayerType prevLayerType = m_layerType;
+ computeLayerType();
+ if (prevLayerType != m_layerType)
+ m_state.dirty = true;
+ if (m_transforms.dirty)
+ setNeedsDisplay();
+
+ computeTransformations();
+ if (m_state.maskLayer && !m_state.dirty)
+ m_state.dirty = m_state.maskLayer->m_state.dirty;
+ if (m_state.replicaLayer && !m_state.dirty)
+ m_state.dirty = m_state.replicaLayer->m_state.dirty;
+
+ const int size = m_children.size();
+
+ for (int i = size - 1; i >= 0; --i) {
+ TextureMapperNode* layer = m_children[i];
+
+ layer->performPostSyncOperations();
+ if (!m_state.dirty)
+ m_state.dirty = layer->m_state.dirty;
+ }
+ m_state.hasSurfaceDescendants = hasSurfaceDescendants();
+ if (m_state.dirty)
+ m_state.descendantsWithContent = countDescendantsWithContent();
+
+ if (m_state.preserves3D)
+ sortByZOrder(m_children, 0, size);
+ if (m_state.dirty)
+ setNeedsDisplay();
+}
+
+void TextureMapperNode::syncCompositingState(bool recurse)
+{
+ bool needsToInvalidateTransform = false;
+
+ if (!m_layer)
+ return;
+
+ if (m_changeMask == NoChanges)
+ goto afterCurrentLayerSync;
+
+ setNeedsDisplay();
+ if (m_parent)
+ m_parent->m_state.dirty = true;
+
+ if (m_currentContent.contentType == HTMLContentType && (m_changeMask & ParentChange)) {
+ // The WebCore compositor manages item ownership. We have to make sure graphicsview doesn't
+ // try to snatch that ownership.
+
+ if (!m_layer->parent())
+ m_parent = 0;
+ else
+ m_parent = toTextureMapperNode(m_layer->parent());
+
+ if (!m_layer->parent() && m_parent) {
+ size_t index = m_parent->m_children.find(this);
+ m_parent->m_children.remove(index);
+ }
+
+ }
+
+ if (m_changeMask & ChildrenChange) {
+ m_children.clear();
+ for (size_t i = 0; i < m_layer->children().size(); ++i) {
+ if (TextureMapperNode* child = toTextureMapperNode(m_layer->children()[i])) {
+ if (!child)
+ continue;
+ m_children.append(child);
+ child->m_parent = this;
+ }
+ }
+ m_state.dirty = true;
+ }
+
+ if (m_changeMask & (SizeChange | ContentsRectChange)) {
+ IntSize wantedSize = IntSize(m_layer->size().width(), m_layer->size().height());
+ if (wantedSize.isEmpty() && m_pendingContent.contentType == HTMLContentType)
+ wantedSize = IntSize(m_layer->contentsRect().width(), m_layer->contentsRect().height());
+
+ if (wantedSize != m_size) {
+ m_size = IntSize(wantedSize.width(), wantedSize.height());
+ if (m_platformClient)
+ m_platformClient->setSizeChanged(m_size);
+ const bool needsTiling = m_size.width() > 2000 || m_size.height() > 2000;
+ if (m_state.tiled != needsTiling)
+ m_state.tiled = needsTiling;
+ m_state.dirty = true;
+ }
+ }
+
+ if (m_changeMask & MaskLayerChange) {
+ if (TextureMapperNode* layer = toTextureMapperNode(m_layer->maskLayer()))
+ layer->m_effectTarget = this;
+ }
+
+ if (m_changeMask & ReplicaLayerChange) {
+ if (TextureMapperNode* layer = toTextureMapperNode(m_layer->replicaLayer()))
+ layer->m_effectTarget = this;
+ }
+
+ if (m_changeMask & (TransformChange | SizeChange | AnchorPointChange | PositionChange))
+ m_transforms.localDirty = true;
+
+ if (m_changeMask & (ChildrenTransformChange | SizeChange))
+ m_transforms.perspectiveDirty = true;
+
+ if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | ContentsRectChange | BackfaceVisibilityChange | PositionChange | MaskLayerChange | DrawsContentChange | ContentChange | ReplicaLayerChange)) {
+ // Due to the differences between the way WebCore handles transforms and the way Qt handles transforms,
+ // all these elements affect the transforms of all the descendants.
+ needsToInvalidateTransform = true;
+ }
+
+ if (m_changeMask & DisplayChange)
+ m_state.dirty = true;
+
+ m_state.maskLayer = toTextureMapperNode(m_layer->maskLayer());
+ m_state.replicaLayer = toTextureMapperNode(m_layer->replicaLayer());
+ m_state.pos = m_layer->position();
+ m_state.anchorPoint = m_layer->anchorPoint();
+ m_state.size = m_layer->size();
+ m_state.transform = m_layer->transform();
+ m_state.contentsRect = m_layer->contentsRect();
+ m_state.opacity = m_layer->opacity();
+ m_state.contentsRect = m_layer->contentsRect();
+ m_state.preserves3D = m_layer->preserves3D();
+ m_state.masksToBounds = m_layer->masksToBounds();
+ m_state.drawsContent = m_layer->drawsContent();
+ m_state.contentsOpaque = m_layer->contentsOpaque();
+ m_state.backfaceVisibility = m_layer->backfaceVisibility();
+ m_state.childrenTransform = m_layer->childrenTransform();
+ m_currentContent.contentType = m_pendingContent.contentType;
+ m_currentContent.image = m_pendingContent.image;
+ m_currentContent.media = m_pendingContent.media;
+ m_currentContent.backgroundColor = m_pendingContent.backgroundColor;
+ m_currentContent.needsDisplay = m_currentContent.needsDisplay || m_pendingContent.needsDisplay;
+ m_currentContent.needsDisplayRect.unite(m_pendingContent.needsDisplayRect);
+ m_pendingContent.needsDisplay = false;
+ m_pendingContent.needsDisplayRect = IntRect();
+ m_changeMask = NoChanges;
+ afterCurrentLayerSync:
+ if (needsToInvalidateTransform)
+ invalidateTransform();
+
+ if (m_state.maskLayer) {
+ m_state.maskLayer->syncCompositingState(false);
+ if (m_state.maskLayer->m_size.isEmpty())
+ m_state.maskLayer->m_size = m_size;
+ }
+
+ if (m_state.replicaLayer)
+ m_state.replicaLayer->syncCompositingState(false);
+
+#if 0
+ if (m_state.dirty && m_texture && m_texture->allowOfflineTextureUpload())
+ uploadTextureFromContent(0);
+#endif
+
+ if (!recurse)
+ return;
+
+ const int childrenSize = m_children.size();
+ for (int i = childrenSize-1; i >= 0; --i)
+ m_children[i]->syncCompositingState(true);
+}
+
+GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(GraphicsLayerClient* client)
+ : GraphicsLayer(client)
+ , m_node(new TextureMapperNode(this))
+{
+}
+
+void GraphicsLayerTextureMapper::setName(const String& name)
+{
+ m_node->m_name = name;
+}
+
+GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper()
+{
+}
+
+/* \reimp (GraphicsLayer.h): The current size might change, thus we need to update the whole display.
+*/
+void GraphicsLayerTextureMapper::setNeedsDisplay()
+{
+ m_node->m_pendingContent.needsDisplay = true;
+ m_node->notifyChange(TextureMapperNode::DisplayChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ if (m_node->m_pendingContent.needsDisplay)
+ return;
+ m_node->m_pendingContent.needsDisplayRect.unite(IntRect(rect));
+ m_node->notifyChange(TextureMapperNode::DisplayChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setParent(GraphicsLayer* layer)
+{
+ m_node->notifyChange(TextureMapperNode::ParentChange);
+ GraphicsLayer::setParent(layer);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ m_node->notifyChange(TextureMapperNode::ChildrenChange);
+ return GraphicsLayer::setChildren(children);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer)
+{
+ m_node->notifyChange(TextureMapperNode::ChildrenChange);
+ GraphicsLayer::addChild(layer);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::addChildAtIndex(GraphicsLayer* layer, int index)
+{
+ GraphicsLayer::addChildAtIndex(layer, index);
+ m_node->notifyChange(TextureMapperNode::ChildrenChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildAbove(layer, sibling);
+ m_node->notifyChange(TextureMapperNode::ChildrenChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+
+ GraphicsLayer::addChildBelow(layer, sibling);
+ m_node->notifyChange(TextureMapperNode::ChildrenChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ if (GraphicsLayer::replaceChild(oldChild, newChild)) {
+ m_node->notifyChange(TextureMapperNode::ChildrenChange);
+ return true;
+ }
+
+ return false;
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::removeFromParent()
+{
+ if (!parent())
+ return;
+ m_node->notifyChange(TextureMapperNode::ParentChange);
+ GraphicsLayer::removeFromParent();
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setMaskLayer(GraphicsLayer* value)
+{
+ if (value == maskLayer())
+ return;
+ GraphicsLayer::setMaskLayer(value);
+ m_node->notifyChange(TextureMapperNode::MaskLayerChange);
+}
+
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value)
+{
+ if (value == replicaLayer())
+ return;
+ GraphicsLayer::setReplicatedByLayer(value);
+ m_node->notifyChange(TextureMapperNode::ReplicaLayerChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value)
+{
+ if (value == position())
+ return;
+ GraphicsLayer::setPosition(value);
+ m_node->notifyChange(TextureMapperNode::PositionChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
+{
+ if (value == anchorPoint())
+ return;
+ GraphicsLayer::setAnchorPoint(value);
+ m_node->notifyChange(TextureMapperNode::AnchorPointChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setSize(const FloatSize& value)
+{
+ if (value == size())
+ return;
+
+ GraphicsLayer::setSize(value);
+ m_node->notifyChange(TextureMapperNode::SizeChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value)
+{
+ if (value == transform())
+ return;
+
+ GraphicsLayer::setTransform(value);
+ m_node->notifyChange(TextureMapperNode::TransformChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix& value)
+{
+ if (value == childrenTransform())
+ return;
+ GraphicsLayer::setChildrenTransform(value);
+ m_node->notifyChange(TextureMapperNode::ChildrenTransformChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setPreserves3D(bool value)
+{
+ if (value == preserves3D())
+ return;
+ GraphicsLayer::setPreserves3D(value);
+ m_node->notifyChange(TextureMapperNode::Preserves3DChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setMasksToBounds(bool value)
+{
+ if (value == masksToBounds())
+ return;
+ GraphicsLayer::setMasksToBounds(value);
+ m_node->notifyChange(TextureMapperNode::MasksToBoundsChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setDrawsContent(bool value)
+{
+ if (value == drawsContent())
+ return;
+ m_node->notifyChange(TextureMapperNode::DrawsContentChange);
+ GraphicsLayer::setDrawsContent(value);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setBackgroundColor(const Color& value)
+{
+ if (value == m_node->m_pendingContent.backgroundColor)
+ return;
+ m_node->m_pendingContent.backgroundColor = value;
+ GraphicsLayer::setBackgroundColor(value);
+ m_node->notifyChange(TextureMapperNode::BackgroundColorChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::clearBackgroundColor()
+{
+ if (!m_node->m_pendingContent.backgroundColor.isValid())
+ return;
+ m_node->m_pendingContent.backgroundColor = Color();
+ GraphicsLayer::clearBackgroundColor();
+ m_node->notifyChange(TextureMapperNode::BackgroundColorChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsOpaque(bool value)
+{
+ if (value == contentsOpaque())
+ return;
+ m_node->notifyChange(TextureMapperNode::ContentsOpaqueChange);
+ GraphicsLayer::setContentsOpaque(value);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value)
+{
+ if (value == backfaceVisibility())
+ return;
+ GraphicsLayer::setBackfaceVisibility(value);
+ m_node->notifyChange(TextureMapperNode::BackfaceVisibilityChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setOpacity(float value)
+{
+ if (value == opacity())
+ return;
+ GraphicsLayer::setOpacity(value);
+ m_node->notifyChange(TextureMapperNode::OpacityChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsRect(const IntRect& value)
+{
+ if (value == contentsRect())
+ return;
+ GraphicsLayer::setContentsRect(value);
+ m_node->notifyChange(TextureMapperNode::ContentsRectChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
+{
+ m_node->notifyChange(TextureMapperNode::ContentChange);
+ m_node->m_pendingContent.contentType = image ? TextureMapperNode::DirectImageContentType : TextureMapperNode::HTMLContentType;
+ m_node->m_pendingContent.image = image;
+ GraphicsLayer::setContentsToImage(image);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsBackgroundColor(const Color& color)
+{
+ m_node->notifyChange(TextureMapperNode::ContentChange);
+ m_node->m_pendingContent.contentType = TextureMapperNode::ColorContentType;
+ m_node->m_pendingContent.backgroundColor = color;
+ GraphicsLayer::setContentsBackgroundColor(color);
+}
+
+
+void GraphicsLayerTextureMapper::setContentsToMedia(PlatformLayer* media)
+{
+ GraphicsLayer::setContentsToMedia(media);
+ m_node->notifyChange(TextureMapperNode::ContentChange);
+ m_node->m_pendingContent.contentType = media ? TextureMapperNode::MediaContentType : TextureMapperNode::HTMLContentType;
+ if (media)
+ m_node->m_pendingContent.media = static_cast<TextureMapperVideoLayer*>(media);
+ else
+ m_node->m_pendingContent.media = 0;
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsOrientation(CompositingCoordinatesOrientation orientation)
+{
+ if (contentsOrientation() == orientation)
+ return;
+ m_node->notifyChange(TextureMapperNode::ContentsOrientationChange);
+ GraphicsLayer::setContentsOrientation(orientation);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::syncCompositingStateForThisLayerOnly()
+{
+ m_node->syncCompositingState(false);
+ m_node->performPostSyncOperations();
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::syncCompositingState()
+{
+ GraphicsLayer::syncCompositingState();
+ m_node->syncCompositingState(true);
+ m_node->performPostSyncOperations();
+}
+
+/* \reimp (GraphicsLayer.h)
+ */
+NativeLayer GraphicsLayerTextureMapper::nativeLayer() const
+{
+ return m_node.get();
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+PlatformLayer* GraphicsLayerTextureMapper::platformLayer() const
+{
+ return m_node.get();
+}
+
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerTextureMapper(client);
+}
+
+}
diff --git a/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
new file mode 100644
index 0000000..36ebd74
--- /dev/null
+++ b/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2009 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 GraphicsLayerTextureMapper_h
+#define GraphicsLayerTextureMapper_h
+
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "GraphicsLayerClient.h"
+#include "Image.h"
+
+#if ENABLE(3D_CANVAS)
+#include "GraphicsContext3D.h"
+#endif
+
+#define ENABLE_TEXMAP_ANIMATION 0
+
+namespace WebCore {
+
+class TextureMapperNode;
+class BitmapTexture;
+class TextureMapper;
+
+class GraphicsLayerTextureMapper : public GraphicsLayer {
+ friend class TextureMapperNode;
+
+public:
+ GraphicsLayerTextureMapper(GraphicsLayerClient*);
+ virtual ~GraphicsLayerTextureMapper();
+
+ // reimps from GraphicsLayer.h
+ virtual void setNeedsDisplay();
+ virtual void setNeedsDisplayInRect(const FloatRect&);
+ virtual void setParent(GraphicsLayer* layer);
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
+ virtual void addChild(GraphicsLayer*);
+ virtual void addChildAtIndex(GraphicsLayer*, int index);
+ virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild);
+ virtual void removeFromParent();
+ virtual void setMaskLayer(GraphicsLayer* layer);
+ virtual void setPosition(const FloatPoint& p);
+ virtual void setAnchorPoint(const FloatPoint3D& p);
+ virtual void setSize(const FloatSize& size);
+ virtual void setTransform(const TransformationMatrix& t);
+ virtual void setChildrenTransform(const TransformationMatrix& t);
+ virtual void setPreserves3D(bool b);
+ virtual void setMasksToBounds(bool b);
+ virtual void setDrawsContent(bool b);
+ virtual void setBackgroundColor(const Color&);
+ virtual void clearBackgroundColor();
+ virtual void setContentsOpaque(bool b);
+ virtual void setBackfaceVisibility(bool b);
+ virtual void setOpacity(float opacity);
+ virtual void setContentsRect(const IntRect& r);
+ virtual void setReplicatedByLayer(GraphicsLayer*);
+ virtual void setContentsToImage(Image*);
+ virtual void setContentsToMedia(PlatformLayer*);
+ virtual void setContentsBackgroundColor(const Color&);
+#if ENABLE(3D_CANVAS)
+ virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*);
+ virtual void setGraphicsContext3DNeedsDisplay();
+#endif
+ virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation);
+ virtual void syncCompositingState();
+ virtual void syncCompositingStateForThisLayerOnly();
+ virtual void setName(const String& name);
+ virtual NativeLayer nativeLayer() const;
+ virtual PlatformLayer* platformLayer() const;
+
+ virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*,
+ const String& /*keyframesName*/, double /*timeOffset*/) { return false; }
+
+private:
+ OwnPtr<TextureMapperNode> m_node;
+};
+
+}
+#endif // GraphicsLayerTextureMapper_h
diff --git a/WebCore/platform/graphics/texmap/TextureMapper.h b/WebCore/platform/graphics/texmap/TextureMapper.h
new file mode 100644
index 0000000..03c1c6d
--- /dev/null
+++ b/WebCore/platform/graphics/texmap/TextureMapper.h
@@ -0,0 +1,120 @@
+/*
+ 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 TextureMapper_h
+#define TextureMapper_h
+
+#if USE(ACCELERATED_COMPOSITING)
+#if (defined(QT_OPENGL_LIB))
+ #if defined(QT_OPENGL_ES_2) && !defined(TEXMAP_OPENGL_ES_2)
+ #define TEXMAP_OPENGL_ES_2
+ #endif
+#endif
+
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "IntSize.h"
+#include "TransformationMatrix.h"
+
+/*
+ TextureMapper is a mechanism that enables hardware acceleration of CSS animations (accelerated compositing) without
+ a need for a platform specific scene-graph library like CoreAnimations or QGraphicsView.
+*/
+
+namespace WebCore {
+
+class TextureMapper;
+
+// A 2D texture that can be the target of software or GL rendering.
+class BitmapTexture : public RefCounted<BitmapTexture> {
+public:
+ BitmapTexture() : m_lockCount(0) {}
+ virtual ~BitmapTexture() { }
+
+ virtual bool allowOfflineTextureUpload() const { return false; }
+ virtual void destroy() = 0;
+ virtual IntSize size() const = 0;
+ virtual bool isValid() const = 0;
+ virtual void reset(const IntSize& size, bool opaque = false)
+ {
+ m_isOpaque = opaque;
+ m_contentSize = size;
+ }
+
+ virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect) = 0;
+ virtual void endPaint() = 0;
+ virtual PlatformGraphicsContext* beginPaintMedia()
+ {
+ return beginPaint(IntRect(0, 0, size().width(), size().height()));
+ }
+ virtual void setContentsToImage(Image*) = 0;
+ virtual bool save(const String& filename) { return false; }
+
+ inline void lock() { ++m_lockCount; }
+ inline void unlock() { --m_lockCount; }
+ inline bool isLocked() { return m_lockCount; }
+ inline IntSize contentSize() const { return m_contentSize; }
+ inline void setOffset(const IntPoint& o) { m_offset = o; }
+ inline IntPoint offset() const { return m_offset; }
+private:
+ int m_lockCount;
+ IntSize m_contentSize;
+ bool m_isOpaque;
+ IntPoint m_offset;
+};
+
+// A "context" class used to encapsulate accelerated texture mapping functions: i.e. drawing a texture
+// onto the screen or into another texture with a specified transform, opacity and mask.
+class TextureMapper : public RefCounted<TextureMapper> {
+ friend class BitmapTexture;
+
+public:
+ static PassRefPtr<TextureMapper> create(GraphicsContext*);
+ virtual ~TextureMapper() { }
+
+ virtual void drawTexture(const BitmapTexture& texture, const IntRect& target, const TransformationMatrix& matrix = TransformationMatrix(), float opacity = 1.0f, const BitmapTexture* maskTexture = 0) = 0;
+
+ // makes a surface the target for the following drawTexture calls.
+ virtual void bindSurface(BitmapTexture* surface) = 0;
+ virtual void paintToTarget(const BitmapTexture& texture, const IntSize&, const TransformationMatrix& matrix, float opacity, const IntRect& visibleRect)
+ {
+ drawTexture(texture, IntRect(0, 0, texture.contentSize().width(), texture.contentSize().height()), matrix, opacity, 0);
+ }
+
+ virtual void setClip(const IntRect&) = 0;
+ virtual bool allowSurfaceForRoot() const = 0;
+ virtual PassRefPtr<BitmapTexture> createTexture() = 0;
+ virtual const char* type() const = 0;
+ virtual void cleanup() {}
+
+ GraphicsContext* graphicsContext() const
+ {
+ return m_gc;
+ }
+
+protected:
+ TextureMapper(GraphicsContext* gc) : m_gc(gc) {}
+ GraphicsContext* m_gc;
+};
+
+};
+
+#endif
+
+#endif
diff --git a/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
new file mode 100644
index 0000000..23e9fc9
--- /dev/null
+++ b/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 2009 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 TextureMapperPlatformLayer_h
+#define TextureMapperPlatformLayer_h
+
+namespace WebCore {
+
+class GraphicsContext;
+class IntRect;
+class IntSize;
+class TransformationMatrix;
+
+
+// Glue layer to connect the texmap layer to the platform specific container.
+class TextureMapperLayerClient {
+public:
+ virtual ~TextureMapperLayerClient() {}
+ virtual void setNeedsDisplay() = 0;
+ virtual void setNeedsDisplayInRect(const IntRect& rect) = 0;
+ virtual void setSizeChanged(const IntSize&) = 0;
+};
+
+class TextureMapperPlatformLayer {
+public:
+ enum Type {
+ ContentLayer,
+ VideoLayer
+ };
+
+ virtual Type layerType() const = 0;
+ virtual ~TextureMapperPlatformLayer() {}
+};
+
+class TextureMapperContentLayer : public TextureMapperPlatformLayer {
+public:
+ virtual void setPlatformLayerClient(TextureMapperLayerClient*) = 0;
+ virtual void paint(GraphicsContext*, const IntSize&, const IntRect& targetRect, const IntRect& exposedRect, const TransformationMatrix& transform, float opacity) {}
+ virtual IntSize size() const = 0;
+ virtual void cleanupTextureMapper() {}
+ virtual Type layerType() const { return ContentLayer; }
+};
+
+#if ENABLE(VIDEO)
+class TextureMapperVideoLayer : public TextureMapperPlatformLayer {
+public:
+ virtual void paint(GraphicsContext*) = 0;
+ virtual Type layerType() const { return VideoLayer; }
+};
+#endif
+
+}
+
+#endif // TextureMapperPlatformLayer_h
diff --git a/WebCore/platform/graphics/transforms/AffineTransform.cpp b/WebCore/platform/graphics/transforms/AffineTransform.cpp
index be18e07..f275526 100644
--- a/WebCore/platform/graphics/transforms/AffineTransform.cpp
+++ b/WebCore/platform/graphics/transforms/AffineTransform.cpp
@@ -41,8 +41,8 @@ static void affineTransformDecompose(const AffineTransform& matrix, double sr[9]
AffineTransform m(matrix);
// Compute scaling factors
- double sx = sqrt(m.a() * m.a() + m.b() * m.b());
- double sy = sqrt(m.c() * m.c() + m.d() * m.d());
+ double sx = matrix.xScale();
+ double sy = matrix.yScale();
// Compute cross product of transformed unit vectors. If negative,
// one axis was flipped.
@@ -119,6 +119,16 @@ bool AffineTransform::isIdentity() const
&& m_transform[4] == 0 && m_transform[5] == 0);
}
+double AffineTransform::xScale() const
+{
+ return sqrt(m_transform[0] * m_transform[0] + m_transform[1] * m_transform[1]);
+}
+
+double AffineTransform::yScale() const
+{
+ return sqrt(m_transform[2] * m_transform[2] + m_transform[3] * m_transform[3]);
+}
+
double AffineTransform::det() const
{
return m_transform[0] * m_transform[3] - m_transform[1] * m_transform[2];
diff --git a/WebCore/platform/graphics/transforms/AffineTransform.h b/WebCore/platform/graphics/transforms/AffineTransform.h
index 289ec54..baee102 100644
--- a/WebCore/platform/graphics/transforms/AffineTransform.h
+++ b/WebCore/platform/graphics/transforms/AffineTransform.h
@@ -110,7 +110,10 @@ public:
AffineTransform& skew(double angleX, double angleY);
AffineTransform& skewX(double angle);
AffineTransform& skewY(double angle);
-
+
+ double xScale() const;
+ double yScale() const;
+
double det() const;
bool isInvertible() const;
AffineTransform inverse() const;
diff --git a/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h b/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h
index 7430dbc..0a0aaf0 100644
--- a/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h
+++ b/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h
@@ -37,6 +37,8 @@ public:
return adoptRef(new Matrix3DTransformOperation(matrix));
}
+ TransformationMatrix matrix() const {return m_matrix; }
+
private:
virtual bool isIdentity() const { return m_matrix.isIdentity(); }
diff --git a/WebCore/platform/graphics/transforms/MatrixTransformOperation.h b/WebCore/platform/graphics/transforms/MatrixTransformOperation.h
index ee47a11..fd9b27e 100644
--- a/WebCore/platform/graphics/transforms/MatrixTransformOperation.h
+++ b/WebCore/platform/graphics/transforms/MatrixTransformOperation.h
@@ -42,6 +42,8 @@ public:
return adoptRef(new MatrixTransformOperation(t));
}
+ TransformationMatrix matrix() const { return TransformationMatrix(m_a, m_b, m_c, m_d, m_e, m_f); }
+
private:
virtual bool isIdentity() const { return m_a == 1 && m_b == 0 && m_c == 0 && m_d == 1 && m_e == 0 && m_f == 0; }
diff --git a/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h b/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
index a665f3e..834cc83 100644
--- a/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
+++ b/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h
@@ -36,6 +36,8 @@ public:
{
return adoptRef(new PerspectiveTransformOperation(p));
}
+
+ double perspective() const { return m_p; }
private:
virtual bool isIdentity() const { return m_p == 0; }
diff --git a/WebCore/platform/graphics/transforms/RotateTransformOperation.h b/WebCore/platform/graphics/transforms/RotateTransformOperation.h
index 699ea43..2acb002 100644
--- a/WebCore/platform/graphics/transforms/RotateTransformOperation.h
+++ b/WebCore/platform/graphics/transforms/RotateTransformOperation.h
@@ -41,6 +41,9 @@ public:
return adoptRef(new RotateTransformOperation(x, y, z, angle, type));
}
+ double x() const { return m_x; }
+ double y() const { return m_y; }
+ double z() const { return m_z; }
double angle() const { return m_angle; }
private:
diff --git a/WebCore/platform/graphics/transforms/SkewTransformOperation.h b/WebCore/platform/graphics/transforms/SkewTransformOperation.h
index 6343710..afe9a7b 100644
--- a/WebCore/platform/graphics/transforms/SkewTransformOperation.h
+++ b/WebCore/platform/graphics/transforms/SkewTransformOperation.h
@@ -36,6 +36,9 @@ public:
return adoptRef(new SkewTransformOperation(angleX, angleY, type));
}
+ double angleX() const { return m_angleX; }
+ double angleY() const { return m_angleY; }
+
private:
virtual bool isIdentity() const { return m_angleX == 0 && m_angleY == 0; }
virtual OperationType getOperationType() const { return m_type; }
diff --git a/WebCore/platform/graphics/transforms/TranslateTransformOperation.h b/WebCore/platform/graphics/transforms/TranslateTransformOperation.h
index a66cc3d..ea48d49 100644
--- a/WebCore/platform/graphics/transforms/TranslateTransformOperation.h
+++ b/WebCore/platform/graphics/transforms/TranslateTransformOperation.h
@@ -46,6 +46,10 @@ public:
double y(const IntSize& borderBoxSize) const { return m_y.calcFloatValue(borderBoxSize.height()); }
double z(const IntSize&) const { return m_z.calcFloatValue(1); }
+ Length x() const { return m_x; }
+ Length y() const { return m_y; }
+ Length z() const { return m_z; }
+
private:
virtual bool isIdentity() const { return m_x.calcFloatValue(1) == 0 && m_y.calcFloatValue(1) == 0 && m_z.calcFloatValue(1) == 0; }
diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp
index c6437f2..2f1fb41 100644
--- a/WebCore/platform/graphics/win/FontCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -360,14 +360,14 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
graphicsContext->clearShadow();
Color fillColor = graphicsContext->fillColor();
Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- graphicsContext->setFillColor(shadowFillColor, DeviceColorSpace);
+ graphicsContext->setFillColor(shadowFillColor, ColorSpaceDeviceRGB);
CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width(), point.y() + translation.height() + shadowOffset.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
if (font->syntheticBoldOffset()) {
CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowOffset.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
- graphicsContext->setFillColor(fillColor, DeviceColorSpace);
+ graphicsContext->setFillColor(fillColor, ColorSpaceDeviceRGB);
}
CGContextSetTextPosition(cgContext, point.x() + translation.width(), point.y() + translation.height());
@@ -378,7 +378,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
}
if (hasSimpleShadow)
- graphicsContext->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace);
+ graphicsContext->setShadow(shadowOffset, shadowBlur, shadowColor, ColorSpaceDeviceRGB);
wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle);
}
diff --git a/WebCore/platform/graphics/win/GDIExtras.cpp b/WebCore/platform/graphics/win/GDIExtras.cpp
new file mode 100644
index 0000000..4bd95da
--- /dev/null
+++ b/WebCore/platform/graphics/win/GDIExtras.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "GDIExtras.h"
+
+#include "SoftLinking.h"
+
+namespace WebCore {
+
+#if OS(WINCE)
+SOFT_LINK_LIBRARY(coredll)
+SOFT_LINK_OPTIONAL(coredll, AlphaBlend, BOOL, APIENTRY, (HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc,
+ int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction))
+
+AlphaBlendPointerType AlphaBlendPointer()
+{
+ return AlphaBlendPtr();
+}
+#endif
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/GDIExtras.h b/WebCore/platform/graphics/win/GDIExtras.h
new file mode 100644
index 0000000..0166124
--- /dev/null
+++ b/WebCore/platform/graphics/win/GDIExtras.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GDIExtras_h
+#define GDIExtras_h
+
+#include <windows.h>
+
+namespace WebCore {
+
+typedef BOOL (APIENTRY *AlphaBlendPointerType) (HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc,
+ int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction);
+
+#if OS(WINCE)
+AlphaBlendPointerType AlphaBlendPointer();
+#endif
+
+inline bool hasAlphaBlendSupport()
+{
+#if OS(WINCE)
+ return AlphaBlendPointer();
+#else
+ return true;
+#endif
+}
+
+inline bool alphaBlendIfSupported(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc,
+ int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction)
+{
+#if OS(WINCE)
+ AlphaBlendPointerType alphaBlendPointer = AlphaBlendPointer();
+ if (!alphaBlendPointer)
+ return false;
+
+ alphaBlendPointer(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, blendFunction);
+#else
+ AlphaBlend(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, blendFunction);
+#endif
+ return true;
+}
+
+} // namespace WebCore
+
+#endif // GDIExtras_h
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index 0203d42..c9288e5 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -70,8 +70,8 @@ GraphicsContext::GraphicsContext(HDC hdc, bool hasAlpha)
setPaintingDisabled(!m_data->m_cgContext);
if (m_data->m_cgContext) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor(), DeviceColorSpace);
- setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
+ setPlatformFillColor(fillColor(), ColorSpaceDeviceRGB);
+ setPlatformStrokeColor(strokeColor(), ColorSpaceDeviceRGB);
}
}
@@ -129,6 +129,8 @@ void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int of
// FIXME: implement
}
+// FIXME: This is nearly identical to the GraphicsContext::drawFocusRing function in GraphicsContextMac.mm.
+// The code could move to GraphicsContextCG.cpp and be shared.
void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
{
if (paintingDisabled())
@@ -136,7 +138,7 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
float radius = (width - 1) / 2.0f;
offset += radius;
- CGColorRef colorRef = color.isValid() ? createCGColor(color) : 0;
+ CGColorRef colorRef = color.isValid() ? cachedCGColor(color, ColorSpaceDeviceRGB) : 0;
CGMutablePathRef focusRingPath = CGPathCreateMutable();
unsigned rectCount = rects.size();
@@ -151,8 +153,6 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
wkDrawFocusRing(context, colorRef, radius);
- CGColorRelease(colorRef);
-
CGPathRelease(focusRingPath);
CGContextRestoreGState(context);
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
index dad5da1..f7674db 100644
--- a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
@@ -99,9 +99,7 @@ TransformationMatrix CAToTransform3D(const CATransform3D& fromT3D)
static void setLayerBorderColor(WKCACFLayer* layer, const Color& color)
{
- CGColorRef borderColor = createCGColor(color);
- layer->setBorderColor(borderColor);
- CGColorRelease(borderColor);
+ layer->setBorderColor(cachedCGColor(color, ColorSpaceDeviceRGB));
}
static void clearBorderColor(WKCACFLayer* layer)
@@ -111,9 +109,7 @@ static void clearBorderColor(WKCACFLayer* layer)
static void setLayerBackgroundColor(WKCACFLayer* layer, const Color& color)
{
- CGColorRef bgColor = createCGColor(color);
- layer->setBackgroundColor(bgColor);
- CGColorRelease(bgColor);
+ layer->setBackgroundColor(cachedCGColor(color, ColorSpaceDeviceRGB));
}
static void clearLayerBackgroundColor(WKCACFLayer* layer)
diff --git a/WebCore/platform/graphics/win/ImageCGWin.cpp b/WebCore/platform/graphics/win/ImageCGWin.cpp
index a0fbba7..e65b859 100644
--- a/WebCore/platform/graphics/win/ImageCGWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCGWin.cpp
@@ -78,9 +78,9 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
IntSize imageSize = BitmapImage::size();
if (size)
- drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), DeviceColorSpace, CompositeCopy);
+ drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), ColorSpaceDeviceRGB, CompositeCopy);
else
- draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, CompositeCopy);
+ draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), ColorSpaceDeviceRGB, CompositeCopy);
// Do cleanup
CGContextRelease(cgContext);
diff --git a/WebCore/platform/graphics/win/ImageCairoWin.cpp b/WebCore/platform/graphics/win/ImageCairoWin.cpp
index e3c5ea0..70b132e 100644
--- a/WebCore/platform/graphics/win/ImageCairoWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCairoWin.cpp
@@ -82,9 +82,9 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
IntSize imageSize = BitmapImage::size();
if (size)
- drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), DeviceColorSpace, CompositeCopy);
+ drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), ColorSpaceDeviceRGB, CompositeCopy);
else
- draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, CompositeCopy);
+ draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), ColorSpaceDeviceRGB, CompositeCopy);
// Do cleanup
cairo_destroy(targetRef);
@@ -100,7 +100,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
if (cairo_image_surface_get_height(image) == static_cast<size_t>(srcSize.height()) && cairo_image_surface_get_width(image) == static_cast<size_t>(srcSize.width())) {
size_t currentFrame = m_currentFrame;
m_currentFrame = i;
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), DeviceColorSpace, compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), ColorSpaceDeviceRGB, compositeOp);
m_currentFrame = currentFrame;
return;
}
@@ -108,7 +108,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
// No image of the correct size was found, fallback to drawing the current frame
IntSize imageSize = BitmapImage::size();
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), ColorSpaceDeviceRGB, compositeOp);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
index 4a7e45e..4a7e45e 100755..100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
index 354e0bf..1b4f1d9 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
@@ -42,7 +42,6 @@
#include "ScrollView.h"
#include "Settings.h"
#include "SoftLinking.h"
-#include "StringBuilder.h"
#include "TimeRanges.h"
#include "Timer.h"
#include <AssertMacros.h>
@@ -53,6 +52,7 @@
#include <wtf/MainThread.h>
#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringHash.h>
#if USE(ACCELERATED_COMPOSITING)
@@ -174,6 +174,8 @@ MediaPlayerPrivateQuickTimeVisualContext::MediaPlayerPrivateQuickTimeVisualConte
, m_movieTransform(CGAffineTransformIdentity)
#endif
, m_visualContextClient(new MediaPlayerPrivateQuickTimeVisualContext::VisualContextClient(this))
+ , m_delayingLoad(false)
+ , m_preload(MediaPlayer::Auto)
{
}
@@ -241,7 +243,7 @@ static void addCookieParam(StringBuilder& cookieBuilder, const String& name, con
// Add parameter name, and value if there is one.
cookieBuilder.append(name);
if (!value.isEmpty()) {
- cookieBuilder.append("=");
+ cookieBuilder.append('=');
cookieBuilder.append(value);
}
}
@@ -275,7 +277,7 @@ void MediaPlayerPrivateQuickTimeVisualContext::setUpCookiesForQuickTime(const St
addCookieParam(cookieBuilder, "expires", rfc2616DateStringFromTime(cookie.expires));
if (cookie.httpOnly)
addCookieParam(cookieBuilder, "httpOnly", String());
- cookieBuilder.append(";");
+ cookieBuilder.append(';');
String cookieURL;
if (!cookie.domain.isEmpty()) {
@@ -316,8 +318,28 @@ static void disableComponentsOnce()
QTMovie::disableComponent(componentsToDisable[i]);
}
+void MediaPlayerPrivateQuickTimeVisualContext::resumeLoad()
+{
+ m_delayingLoad = false;
+
+ if (!m_movieURL.isEmpty())
+ loadInternal(m_movieURL);
+}
+
void MediaPlayerPrivateQuickTimeVisualContext::load(const String& url)
{
+ m_movieURL = url;
+
+ if (m_preload == MediaPlayer::None) {
+ m_delayingLoad = true;
+ return;
+ }
+
+ loadInternal(url);
+}
+
+void MediaPlayerPrivateQuickTimeVisualContext::loadInternal(const String& url)
+{
if (!QTMovie::initializeQuickTime()) {
// FIXME: is this the right error to return?
m_networkState = MediaPlayer::DecodeError;
@@ -347,6 +369,12 @@ void MediaPlayerPrivateQuickTimeVisualContext::load(const String& url)
m_movie->setVolume(m_player->volume());
}
+void MediaPlayerPrivateQuickTimeVisualContext::prepareToPlay()
+{
+ if (!m_movie || m_delayingLoad)
+ resumeLoad();
+}
+
void MediaPlayerPrivateQuickTimeVisualContext::play()
{
if (!m_movie)
@@ -1005,6 +1033,13 @@ bool MediaPlayerPrivateQuickTimeVisualContext::hasSingleSecurityOrigin() const
return true;
}
+void MediaPlayerPrivateQuickTimeVisualContext::setPreload(MediaPlayer::Preload preload)
+{
+ m_preload = preload;
+ if (m_delayingLoad && m_preload != MediaPlayer::None)
+ resumeLoad();
+}
+
MediaPlayerPrivateQuickTimeVisualContext::MediaRenderingMode MediaPlayerPrivateQuickTimeVisualContext::currentRenderingMode() const
{
if (!m_movie)
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h
index 272b90f..4c62558 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h
@@ -74,9 +74,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;
@@ -111,6 +114,8 @@ private:
bool hasClosedCaptions() const;
void setClosedCaptionsVisible(bool);
+ void setPreload(MediaPlayer::Preload);
+
void updateStates();
void doSeek();
void cancelSeek();
@@ -189,6 +194,9 @@ private:
bool m_isStreaming;
bool m_visible;
bool m_newFrameAvailable;
+ bool m_delayingLoad;
+ String m_movieURL;
+ MediaPlayer::Preload m_preload;
#if DRAW_FRAME_RATE
double m_frameCountWhilePlaying;
double m_timeStartedPlaying;
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index c37f5d5..39e8a11 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -38,7 +38,6 @@
#include "QTMovieTask.h"
#include "ScrollView.h"
#include "SoftLinking.h"
-#include "StringBuilder.h"
#include "TimeRanges.h"
#include "Timer.h"
#include <Wininet.h>
@@ -46,6 +45,7 @@
#include <wtf/HashSet.h>
#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringHash.h>
#if USE(ACCELERATED_COMPOSITING)
@@ -159,7 +159,7 @@ static void addCookieParam(StringBuilder& cookieBuilder, const String& name, con
// Add parameter name, and value if there is one.
cookieBuilder.append(name);
if (!value.isEmpty()) {
- cookieBuilder.append("=");
+ cookieBuilder.append('=');
cookieBuilder.append(value);
}
}
@@ -194,7 +194,7 @@ void MediaPlayerPrivate::setUpCookiesForQuickTime(const String& url)
addCookieParam(cookieBuilder, "expires", rfc2616DateStringFromTime(cookie.expires));
if (cookie.httpOnly)
addCookieParam(cookieBuilder, "httpOnly", String());
- cookieBuilder.append(";");
+ cookieBuilder.append(';');
String cookieURL;
if (!cookie.domain.isEmpty()) {
diff --git a/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp b/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
index 1685a30..d75c854 100644
--- a/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
+++ b/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
@@ -29,8 +29,8 @@
#include "WKCACFContextFlusher.h"
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <wtf/StdLibExtras.h>
-#include <QuartzCore/CACFContext.h>
namespace WebCore {
@@ -48,24 +48,18 @@ WKCACFContextFlusher::~WKCACFContextFlusher()
{
}
-void WKCACFContextFlusher::addContext(CACFContextRef context)
+void WKCACFContextFlusher::addContext(WKCACFContext* context)
{
ASSERT(context);
- if (m_contexts.add(context).second)
- CFRetain(context);
+ m_contexts.add(context);
}
-void WKCACFContextFlusher::removeContext(CACFContextRef context)
+void WKCACFContextFlusher::removeContext(WKCACFContext* context)
{
ASSERT(context);
- ContextSet::iterator found = m_contexts.find(context);
- if (found == m_contexts.end())
- return;
-
- CFRelease(*found);
- m_contexts.remove(found);
+ m_contexts.remove(context);
}
void WKCACFContextFlusher::flushAllContexts()
@@ -76,11 +70,8 @@ void WKCACFContextFlusher::flushAllContexts()
contextsToFlush.swap(m_contexts);
ContextSet::const_iterator end = contextsToFlush.end();
- for (ContextSet::const_iterator it = contextsToFlush.begin(); it != end; ++it) {
- CACFContextRef context = *it;
- CACFContextFlush(context);
- CFRelease(context);
- }
+ for (ContextSet::const_iterator it = contextsToFlush.begin(); it != end; ++it)
+ wkCACFContextFlush(*it);
}
}
diff --git a/WebCore/platform/graphics/win/WKCACFContextFlusher.h b/WebCore/platform/graphics/win/WKCACFContextFlusher.h
index 9ce76aa..17ec41d 100644
--- a/WebCore/platform/graphics/win/WKCACFContextFlusher.h
+++ b/WebCore/platform/graphics/win/WKCACFContextFlusher.h
@@ -32,7 +32,7 @@
#include <wtf/HashSet.h>
-typedef struct _CACFContext* CACFContextRef;
+struct WKCACFContext;
namespace WebCore {
@@ -40,8 +40,8 @@ class WKCACFContextFlusher : public Noncopyable {
public:
static WKCACFContextFlusher& shared();
- void addContext(CACFContextRef);
- void removeContext(CACFContextRef);
+ void addContext(WKCACFContext*);
+ void removeContext(WKCACFContext*);
void flushAllContexts();
@@ -49,7 +49,7 @@ private:
WKCACFContextFlusher();
~WKCACFContextFlusher();
- typedef HashSet<CACFContextRef> ContextSet;
+ typedef HashSet<WKCACFContext*> ContextSet;
ContextSet m_contexts;
};
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp
index bf47925..a8714e3 100644
--- a/WebCore/platform/graphics/win/WKCACFLayer.cpp
+++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp
@@ -30,15 +30,10 @@
#include "WKCACFLayer.h"
#include "WKCACFLayerRenderer.h"
-#include <wtf/text/CString.h>
-
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <stdio.h>
-#include <QuartzCore/CACFContext.h>
-#include <QuartzCore/CARender.h>
-
-#ifndef NDEBUG
#include <wtf/CurrentTime.h>
-#endif
+#include <wtf/text/CString.h>
namespace WebCore {
@@ -190,9 +185,9 @@ WKCACFLayer::~WKCACFLayer()
CACFLayerSetDisplayCallback(layer(), 0);
}
-void WKCACFLayer::becomeRootLayerForContext(CACFContextRef context)
+void WKCACFLayer::becomeRootLayerForContext(WKCACFContext* context)
{
- CACFContextSetLayer(context, layer());
+ wkCACFContextSetLayer(context, layer());
setNeedsCommit();
}
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h
index 7243508..4c6639a 100644
--- a/WebCore/platform/graphics/win/WKCACFLayer.h
+++ b/WebCore/platform/graphics/win/WKCACFLayer.h
@@ -41,6 +41,8 @@
#include "PlatformString.h"
#include "TransformationMatrix.h"
+struct WKCACFContext;
+
namespace WebCore {
class WKCACFLayer;
@@ -83,7 +85,7 @@ public:
}
// Makes this layer the root when the passed context is rendered
- void becomeRootLayerForContext(CACFContextRef);
+ void becomeRootLayerForContext(WKCACFContext*);
static RetainPtr<CFTypeRef> cfValue(float value) { return RetainPtr<CFTypeRef>(AdoptCF, CFNumberCreate(0, kCFNumberFloat32Type, &value)); }
static RetainPtr<CFTypeRef> cfValue(const TransformationMatrix& value)
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
index 4f39b13..73cb794 100755..100644
--- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
@@ -36,9 +36,7 @@
#include "WKCACFContextFlusher.h"
#include "WKCACFLayer.h"
#include "WebCoreInstanceHandle.h"
-#include <CoreGraphics/CGSRegion.h>
-#include <QuartzCore/CACFContext.h>
-#include <QuartzCore/CARenderOGL.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
#include <wtf/HashMap.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/OwnPtr.h>
@@ -108,7 +106,7 @@ private:
WKCACFLayerRenderer* m_renderer;
};
-typedef HashMap<CACFContextRef, WKCACFLayerRenderer*> ContextToWindowMap;
+typedef HashMap<WKCACFContext*, WKCACFLayerRenderer*> ContextToWindowMap;
static ContextToWindowMap& windowsForContexts()
{
@@ -206,7 +204,7 @@ bool WKCACFLayerRenderer::acceleratedCompositingAvailable()
return available;
}
-void WKCACFLayerRenderer::didFlushContext(CACFContextRef context)
+void WKCACFLayerRenderer::didFlushContext(WKCACFContext* context)
{
WKCACFLayerRenderer* window = windowsForContexts().get(context);
if (!window)
@@ -226,15 +224,13 @@ WKCACFLayerRenderer::WKCACFLayerRenderer(WKCACFLayerRendererClient* client)
: m_client(client)
, m_mightBeAbleToCreateDeviceLater(true)
, m_rootLayer(WKCACFRootLayer::create(this))
- , m_context(AdoptCF, CACFContextCreate(0))
- , m_renderContext(static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get())))
- , m_renderer(0)
+ , m_context(wkCACFContextCreate())
, m_hostWindow(0)
, m_renderTimer(this, &WKCACFLayerRenderer::renderTimerFired)
, m_backingStoreDirty(false)
, m_mustResetLostDeviceBeforeRendering(false)
{
- windowsForContexts().set(m_context.get(), this);
+ windowsForContexts().set(m_context, this);
// 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.
@@ -250,13 +246,13 @@ WKCACFLayerRenderer::WKCACFLayerRenderer(WKCACFLayerRendererClient* client)
m_rootLayer->setGeometryFlipped(true);
#ifndef NDEBUG
- CGColorRef debugColor = createCGColor(Color(255, 0, 0, 204));
+ CGColorRef debugColor = CGColorCreateGenericRGB(1, 0, 0, 0.8);
m_rootLayer->setBackgroundColor(debugColor);
CGColorRelease(debugColor);
#endif
if (m_context)
- m_rootLayer->becomeRootLayerForContext(m_context.get());
+ m_rootLayer->becomeRootLayerForContext(m_context);
#ifndef NDEBUG
char* printTreeFlag = getenv("CA_PRINT_TREE");
@@ -267,6 +263,7 @@ WKCACFLayerRenderer::WKCACFLayerRenderer(WKCACFLayerRendererClient* client)
WKCACFLayerRenderer::~WKCACFLayerRenderer()
{
destroyRenderer();
+ wkCACFContextDestroy(m_context);
}
WKCACFLayer* WKCACFLayerRenderer::rootLayer() const
@@ -298,7 +295,7 @@ void WKCACFLayerRenderer::setRootChildLayer(WKCACFLayer* layer)
void WKCACFLayerRenderer::layerTreeDidChange()
{
- WKCACFContextFlusher::shared().addContext(m_context.get());
+ WKCACFContextFlusher::shared().addContext(m_context);
renderSoon();
}
@@ -373,7 +370,7 @@ bool WKCACFLayerRenderer::createRenderer()
initD3DGeometry();
- m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0);
+ wkCACFContextInitializeD3DDevice(m_context, m_d3dDevice.get());
if (IsWindow(m_hostWindow))
m_rootLayer->setBounds(bounds());
@@ -384,14 +381,10 @@ bool WKCACFLayerRenderer::createRenderer()
void WKCACFLayerRenderer::destroyRenderer()
{
if (m_context) {
- CACFContextSetLayer(m_context.get(), 0);
- windowsForContexts().remove(m_context.get());
- WKCACFContextFlusher::shared().removeContext(m_context.get());
+ windowsForContexts().remove(m_context);
+ WKCACFContextFlusher::shared().removeContext(m_context);
}
- if (m_renderer)
- CARenderOGLDestroy(m_renderer);
- m_renderer = 0;
m_d3dDevice = 0;
if (s_d3d)
s_d3d->Release();
@@ -476,7 +469,7 @@ void WKCACFLayerRenderer::paint()
render(dirtyRects);
}
-void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects)
+void WKCACFLayerRenderer::render(const Vector<CGRect>& windowDirtyRects)
{
ASSERT(m_d3dDevice);
@@ -499,31 +492,21 @@ void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects)
CFTimeInterval t = CACurrentMediaTime();
// Give the renderer some space to use. This needs to be valid until the
- // CARenderUpdateFinish() call below.
+ // wkCACFContextFinishUpdate() call below.
char space[4096];
- CARenderUpdate* u = CARenderUpdateBegin(space, sizeof(space), t, 0, 0, &bounds);
- if (!u)
+ if (!wkCACFContextBeginUpdate(m_context, space, sizeof(space), t, bounds, windowDirtyRects.data(), windowDirtyRects.size()))
return;
- CARenderContextLock(m_renderContext);
- CARenderUpdateAddContext(u, m_renderContext);
- CARenderContextUnlock(m_renderContext);
-
- for (size_t i = 0; i < dirtyRects.size(); ++i)
- CARenderUpdateAddRect(u, &dirtyRects[i]);
-
HRESULT err = S_OK;
do {
- CGSRegionObj rgn = CARenderUpdateCopyRegion(u);
+ // FIXME: don't need to clear dirty region if layer tree is opaque.
- if (!rgn)
+ WKCACFUpdateRectEnumerator* e = wkCACFContextCopyUpdateRectEnumerator(m_context);
+ if (!e)
break;
- // FIXME: don't need to clear dirty region if layer tree is opaque.
-
Vector<D3DRECT, 64> rects;
- CGSRegionEnumeratorObj e = CGSRegionEnumerator(rgn);
- for (const CGRect* r = CGSNextRect(e); r; r = CGSNextRect(e)) {
+ for (const CGRect* r = wkCACFUpdateRectEnumeratorNextRect(e); r; r = wkCACFUpdateRectEnumeratorNextRect(e)) {
D3DRECT rect;
rect.x1 = r->origin.x;
rect.x2 = rect.x1 + r->size.width;
@@ -532,8 +515,7 @@ void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects)
rects.append(rect);
}
- CGSReleaseRegionEnumerator(e);
- CGSReleaseRegion(rgn);
+ wkCACFUpdateRectEnumeratorRelease(e);
if (rects.isEmpty())
break;
@@ -541,13 +523,13 @@ void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects)
m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0);
m_d3dDevice->BeginScene();
- CARenderOGLRender(m_renderer, u);
+ wkCACFContextRenderUpdate(m_context);
m_d3dDevice->EndScene();
err = m_d3dDevice->Present(0, 0, 0, 0);
if (err == D3DERR_DEVICELOST) {
- CARenderUpdateAddRect(u, &bounds);
+ wkCACFContextAddUpdateRect(m_context, bounds);
if (!resetDevice(LostDevice)) {
// We can't reset the device right now. Try again soon.
renderSoon();
@@ -556,7 +538,7 @@ void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects)
}
} while (err == D3DERR_DEVICELOST);
- CARenderUpdateFinish(u);
+ wkCACFContextFinishUpdate(m_context);
#ifndef NDEBUG
if (m_printTree)
@@ -598,7 +580,7 @@ void WKCACFLayerRenderer::initD3DGeometry()
bool WKCACFLayerRenderer::resetDevice(ResetReason reason)
{
ASSERT(m_d3dDevice);
- ASSERT(m_renderContext);
+ ASSERT(m_context);
HRESULT hr = m_d3dDevice->TestCooperativeLevel();
@@ -617,10 +599,10 @@ bool WKCACFLayerRenderer::resetDevice(ResetReason reason)
// We can reset the device.
- // We have to purge the CARenderOGLContext whenever we reset the IDirect3DDevice9 in order to
+ // We have to release the context's D3D resrouces whenever we reset the IDirect3DDevice9 in order to
// destroy any D3DPOOL_DEFAULT resources that Core Animation has allocated (e.g., textures used
// for mask layers). See <http://msdn.microsoft.com/en-us/library/bb174425(v=VS.85).aspx>.
- CARenderOGLPurge(m_renderer);
+ wkCACFContextReleaseD3DResources(m_context);
D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
hr = m_d3dDevice->Reset(&parameters);
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
index 1d73b99..763fffa 100755..100644
--- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
@@ -41,9 +41,7 @@
#include <CoreGraphics/CGGeometry.h>
interface IDirect3DDevice9;
-typedef struct _CACFContext* CACFContextRef;
-typedef struct _CARenderContext CARenderContext;
-typedef struct _CARenderOGLContext CARenderOGLContext;
+struct WKCACFContext;
namespace WebCore {
@@ -64,7 +62,7 @@ public:
~WKCACFLayerRenderer();
static bool acceleratedCompositingAvailable();
- static void didFlushContext(CACFContextRef);
+ static void didFlushContext(WKCACFContext*);
void setRootContents(CGImageRef);
void setRootContentsAndDisplay(CGImageRef);
@@ -104,9 +102,7 @@ private:
COMPtr<IDirect3DDevice9> m_d3dDevice;
RefPtr<WKCACFRootLayer> m_rootLayer;
RefPtr<WKCACFLayer> m_rootChildLayer;
- RetainPtr<CACFContextRef> m_context;
- CARenderContext* m_renderContext;
- CARenderOGLContext* m_renderer;
+ WKCACFContext* m_context;
HWND m_hostWindow;
Timer<WKCACFLayerRenderer> m_renderTimer;
bool m_backingStoreDirty;
diff --git a/WebCore/platform/graphics/win/WebLayer.cpp b/WebCore/platform/graphics/win/WebLayer.cpp
index 70a522d..ecda294 100644
--- a/WebCore/platform/graphics/win/WebLayer.cpp
+++ b/WebCore/platform/graphics/win/WebLayer.cpp
@@ -94,7 +94,7 @@ void WebLayer::drawInContext(PlatformGraphicsContext* context)
#endif
if (m_owner->showRepaintCounter()) {
- String text = String::format("%d", m_owner->incrementRepaintCount());;
+ String text = String::number(m_owner->incrementRepaintCount());
CGContextSaveGState(context);
@@ -129,7 +129,7 @@ void WebLayer::drawInContext(PlatformGraphicsContext* context)
font.update(0);
GraphicsContext cg(context);
- cg.setFillColor(Color::black, DeviceColorSpace);
+ cg.setFillColor(Color::black, ColorSpaceDeviceRGB);
cg.drawText(font, TextRun(text), IntPoint(aBounds.origin.x + 5, aBounds.origin.y + 17));
CGContextRestoreGState(context);
diff --git a/WebCore/platform/graphics/win/WebTiledLayer.cpp b/WebCore/platform/graphics/win/WebTiledLayer.cpp
index 01dd6ae..4705033 100644
--- a/WebCore/platform/graphics/win/WebTiledLayer.cpp
+++ b/WebCore/platform/graphics/win/WebTiledLayer.cpp
@@ -201,7 +201,7 @@ void WebTiledLayer::addTile()
CACFLayerInsertSublayer(m_tileParent.get(), newLayer.get(), sublayers ? CFArrayGetCount(sublayers) : 0);
if (m_owner->showDebugBorders()) {
- CGColorRef borderColor = createCGColor(Color(128, 0, 128, 180));
+ CGColorRef borderColor = CGColorCreateGenericRGB(0.5, 0, 0.5, 0.7);
CACFLayerSetBorderColor(newLayer.get(), borderColor);
CGColorRelease(borderColor);
CACFLayerSetBorderWidth(newLayer.get(), 2);
diff --git a/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp b/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
index a91b988..a0c10fc 100644
--- a/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
+++ b/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007-2009 Torch Mobile Inc.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,6 +25,7 @@
#include "AffineTransform.h"
#include "CharacterNames.h"
#include "Font.h"
+#include "GDIExtras.h"
#include "GlyphBuffer.h"
#include "Gradient.h"
#include "GraphicsContextPrivate.h"
@@ -322,8 +324,7 @@ public:
if (hdc == m_dc)
return;
-#if !defined(NO_ALPHABLEND)
- if (alphaPaint == AlphaPaintOther) {
+ if (alphaPaint == AlphaPaintOther && hasAlphaBlendSupport()) {
ASSERT(bmp && bmp->bytes() && bmp->is32bit());
unsigned* pixels = (unsigned*)bmp->bytes();
const unsigned* const pixelsEnd = pixels + bmp->bitmapInfo().numPixels();
@@ -332,13 +333,13 @@ public:
++pixels;
}
}
- if (m_opacity < 1. || alphaPaint == AlphaPaintOther) {
+ if ((m_opacity < 1. || alphaPaint == AlphaPaintOther) && hasAlphaBlendSupport()) {
const BLENDFUNCTION blend = { AC_SRC_OVER, 0
, m_opacity >= 1. ? 255 : (BYTE)(m_opacity * 255)
, alphaPaint == AlphaPaintNone ? 0 : AC_SRC_ALPHA };
- AlphaBlend(m_dc, origRect.x(), origRect.y(), origRect.width(), origRect.height(), hdc, 0, 0, bmpRect.right, bmpRect.bottom, blend);
+ bool success = alphaBlendIfSupported(m_dc, origRect.x(), origRect.y(), origRect.width(), origRect.height(), hdc, 0, 0, bmpRect.right, bmpRect.bottom, blend);
+ ASSERT_UNUSED(success, success);
} else
-#endif
StretchBlt(m_dc, origRect.x(), origRect.y(), origRect.width(), origRect.height(), hdc, 0, 0, bmpRect.right, bmpRect.bottom, SRCCOPY);
}
@@ -347,7 +348,7 @@ public:
Vector<GraphicsContextPlatformPrivateData> m_backupData;
};
-static HPEN createPen(const Color& col, double fWidth, StrokeStyle style)
+static PassOwnPtr<HPEN> createPen(const Color& col, double fWidth, StrokeStyle style)
{
int width = stableRound(fWidth);
if (width < 1)
@@ -367,12 +368,12 @@ static HPEN createPen(const Color& col, double fWidth, StrokeStyle style)
break;
}
- return CreatePen(penStyle, width, RGB(col.red(), col.green(), col.blue()));
+ return adoptPtr(CreatePen(penStyle, width, RGB(col.red(), col.green(), col.blue())));
}
-static inline HGDIOBJ createBrush(const Color& col)
+static inline PassOwnPtr<HBRUSH> createBrush(const Color& col)
{
- return CreateSolidBrush(RGB(col.red(), col.green(), col.blue()));
+ return adoptPtr(CreateSolidBrush(RGB(col.red(), col.green(), col.blue())));
}
template <typename PixelType, bool Is16bit> static void _rotateBitmap(SharedBitmap* destBmp, const SharedBitmap* sourceBmp, const RotationTransform& transform)
@@ -644,41 +645,33 @@ void GraphicsContext::drawRect(const IntRect& rect)
return;
trRect.move(transparentDC.toShift());
- HGDIOBJ brush = 0;
+ OwnPtr<HBRUSH> brush;
HGDIOBJ oldBrush;
if (fillColor().alpha()) {
brush = createBrush(fillColor());
- oldBrush = SelectObject(dc, brush);
+ oldBrush = SelectObject(dc, brush.get());
} else
- SelectObject(dc, GetStockObject(NULL_BRUSH));
+ oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
- HGDIOBJ pen = 0;
+ OwnPtr<HPEN> pen;
HGDIOBJ oldPen;
if (strokeStyle() != NoStroke) {
pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
- oldPen = SelectObject(dc, pen);
+ oldPen = SelectObject(dc, pen.get());
} else
- SelectObject(dc, GetStockObject(NULL_PEN));
+ oldPen = SelectObject(dc, GetStockObject(NULL_PEN));
- if (!brush && !pen)
- return;
-
- if (trRect.width() <= 0)
- trRect.setWidth(1);
- if (trRect.height() <= 0)
- trRect.setHeight(1);
-
- Rectangle(dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
+ if (brush || pen) {
+ if (trRect.width() <= 0)
+ trRect.setWidth(1);
+ if (trRect.height() <= 0)
+ trRect.setHeight(1);
- if (pen) {
- SelectObject(dc, oldPen);
- DeleteObject(pen);
+ Rectangle(dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
}
- if (brush) {
- SelectObject(dc, oldBrush);
- DeleteObject(brush);
- }
+ SelectObject(dc, oldPen);
+ SelectObject(dc, oldBrush);
}
void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
@@ -702,14 +695,13 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
trPoint1 += transparentDC.toShift();
trPoint2 += transparentDC.toShift();
- HGDIOBJ pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
- HGDIOBJ oldPen = SelectObject(dc, pen);
+ OwnPtr<HPEN> pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
+ HGDIOBJ oldPen = SelectObject(dc, pen.get());
MoveToEx(dc, trPoint1.x(), trPoint1.y(), 0);
LineTo(dc, trPoint2.x(), trPoint2.y());
SelectObject(dc, oldPen);
- DeleteObject(pen);
}
void GraphicsContext::drawEllipse(const IntRect& rect)
@@ -728,32 +720,27 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
return;
trRect.move(transparentDC.toShift());
- HGDIOBJ brush = 0;
+ OwnPtr<HBRUSH> brush;
HGDIOBJ oldBrush;
if (fillColor().alpha()) {
brush = createBrush(fillColor());
- oldBrush = SelectObject(dc, brush);
+ oldBrush = SelectObject(dc, brush.get());
} else
- SelectObject(dc, GetStockObject(NULL_BRUSH));
- HGDIOBJ pen = 0;
- HGDIOBJ oldPen;
+ oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
+
+ OwnPtr<HPEN> pen;
+ HGDIOBJ oldPen = 0;
if (strokeStyle() != NoStroke) {
pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
- oldPen = SelectObject(dc, pen);
+ oldPen = SelectObject(dc, pen.get());
} else
- SelectObject(dc, GetStockObject(NULL_PEN));
-
- Ellipse(dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
+ oldPen = SelectObject(dc, GetStockObject(NULL_PEN));
- if (pen) {
- SelectObject(dc, oldPen);
- DeleteObject(pen);
- }
+ if (brush || pen)
+ Ellipse(dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
- if (brush) {
- SelectObject(dc, oldBrush);
- DeleteObject(brush);
- }
+ SelectObject(dc, oldPen);
+ SelectObject(dc, oldBrush);
}
static inline bool equalAngle(double a, double b)
@@ -815,8 +802,8 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
return;
trRect.move(transparentDC.toShift());
- HGDIOBJ pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
- HGDIOBJ oldPen = SelectObject(dc, pen);
+ OwnPtr<HPEN> pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
+ HGDIOBJ oldPen = SelectObject(dc, pen.get());
double a = trRect.width() * 0.5;
double b = trRect.height() * 0.5;
@@ -872,7 +859,6 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
SelectClipRgn(dc, clipRgn.get());
SelectObject(dc, oldPen);
- DeleteObject(pen);
}
void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
@@ -916,36 +902,27 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
winPoints[i].y += transparentDC.toShift().height();
}
- HGDIOBJ brush = 0;
+ OwnPtr<HBRUSH> brush;
HGDIOBJ oldBrush;
if (fillColor().alpha()) {
brush = createBrush(fillColor());
- oldBrush = SelectObject(dc, brush);
+ oldBrush = SelectObject(dc, brush.get());
} else
- SelectObject(dc, GetStockObject(NULL_BRUSH));
+ oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
- HGDIOBJ pen = 0;
+ OwnPtr<HPEN> pen;
HGDIOBJ oldPen;
if (strokeStyle() != NoStroke) {
pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
- oldPen = SelectObject(dc, pen);
+ oldPen = SelectObject(dc, pen.get());
} else
- SelectObject(dc, GetStockObject(NULL_PEN));
-
- if (!brush && !pen)
- return;
-
- Polygon(dc, winPoints.data(), npoints);
+ oldPen = SelectObject(dc, GetStockObject(NULL_PEN));
- if (pen) {
- SelectObject(dc, oldPen);
- DeleteObject(pen);
- }
+ if (brush || pen)
+ Polygon(dc, winPoints.data(), npoints);
- if (brush) {
- SelectObject(dc, oldBrush);
- DeleteObject(brush);
- }
+ SelectObject(dc, oldPen);
+ SelectObject(dc, oldBrush);
}
void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
@@ -1104,7 +1081,7 @@ void GraphicsContext::clearRect(const FloatRect& rect)
return;
}
- fillRect(rect, Color(Color::white), DeviceColorSpace);
+ fillRect(rect, Color(Color::white), ColorSpaceDeviceRGB);
}
void GraphicsContext::strokeRect(const FloatRect& rect, float width)
@@ -1124,8 +1101,8 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
return;
trRect.move(transparentDC.toShift());
- HGDIOBJ pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
- HGDIOBJ oldPen = SelectObject(dc, pen);
+ OwnPtr<HPEN> pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
+ HGDIOBJ oldPen = SelectObject(dc, pen.get());
int right = trRect.right() - 1;
int bottom = trRect.bottom() - 1;
@@ -1141,7 +1118,6 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
Polyline(dc, intPoints, 5);
SelectObject(dc, oldPen);
- DeleteObject(pen);
}
void GraphicsContext::beginTransparencyLayer(float opacity)
@@ -1286,9 +1262,9 @@ void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& to
RECT rectWin = dstRect;
- HGDIOBJ brush = createBrush(shadowColor);
- HGDIOBJ oldBrush = SelectObject(dc, brush);
-
+ OwnPtr<HBRUSH> brush = createBrush(shadowColor);
+ HGDIOBJ oldBrush = SelectObject(dc, brush.get());
+
SelectObject(dc, GetStockObject(NULL_PEN));
IntPoint centerPoint = rectCenterPoint(rectWin);
@@ -1324,7 +1300,6 @@ void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& to
drawRoundCorner(needsNewClip, clipRect, rectWin, dc, stableRound(newBottomRight.width() * 2), stableRound(newBottomRight.height() * 2));
SelectObject(dc, oldBrush);
- DeleteObject(brush);
}
@@ -1382,8 +1357,9 @@ void GraphicsContext::fillPath()
if (!m_data->m_dc)
return;
+ OwnPtr<HBRUSH> brush = createBrush(c);
+
if (m_data->m_opacity < 1.0f || m_data->hasAlpha()) {
- HGDIOBJ brush = createBrush(c);
for (Vector<Path>::const_iterator i = m_data->m_paths.begin(); i != m_data->m_paths.end(); ++i) {
IntRect trRect = enclosingIntRect(m_data->mapRect(i->boundingRect()));
trRect.inflate(1);
@@ -1396,19 +1372,16 @@ void GraphicsContext::fillPath()
tr.translate(transparentDC.toShift().width(), transparentDC.toShift().height());
SelectObject(dc, GetStockObject(NULL_PEN));
- HGDIOBJ oldBrush = SelectObject(dc, brush);
+ HGDIOBJ oldBrush = SelectObject(dc, brush.get());
i->platformPath()->fillPath(dc, &tr);
SelectObject(dc, oldBrush);
}
- DeleteObject(brush);
} else {
SelectObject(m_data->m_dc, GetStockObject(NULL_PEN));
- HGDIOBJ brush = createBrush(c);
- HGDIOBJ oldBrush = SelectObject(m_data->m_dc, brush);
+ HGDIOBJ oldBrush = SelectObject(m_data->m_dc, brush.get());
for (Vector<Path>::const_iterator i = m_data->m_paths.begin(); i != m_data->m_paths.end(); ++i)
i->platformPath()->fillPath(m_data->m_dc, &m_data->m_transform);
SelectObject(m_data->m_dc, oldBrush);
- DeleteObject(brush);
}
}
@@ -1422,8 +1395,9 @@ void GraphicsContext::strokePath()
if (!m_data->m_dc)
return;
+ OwnPtr<HPEN> pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
+
if (m_data->m_opacity < 1.0f || m_data->hasAlpha()) {
- HGDIOBJ pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
for (Vector<Path>::const_iterator i = m_data->m_paths.begin(); i != m_data->m_paths.end(); ++i) {
IntRect trRect = enclosingIntRect(m_data->mapRect(i->boundingRect()));
trRect.inflate(1);
@@ -1436,19 +1410,16 @@ void GraphicsContext::strokePath()
tr.translate(transparentDC.toShift().width(), transparentDC.toShift().height());
SelectObject(dc, GetStockObject(NULL_BRUSH));
- HGDIOBJ oldPen = SelectObject(dc, pen);
+ HGDIOBJ oldPen = SelectObject(dc, pen.get());
i->platformPath()->strokePath(dc, &tr);
SelectObject(dc, oldPen);
}
- DeleteObject(pen);
} else {
SelectObject(m_data->m_dc, GetStockObject(NULL_BRUSH));
- HGDIOBJ pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
- HGDIOBJ oldPen = SelectObject(m_data->m_dc, pen);
+ HGDIOBJ oldPen = SelectObject(m_data->m_dc, pen.get());
for (Vector<Path>::const_iterator i = m_data->m_paths.begin(); i != m_data->m_paths.end(); ++i)
i->platformPath()->strokePath(m_data->m_dc, &m_data->m_transform);
SelectObject(m_data->m_dc, oldPen);
- DeleteObject(pen);
}
}
@@ -1465,7 +1436,7 @@ void GraphicsContext::fillRect(const FloatRect& r, const Gradient* gradient)
if (numStops == 1) {
const Gradient::ColorStop& stop = stops.first();
Color color(stop.red, stop.green, stop.blue, stop.alpha);
- fillRect(r, color, DeviceColorSpace);
+ fillRect(r, color, ColorSpaceDeviceRGB);
return;
}
@@ -1555,7 +1526,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
if (m_common->state.fillGradient)
fillRect(rect, m_common->state.fillGradient.get());
else
- fillRect(rect, fillColor(), DeviceColorSpace);
+ fillRect(rect, fillColor(), ColorSpaceDeviceRGB);
restorePlatformState();
}
diff --git a/WebCore/platform/graphics/wince/ImageWinCE.cpp b/WebCore/platform/graphics/wince/ImageWinCE.cpp
index 61ec954..53b9b68 100644
--- a/WebCore/platform/graphics/wince/ImageWinCE.cpp
+++ b/WebCore/platform/graphics/wince/ImageWinCE.cpp
@@ -82,9 +82,9 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
IntSize imageSize = BitmapImage::size();
if (size)
- drawFrameMatchingSourceSize(&gc, FloatRect(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), DeviceColorSpace, CompositeCopy);
+ drawFrameMatchingSourceSize(&gc, FloatRect(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), ColorSpaceDeviceRGB, CompositeCopy);
else
- draw(&gc, FloatRect(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0, 0, imageSize.width(), imageSize.height()), DeviceColorSpace, CompositeCopy);
+ draw(&gc, FloatRect(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0, 0, imageSize.width(), imageSize.height()), ColorSpaceDeviceRGB, CompositeCopy);
}
SelectObject(hdc.get(), hOldBmp);
diff --git a/WebCore/platform/graphics/wince/PathWinCE.cpp b/WebCore/platform/graphics/wince/PathWinCE.cpp
index 4f0195c..fa4c8fb 100644
--- a/WebCore/platform/graphics/wince/PathWinCE.cpp
+++ b/WebCore/platform/graphics/wince/PathWinCE.cpp
@@ -123,11 +123,6 @@ bool Path::isEmpty() const
return m_path->isEmpty();
}
-String Path::debugString() const
-{
- return m_path->debugString();
-}
-
void Path::apply(void* info, PathApplierFunction function) const
{
m_path->apply(info, function);
diff --git a/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp b/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp
index 80e01a9..8534f89 100644
--- a/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp
+++ b/WebCore/platform/graphics/wince/PlatformPathWinCE.cpp
@@ -754,43 +754,6 @@ void PlatformPath::addEllipse(const FloatRect& r)
addEllipse(r.location() + radius, radius.width(), radius.height(), 0, 0, true);
}
-String PlatformPath::debugString() const
-{
- String ret;
- for (PlatformPathElements::const_iterator i(m_elements.begin()); i != m_elements.end(); ++i) {
- switch (i->platformType()) {
- case PlatformPathElement::PathMoveTo:
- case PlatformPathElement::PathLineTo:
- ret += String::format("M %f %f\n", i->pointAt(0).m_x, i->pointAt(0).m_y);
- break;
- case PlatformPathElement::PathArcTo:
- ret += String::format("A %f %f %f %f %f %f %c\n"
- , i->arcTo().m_end.m_x, i->arcTo().m_end.m_y
- , i->arcTo().m_center.m_x, i->arcTo().m_center.m_y
- , i->arcTo().m_radius.m_x, i->arcTo().m_radius.m_y
- , i->arcTo().m_clockwise? 'Y' : 'N');
- break;
- case PlatformPathElement::PathQuadCurveTo:
- ret += String::format("Q %f %f %f %f\n"
- , i->pointAt(0).m_x, i->pointAt(0).m_y
- , i->pointAt(1).m_x, i->pointAt(1).m_y);
- break;
- case PlatformPathElement::PathBezierCurveTo:
- ret += String::format("B %f %f %f %f %f %f\n"
- , i->pointAt(0).m_x, i->pointAt(0).m_y
- , i->pointAt(1).m_x, i->pointAt(1).m_y
- , i->pointAt(2).m_x, i->pointAt(2).m_y);
- break;
- default:
- ASSERT(i->platformType() == PlatformPathElement::PathCloseSubpath);
- ret += "S\n";
- break;
- }
- }
-
- return ret;
-}
-
void PlatformPath::apply(void* info, PathApplierFunction function) const
{
PathElement pelement;
diff --git a/WebCore/platform/graphics/wince/PlatformPathWinCE.h b/WebCore/platform/graphics/wince/PlatformPathWinCE.h
index 3414b04..4c86fc3 100644
--- a/WebCore/platform/graphics/wince/PlatformPathWinCE.h
+++ b/WebCore/platform/graphics/wince/PlatformPathWinCE.h
@@ -164,7 +164,6 @@ namespace WebCore {
void addEllipse(const FloatPoint& p, float a, float b, float sar, float ear, bool anticlockwise);
void addRect(const FloatRect& r);
void addEllipse(const FloatRect& r);
- String debugString() const;
void apply(void* info, PathApplierFunction function) const;
private:
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index a39404a..30daa67 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -120,8 +120,8 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
setPaintingDisabled(!context);
if (context) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor(), DeviceColorSpace);
- setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
+ setPlatformFillColor(fillColor(), ColorSpaceDeviceRGB);
+ setPlatformStrokeColor(strokeColor(), ColorSpaceDeviceRGB);
}
#if USE(WXGC)
m_data->context = (wxGCDC*)context;
diff --git a/WebCore/platform/graphics/wx/PathWx.cpp b/WebCore/platform/graphics/wx/PathWx.cpp
index 3006e27..f5355f2 100644
--- a/WebCore/platform/graphics/wx/PathWx.cpp
+++ b/WebCore/platform/graphics/wx/PathWx.cpp
@@ -117,12 +117,6 @@ bool Path::strokeContains(StrokeStyleApplier*, const FloatPoint&) const
return false;
}
-String Path::debugString() const
-{
- notImplemented();
- return String();
-}
-
Path& Path::operator=(const Path& path)
{
*m_path = *path.platformPath();