summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/cg
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-24 11:24:40 +0100
committerBen Murdoch <benm@google.com>2011-06-02 09:53:15 +0100
commit81bc750723a18f21cd17d1b173cd2a4dda9cea6e (patch)
tree7a9e5ed86ff429fd347a25153107221543909b19 /Source/WebCore/platform/graphics/cg
parent94088a6d336c1dd80a1e734af51e96abcbb689a7 (diff)
downloadexternal_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.zip
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.gz
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.bz2
Merge WebKit at r80534: Intial merge by Git
Change-Id: Ia7a83357124c9e1cdb1debf55d9661ec0bd09a61
Diffstat (limited to 'Source/WebCore/platform/graphics/cg')
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp116
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h6
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp16
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp26
4 files changed, 136 insertions, 28 deletions
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index 3591479..dbcab45 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -65,6 +65,11 @@
#endif
+// Undocumented CGContextSetCTM function, available at least since 10.4.
+extern "C" {
+ CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
+};
+
using namespace std;
namespace WebCore {
@@ -603,12 +608,42 @@ void GraphicsContext::strokePath(const Path& path)
CGContextAddPath(context, path.platformPath());
if (m_state.strokeGradient) {
- CGContextSaveGState(context);
- CGContextReplacePathWithStrokedPath(context);
- CGContextClip(context);
- CGContextConcatCTM(context, m_state.strokeGradient->gradientSpaceTransform());
- m_state.strokeGradient->paint(this);
- CGContextRestoreGState(context);
+ if (hasShadow()) {
+ FloatRect rect = path.boundingRect();
+ float lineWidth = strokeThickness();
+ float doubleLineWidth = lineWidth * 2;
+ float layerWidth = ceilf(rect.width() + doubleLineWidth);
+ float layerHeight = ceilf(rect.height() + doubleLineWidth);
+
+ CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(layerWidth, layerHeight), 0);
+ CGContextRef layerContext = CGLayerGetContext(layer);
+ CGContextSetLineWidth(layerContext, lineWidth);
+
+ // Compensate for the line width, otherwise the layer's top-left corner would be
+ // aligned with the rect's top-left corner. This would result in leaving pixels out of
+ // the layer on the left and top sides.
+ float translationX = lineWidth - rect.x();
+ float translationY = lineWidth - rect.y();
+ CGContextTranslateCTM(layerContext, translationX, translationY);
+
+ CGContextAddPath(layerContext, path.platformPath());
+ CGContextReplacePathWithStrokedPath(layerContext);
+ CGContextClip(layerContext);
+ CGContextConcatCTM(layerContext, m_state.strokeGradient->gradientSpaceTransform());
+ m_state.strokeGradient->paint(layerContext);
+
+ float destinationX = roundf(rect.x() - lineWidth);
+ float destinationY = roundf(rect.y() - lineWidth);
+ CGContextDrawLayerAtPoint(context, CGPointMake(destinationX, destinationY), layer);
+ CGLayerRelease(layer);
+ } else {
+ CGContextSaveGState(context);
+ CGContextReplacePathWithStrokedPath(context);
+ CGContextClip(context);
+ CGContextConcatCTM(context, m_state.strokeGradient->gradientSpaceTransform());
+ m_state.strokeGradient->paint(this);
+ CGContextRestoreGState(context);
+ }
return;
}
@@ -952,7 +987,7 @@ void GraphicsContext::clearRect(const FloatRect& r)
CGContextClearRect(platformContext(), r);
}
-void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
+void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
{
if (paintingDisabled())
return;
@@ -960,19 +995,49 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
CGContextRef context = platformContext();
if (m_state.strokeGradient) {
- CGContextSaveGState(context);
- setStrokeThickness(lineWidth);
- CGContextAddRect(context, r);
- CGContextReplacePathWithStrokedPath(context);
- CGContextClip(context);
- m_state.strokeGradient->paint(this);
- CGContextRestoreGState(context);
+ if (hasShadow()) {
+ const float doubleLineWidth = lineWidth * 2;
+ const float layerWidth = ceilf(rect.width() + doubleLineWidth);
+ const float layerHeight = ceilf(rect.height() + doubleLineWidth);
+ CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(layerWidth, layerHeight), 0);
+
+ CGContextRef layerContext = CGLayerGetContext(layer);
+ m_state.strokeThickness = lineWidth;
+ CGContextSetLineWidth(layerContext, lineWidth);
+
+ // Compensate for the line width, otherwise the layer's top-left corner would be
+ // aligned with the rect's top-left corner. This would result in leaving pixels out of
+ // the layer on the left and top sides.
+ const float translationX = lineWidth - rect.x();
+ const float translationY = lineWidth - rect.y();
+ CGContextTranslateCTM(layerContext, translationX, translationY);
+
+ CGContextAddRect(layerContext, rect);
+ CGContextReplacePathWithStrokedPath(layerContext);
+ CGContextClip(layerContext);
+ CGContextConcatCTM(layerContext, m_state.strokeGradient->gradientSpaceTransform());
+ m_state.strokeGradient->paint(layerContext);
+
+ const float destinationX = roundf(rect.x() - lineWidth);
+ const float destinationY = roundf(rect.y() - lineWidth);
+ CGContextDrawLayerAtPoint(context, CGPointMake(destinationX, destinationY), layer);
+ CGLayerRelease(layer);
+ } else {
+ CGContextSaveGState(context);
+ setStrokeThickness(lineWidth);
+ CGContextAddRect(context, rect);
+ CGContextReplacePathWithStrokedPath(context);
+ CGContextClip(context);
+ CGContextConcatCTM(context, m_state.strokeGradient->gradientSpaceTransform());
+ m_state.strokeGradient->paint(this);
+ CGContextRestoreGState(context);
+ }
return;
}
if (m_state.strokePattern)
applyStrokePattern();
- CGContextStrokeRectWithWidth(context, r, lineWidth);
+ CGContextStrokeRectWithWidth(context, rect, lineWidth);
}
void GraphicsContext::setLineCap(LineCap cap)
@@ -1085,6 +1150,15 @@ void GraphicsContext::concatCTM(const AffineTransform& transform)
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
}
+void GraphicsContext::setCTM(const AffineTransform& transform)
+{
+ if (paintingDisabled())
+ return;
+ CGContextSetCTM(platformContext(), transform);
+ m_data->setCTM(transform);
+ m_data->m_userToDeviceTransformKnownToBeIdentity = false;
+}
+
AffineTransform GraphicsContext::getCTM() const
{
CGAffineTransform t = CGContextGetCTM(platformContext());
@@ -1130,7 +1204,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin);
}
-void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool printing)
+void GraphicsContext::drawLineForText(const FloatPoint& point, float width, bool printing)
{
if (paintingDisabled())
return;
@@ -1269,6 +1343,16 @@ void GraphicsContext::setAllowsFontSmoothing(bool allowsFontSmoothing)
#endif
}
+void GraphicsContext::setIsCALayerContext(bool)
+{
+ m_data->m_isCALayerContext = true;
+}
+
+bool GraphicsContext::isCALayerContext() const
+{
+ return m_data->m_isCALayerContext;
+}
+
void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode)
{
if (paintingDisabled())
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
index d4fa32e..f9255df 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -33,7 +33,7 @@ namespace WebCore {
class GraphicsContextPlatformPrivate {
public:
- GraphicsContextPlatformPrivate(CGContextRef cgContext)
+ GraphicsContextPlatformPrivate(CGContextRef cgContext, bool isLayerContext = false)
: m_cgContext(cgContext)
#if PLATFORM(WIN)
, m_hdc(0)
@@ -41,6 +41,7 @@ public:
, m_shouldIncludeChildWindows(false)
#endif
, m_userToDeviceTransformKnownToBeIdentity(false)
+ , m_isCALayerContext(isLayerContext)
{
}
@@ -59,6 +60,7 @@ public:
void rotate(float) {}
void translate(float, float) {}
void concatCTM(const AffineTransform&) {}
+ void setCTM(const AffineTransform&) {}
void beginTransparencyLayer() {}
void endTransparencyLayer() {}
#endif
@@ -74,6 +76,7 @@ public:
void rotate(float);
void translate(float, float);
void concatCTM(const AffineTransform&);
+ void setCTM(const AffineTransform&);
void beginTransparencyLayer() { m_transparencyCount++; }
void endTransparencyLayer() { m_transparencyCount--; }
@@ -84,6 +87,7 @@ public:
RetainPtr<CGContextRef> m_cgContext;
bool m_userToDeviceTransformKnownToBeIdentity;
+ bool m_isCALayerContext;
};
}
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index ab5907e..7c8e313 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -244,21 +244,21 @@ void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& src
}
}
-void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
+void ImageBuffer::clip(GraphicsContext* contextToClip, const FloatRect& rect) const
{
- CGContextRef platformContext = context->platformContext();
+ CGContextRef platformContextToClip = contextToClip->platformContext();
RetainPtr<CGImageRef> image;
if (!m_accelerateRendering)
image.adoptCF(cgImage(m_size, m_data));
#if USE(IOSURFACE_CANVAS_BACKING_STORE)
else
- image.adoptCF(wkIOSurfaceContextCreateImage(platformContext));
+ image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext()));
#endif
- CGContextTranslateCTM(platformContext, rect.x(), rect.y() + rect.height());
- CGContextScaleCTM(platformContext, 1, -1);
- CGContextClipToMask(platformContext, FloatRect(FloatPoint(), rect.size()), image.get());
- CGContextScaleCTM(platformContext, 1, -1);
- CGContextTranslateCTM(platformContext, -rect.x(), -rect.y() - rect.height());
+ CGContextTranslateCTM(platformContextToClip, rect.x(), rect.y() + rect.height());
+ CGContextScaleCTM(platformContextToClip, 1, -1);
+ CGContextClipToMask(platformContextToClip, FloatRect(FloatPoint(), rect.size()), image.get());
+ CGContextScaleCTM(platformContextToClip, 1, -1);
+ CGContextTranslateCTM(platformContextToClip, -rect.x(), -rect.y() - rect.height());
}
template <Multiply multiplied>
diff --git a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index 4ed8684..068ea5b 100644
--- a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -40,7 +40,12 @@ using namespace std;
namespace WebCore {
-static const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
+const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
+
+// kCGImagePropertyGIFUnclampedDelayTime is available in the ImageIO framework headers on some versions
+// of SnowLeopard. It's not possible to detect whether the constant is available so we define our own here
+// that won't conflict with ImageIO's version when it is available.
+const CFStringRef WebCoreCGImagePropertyGIFUnclampedDelayTime = CFSTR("UnclampedDelayTime");
#if !PLATFORM(MAC)
size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count)
@@ -222,6 +227,17 @@ bool ImageSource::getHotSpot(IntPoint& hotSpot) const
return true;
}
+size_t ImageSource::bytesDecodedToDetermineProperties() const
+{
+ // Measured by tracing malloc/calloc calls on Mac OS 10.6.6, x86_64.
+ // A non-zero value ensures cached images with no decoded frames still enter
+ // the live decoded resources list when the CGImageSource decodes image
+ // properties, allowing the cache to prune the partially decoded image.
+ // This value is likely to be inaccurate on other platforms, but the overall
+ // behavior is unchanged.
+ return 13088;
+}
+
int ImageSource::repetitionCount()
{
int result = cAnimationLoopOnce; // No property means loop once.
@@ -301,9 +317,13 @@ float ImageSource::frameDurationAtIndex(size_t index)
if (properties) {
CFDictionaryRef typeProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
if (typeProperties) {
- CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(typeProperties, kCGImagePropertyGIFDelayTime);
- if (num)
+ if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(typeProperties, WebCoreCGImagePropertyGIFUnclampedDelayTime)) {
+ // Use the unclamped frame delay if it exists.
+ CFNumberGetValue(num, kCFNumberFloatType, &duration);
+ } else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(typeProperties, kCGImagePropertyGIFDelayTime)) {
+ // Fall back to the clamped frame delay if the unclamped frame delay does not exist.
CFNumberGetValue(num, kCFNumberFloatType, &duration);
+ }
}
}