summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/cg
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-12-15 10:12:09 +0000
committerSteve Block <steveblock@google.com>2009-12-17 17:41:10 +0000
commit643ca7872b450ea4efacab6188849e5aac2ba161 (patch)
tree6982576c228bcd1a7efe98afed544d840751094c /WebCore/platform/graphics/cg
parentd026980fde6eb3b01c1fe49441174e89cd1be298 (diff)
downloadexternal_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.zip
external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.tar.gz
external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.tar.bz2
Merge webkit.org at r51976 : Initial merge by git.
Change-Id: Ib0e7e2f0fb4bee5a186610272edf3186f0986b43
Diffstat (limited to 'WebCore/platform/graphics/cg')
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp229
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h19
-rw-r--r--WebCore/platform/graphics/cg/ImageCG.cpp49
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp31
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.h4
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.cpp17
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.h2
7 files changed, 244 insertions, 107 deletions
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index 1350bd3..39f06a6 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -43,26 +43,78 @@
#include <wtf/OwnArrayPtr.h>
#include <wtf/RetainPtr.h>
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+// Building on 10.6 or later: kCGInterpolationMedium is defined in the CGInterpolationQuality enum.
#define HAVE_CG_INTERPOLATION_MEDIUM 1
#endif
+#if !defined(TARGETING_TIGER) && !defined(TARGETING_LEOPARD)
+// Targeting 10.6 or later: use kCGInterpolationMedium.
+#define WTF_USE_CG_INTERPOLATION_MEDIUM 1
+#endif
+
+#endif
+
using namespace std;
namespace WebCore {
-static void setCGFillColor(CGContextRef context, const Color& color)
+static CGColorRef createCGColorWithColorSpace(const Color& color, ColorSpace colorSpace)
{
- CGFloat red, green, blue, alpha;
- color.getRGBA(red, green, blue, alpha);
- CGContextSetRGBFillColor(context, red, green, blue, alpha);
+ CGFloat components[4];
+ color.getRGBA(components[0], components[1], components[2], components[3]);
+
+ CGColorRef cgColor = 0;
+ if (colorSpace == sRGBColorSpace)
+ cgColor = CGColorCreate(sRGBColorSpaceRef(), components);
+ else
+ cgColor = CGColorCreate(deviceRGBColorSpaceRef(), components);
+
+ return cgColor;
}
-static void setCGStrokeColor(CGContextRef context, const Color& color)
+static void setCGFillColor(CGContextRef context, const Color& color, ColorSpace colorSpace)
{
- CGFloat red, green, blue, alpha;
- color.getRGBA(red, green, blue, alpha);
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
+ CGColorRef cgColor = createCGColorWithColorSpace(color, colorSpace);
+ CGContextSetFillColorWithColor(context, cgColor);
+ CFRelease(cgColor);
+}
+
+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;
+ }
}
GraphicsContext::GraphicsContext(CGContextRef cgContext)
@@ -72,8 +124,8 @@ GraphicsContext::GraphicsContext(CGContextRef cgContext)
setPaintingDisabled(!cgContext);
if (cgContext) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), fillColorSpace());
+ setPlatformStrokeColor(strokeColor(), strokeColorSpace());
}
}
@@ -123,7 +175,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
// We do a fill of four rects to simulate the stroke of a border.
Color oldFillColor = fillColor();
if (oldFillColor != strokeColor())
- setCGFillColor(context, strokeColor());
+ setCGFillColor(context, strokeColor(), strokeColorSpace());
CGRect rects[4] = {
FloatRect(rect.x(), rect.y(), rect.width(), 1),
FloatRect(rect.x(), rect.bottom() - 1, rect.width(), 1),
@@ -132,7 +184,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
};
CGContextFillRects(context, rects, 4);
if (oldFillColor != strokeColor())
- setCGFillColor(context, oldFillColor);
+ setCGFillColor(context, oldFillColor, fillColorSpace());
}
}
@@ -200,7 +252,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
// Do a rect fill of our endpoints. This ensures we always have the
// appearance of being a border. We then draw the actual dotted/dashed line.
- setCGFillColor(context, strokeColor()); // The save/restore make it safe to mutate the fill color here without setting it back to the old color.
+ setCGFillColor(context, strokeColor(), strokeColorSpace()); // The save/restore make it safe to mutate the fill color here without setting it back to the old color.
if (isVerticalLine) {
CGContextFillRect(context, FloatRect(p1.x() - width / 2, p1.y() - width, width, width));
CGContextFillRect(context, FloatRect(p2.x() - width / 2, p2.y(), width, width));
@@ -392,7 +444,7 @@ void GraphicsContext::applyStrokePattern()
{
CGContextRef cgContext = platformContext();
- RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.strokePattern.get()->createPlatformPattern(getCTM()));
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.strokePattern->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
@@ -407,7 +459,7 @@ void GraphicsContext::applyFillPattern()
{
CGContextRef cgContext = platformContext();
- RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.fillPattern.get()->createPlatformPattern(getCTM()));
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.fillPattern->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
@@ -420,8 +472,8 @@ void GraphicsContext::applyFillPattern()
static inline bool calculateDrawingMode(const GraphicsContextState& state, CGPathDrawingMode& mode)
{
- bool shouldFill = state.fillColorSpace == PatternColorSpace || state.fillColor.alpha();
- bool shouldStroke = state.strokeColorSpace == PatternColorSpace || (state.strokeStyle != NoStroke && state.strokeColor.alpha());
+ bool shouldFill = state.fillPattern || state.fillColor.alpha();
+ bool shouldStroke = state.strokePattern || (state.strokeStyle != NoStroke && state.strokeColor.alpha());
bool useEOFill = state.fillRule == RULE_EVENODD;
if (shouldFill) {
@@ -453,16 +505,16 @@ void GraphicsContext::drawPath()
CGContextRef context = platformContext();
const GraphicsContextState& state = m_common->state;
- if (state.fillColorSpace == GradientColorSpace || state.strokeColorSpace == GradientColorSpace) {
+ if (state.fillGradient || state.strokeGradient) {
// We don't have any optimized way to fill & stroke a path using gradients
fillPath();
strokePath();
return;
}
- if (state.fillColorSpace == PatternColorSpace)
+ if (state.fillPattern)
applyFillPattern();
- if (state.strokeColorSpace == PatternColorSpace)
+ if (state.strokePattern)
applyStrokePattern();
CGPathDrawingMode drawingMode;
@@ -484,15 +536,11 @@ void GraphicsContext::fillPath()
return;
CGContextRef context = platformContext();
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- fillPathWithFillRule(context, fillRule());
- break;
- case PatternColorSpace:
- applyFillPattern();
- fillPathWithFillRule(context, fillRule());
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the fillPattern and fillGradient cases?
+ setCGFillColorSpace(context, m_common->state.fillColorSpace);
+
+ if (m_common->state.fillGradient) {
CGContextSaveGState(context);
if (fillRule() == RULE_EVENODD)
CGContextEOClip(context);
@@ -501,8 +549,12 @@ void GraphicsContext::fillPath()
CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform());
CGContextDrawShading(context, m_common->state.fillGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.fillPattern)
+ applyFillPattern();
+ fillPathWithFillRule(context, fillRule());
}
void GraphicsContext::strokePath()
@@ -511,76 +563,83 @@ void GraphicsContext::strokePath()
return;
CGContextRef context = platformContext();
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- CGContextStrokePath(context);
- break;
- case PatternColorSpace:
- applyStrokePattern();
- CGContextStrokePath(context);
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the strokePattern and strokeGradient cases?
+ setCGStrokeColorSpace(context, m_common->state.strokeColorSpace);
+
+ if (m_common->state.strokeGradient) {
CGContextSaveGState(context);
CGContextReplacePathWithStrokedPath(context);
CGContextClip(context);
CGContextConcatCTM(context, m_common->state.strokeGradient->gradientSpaceTransform());
CGContextDrawShading(context, m_common->state.strokeGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.strokePattern)
+ applyStrokePattern();
+ CGContextStrokePath(context);
}
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
+
CGContextRef context = platformContext();
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- CGContextFillRect(context, rect);
- break;
- case PatternColorSpace:
- applyFillPattern();
- CGContextFillRect(context, rect);
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the fillPattern and fillGradient cases?
+ setCGFillColorSpace(context, m_common->state.fillColorSpace);
+
+ if (m_common->state.fillGradient) {
CGContextSaveGState(context);
CGContextClipToRect(context, rect);
CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform());
CGContextDrawShading(context, m_common->state.fillGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.fillPattern)
+ applyFillPattern();
+ CGContextFillRect(context, rect);
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
CGContextRef context = platformContext();
Color oldFillColor = fillColor();
- if (oldFillColor != color)
- setCGFillColor(context, color);
+ ColorSpace oldColorSpace = fillColorSpace();
+
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, color, colorSpace);
+
CGContextFillRect(context, rect);
- if (oldFillColor != color)
- setCGFillColor(context, oldFillColor);
+
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, oldFillColor, oldColorSpace);
}
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
CGContextRef context = platformContext();
Color oldFillColor = fillColor();
- if (oldFillColor != color)
- setCGFillColor(context, color);
+ ColorSpace oldColorSpace = fillColorSpace();
+
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, color, colorSpace);
addPath(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
fillPath();
- if (oldFillColor != color)
- setCGFillColor(context, oldFillColor);
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, oldFillColor, oldColorSpace);
}
void GraphicsContext::clip(const FloatRect& rect)
@@ -680,7 +739,7 @@ void GraphicsContext::endTransparencyLayer()
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
}
-void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color)
+void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -727,7 +786,7 @@ void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Col
if (!color.isValid())
CGContextSetShadow(context, CGSizeMake(width, height), blurRadius);
else {
- RetainPtr<CGColorRef> colorCG(AdoptCF, createCGColor(color));
+ RetainPtr<CGColorRef> colorCG(AdoptCF, createCGColorWithColorSpace(color, colorSpace));
CGContextSetShadowWithColor(context,
CGSizeMake(width, height),
blurRadius,
@@ -769,15 +828,11 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
return;
CGContextRef context = platformContext();
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- CGContextStrokeRectWithWidth(context, r, lineWidth);
- break;
- case PatternColorSpace:
- applyStrokePattern();
- CGContextStrokeRectWithWidth(context, r, lineWidth);
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the strokePattern and strokeGradient cases?
+ setCGStrokeColorSpace(context, m_common->state.strokeColorSpace);
+
+ if (m_common->state.strokeGradient) {
CGContextSaveGState(context);
setStrokeThickness(lineWidth);
CGContextAddRect(context, r);
@@ -785,8 +840,12 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
CGContextClip(context);
CGContextDrawShading(context, m_common->state.strokeGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.strokePattern)
+ applyStrokePattern();
+ CGContextStrokeRectWithWidth(context, r, lineWidth);
}
void GraphicsContext::setLineCap(LineCap cap)
@@ -986,10 +1045,10 @@ void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool pri
}
if (fillColor() != strokeColor())
- setCGFillColor(platformContext(), strokeColor());
+ setCGFillColor(platformContext(), strokeColor(), strokeColorSpace());
CGContextFillRect(platformContext(), CGRectMake(x, y, lineLength, thickness));
if (fillColor() != strokeColor())
- setCGFillColor(platformContext(), fillColor());
+ setCGFillColor(platformContext(), fillColor(), fillColorSpace());
if (restoreAntialiasMode)
CGContextSetShouldAntialias(platformContext(), true);
@@ -1034,9 +1093,9 @@ void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode)
quality = kCGInterpolationLow;
break;
- // Fall through to InterpolationHigh if kCGInterpolationMedium is not available
+ // Fall through to InterpolationHigh if kCGInterpolationMedium is not usable.
case InterpolationMedium:
-#if HAVE(CG_INTERPOLATION_MEDIUM)
+#if USE(CG_INTERPOLATION_MEDIUM)
quality = kCGInterpolationMedium;
break;
#endif
@@ -1061,9 +1120,15 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const
case kCGInterpolationLow:
return InterpolationLow;
#if HAVE(CG_INTERPOLATION_MEDIUM)
+ // kCGInterpolationMedium is known to be present in the CGInterpolationQuality enum.
case kCGInterpolationMedium:
+#if USE(CG_INTERPOLATION_MEDIUM)
+ // Only map to InterpolationMedium if targeting a system that understands it.
return InterpolationMedium;
-#endif
+#else
+ return InterpolationDefault;
+#endif // USE(CG_INTERPOLATION_MEDIUM)
+#endif // HAVE(CG_INTERPOLATION_MEDIUM)
case kCGInterpolationHigh:
return InterpolationHigh;
}
@@ -1107,11 +1172,11 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode)
}
}
-void GraphicsContext::setPlatformStrokeColor(const Color& color)
+void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
- setCGStrokeColor(platformContext(), color);
+ setCGStrokeColor(platformContext(), color, colorSpace);
}
void GraphicsContext::setPlatformStrokeThickness(float thickness)
@@ -1121,11 +1186,11 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness)
CGContextSetLineWidth(platformContext(), thickness);
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
- setCGFillColor(platformContext(), color);
+ setCGFillColor(platformContext(), color, colorSpace);
}
void GraphicsContext::setPlatformShouldAntialias(bool enable)
diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
index 38c5506..ff1816f 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
+++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -27,6 +27,25 @@
namespace WebCore {
+// FIXME: This would be in GraphicsContextCG.h if that existed.
+inline CGColorSpaceRef deviceRGBColorSpaceRef()
+{
+ static CGColorSpaceRef deviceSpace = CGColorSpaceCreateDeviceRGB();
+ return deviceSpace;
+}
+
+// FIXME: This would be in GraphicsContextCG.h if that existed.
+inline CGColorSpaceRef sRGBColorSpaceRef()
+{
+ // FIXME: Windows should be able to use kCGColorSpaceSRGB, this is tracked by http://webkit.org/b/31363.
+#if PLATFORM(WIN) || defined(BUILDING_ON_TIGER)
+ return deviceRGBColorSpaceRef();
+#else
+ static CGColorSpaceRef sRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
+ return sRGBSpace;
+#endif
+}
+
class GraphicsContextPlatformPrivate {
public:
GraphicsContextPlatformPrivate(CGContextRef cgContext)
diff --git a/WebCore/platform/graphics/cg/ImageCG.cpp b/WebCore/platform/graphics/cg/ImageCG.cpp
index 4da7018..2e372e2 100644
--- a/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -32,6 +32,7 @@
#include "FloatConversion.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
+#include "GraphicsContextPlatformPrivateCG.h"
#include "ImageObserver.h"
#include "PDFDocumentImage.h"
#include "PlatformString.h"
@@ -127,25 +128,46 @@ void BitmapImage::checkForSolidColor()
}
}
+static RetainPtr<CGImageRef> imageWithColorSpace(CGImageRef originalImage, ColorSpace colorSpace)
+{
+ CGColorSpaceRef originalColorSpace = CGImageGetColorSpace(originalImage);
+
+ // If the image already has a (non-device) color space, we don't want to
+ // override it, so return.
+ if (!originalColorSpace || !CFEqual(originalColorSpace, deviceRGBColorSpaceRef()))
+ return originalImage;
+
+ switch (colorSpace) {
+ case DeviceColorSpace:
+ return originalImage;
+ case sRGBColorSpace:
+ return RetainPtr<CGImageRef>(AdoptCF, CGImageCreateCopyWithColorSpace(originalImage,
+ sRGBColorSpaceRef()));
+ }
+
+ ASSERT_NOT_REACHED();
+ return originalImage;
+}
+
CGImageRef BitmapImage::getCGImageRef()
{
return frameAtIndex(0);
}
-void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
startAnimation();
- CGImageRef image = frameAtIndex(m_currentFrame);
+ RetainPtr<CGImageRef> image = frameAtIndex(m_currentFrame);
if (!image) // If it's too early we won't have an image yet.
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, destRect, solidColor(), compositeOp);
+ fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, compositeOp);
return;
}
- float currHeight = CGImageGetHeight(image);
+ float currHeight = CGImageGetHeight(image.get());
if (currHeight <= srcRect.y())
return;
@@ -181,10 +203,10 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
adjustedDestRect.setHeight(subimageRect.height() / yScale);
- image = CGImageCreateWithImageInRect(image, subimageRect);
+ image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
if (currHeight < srcRect.bottom()) {
- ASSERT(CGImageGetHeight(image) == currHeight - CGRectIntegral(srcRect).origin.y);
- adjustedDestRect.setHeight(CGImageGetHeight(image) / yScale);
+ ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
+ adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
}
} else {
adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
@@ -204,11 +226,11 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
CGContextScaleCTM(context, 1, -1);
adjustedDestRect.setY(-adjustedDestRect.bottom());
- // Draw the image.
- CGContextDrawImage(context, adjustedDestRect, image);
+ // Adjust the color space.
+ image = imageWithColorSpace(image.get(), styleColorSpace);
- if (shouldUseSubimage)
- CGImageRelease(image);
+ // Draw the image.
+ CGContextDrawImage(context, adjustedDestRect, image.get());
ctxt->restore();
@@ -223,7 +245,7 @@ static void drawPatternCallback(void* info, CGContextRef context)
}
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
{
if (!nativeImageForCurrentFrame())
return;
@@ -260,6 +282,9 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
ASSERT(h == height());
subImage.adoptCF(CGImageCreateWithImageInRect(tileImage, tileRect));
}
+
+ // Adjust the color space.
+ subImage = imageWithColorSpace(subImage.get(), styleColorSpace);
#ifndef BUILDING_ON_TIGER
// Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index 66246fe..2b2c6b0 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -35,12 +35,27 @@
#include <ApplicationServices/ApplicationServices.h>
#include <wtf/UnusedParam.h>
+using namespace std;
+
namespace WebCore {
static const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
#if !PLATFORM(MAC)
-static void sharedBufferDerefCallback(void*, void* info)
+size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count)
+{
+ SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
+ size_t sourceSize = sharedBuffer->size();
+ if (position >= sourceSize)
+ return 0;
+
+ const char* source = sharedBuffer->data() + position;
+ size_t amount = min<size_t>(count, sourceSize - position);
+ memcpy(buffer, source, amount);
+ return amount;
+}
+
+void sharedBufferRelease(void* info)
{
SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
sharedBuffer->deref();
@@ -110,15 +125,17 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
// On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. We use SharedBuffer's ability
// to wrap itself inside CFData to get around this, ensuring that ImageIO is really looking at the SharedBuffer.
RetainPtr<CFDataRef> cfData(AdoptCF, data->createCFData());
+ CGImageSourceUpdateData(m_decoder, cfData.get(), allDataReceived);
#else
- // If no NSData is available, then we know SharedBuffer will always just be a vector. That means no secret changes can occur to it behind the
- // scenes. We use CFDataCreateWithBytesNoCopy in that case. Ensure that the SharedBuffer lives as long as the CFDataRef.
+ // Create a CGDataProvider to wrap the SharedBuffer.
data->ref();
- CFAllocatorContext context = {0, data, 0, 0, 0, 0, 0, &sharedBufferDerefCallback, 0};
- RetainPtr<CFAllocatorRef> derefAllocator(AdoptCF, CFAllocatorCreate(kCFAllocatorDefault, &context));
- RetainPtr<CFDataRef> cfData(AdoptCF, CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data->data()), data->size(), derefAllocator.get()));
+ // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
+ // does not provide a way to lock down the byte pointer and guarantee that it won't move, which
+ // is a requirement for using the GetBytePointer callback.
+ CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, sharedBufferRelease };
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirect(data, data->size(), &providerCallbacks));
+ CGImageSourceUpdateDataProvider(m_decoder, dataProvider.get(), allDataReceived);
#endif
- CGImageSourceUpdateData(m_decoder, cfData.get(), allDataReceived);
}
String ImageSource::filenameExtension() const
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.h b/WebCore/platform/graphics/cg/ImageSourceCG.h
index d5b4b5a..76b4160 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.h
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.h
@@ -36,6 +36,10 @@ String preferredExtensionForImageSourceType(const String& type);
String MIMETypeForImageSourceType(const String& type);
+#if !PLATFORM(MAC)
+size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count);
+#endif
+
}
#endif // ImageSourceCG_h
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
index 2f5c15e..67333ae 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
@@ -33,6 +33,10 @@
#include "ImageObserver.h"
#include <wtf/MathExtras.h>
+#if !PLATFORM(MAC)
+#include "ImageSourceCG.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -69,12 +73,15 @@ bool PDFDocumentImage::dataChanged(bool allDataReceived)
// On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. We use SharedBuffer's ability
// to wrap itself inside CFData to get around this, ensuring that ImageIO is really looking at the SharedBuffer.
RetainPtr<CFDataRef> data(AdoptCF, this->data()->createCFData());
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(data.get()));
#else
- // If no NSData is available, then we know SharedBuffer will always just be a vector. That means no secret changes can occur to it behind the
- // scenes. We use CFDataCreateWithBytesNoCopy in that case.
- RetainPtr<CFDataRef> data(AdoptCF, CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(this->data()->data()), this->data()->size(), kCFAllocatorNull));
+ // Create a CGDataProvider to wrap the SharedBuffer.
+ // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
+ // does not provide a way to lock down the byte pointer and guarantee that it won't move, which
+ // is a requirement for using the GetBytePointer callback.
+ CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, 0 };
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirect(this->data(), this->data()->size(), &providerCallbacks));
#endif
- RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(data.get()));
m_document = CGPDFDocumentCreateWithProvider(dataProvider.get());
setCurrentPage(0);
}
@@ -139,7 +146,7 @@ int PDFDocumentImage::pageCount() const
return m_document ? CGPDFDocumentGetNumberOfPages(m_document) : 0;
}
-void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op)
+void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator op)
{
if (!m_document || m_currentPage == -1)
return;
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.h b/WebCore/platform/graphics/cg/PDFDocumentImage.h
index 130c12c..12ab46c 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.h
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.h
@@ -58,7 +58,7 @@ namespace WebCore {
virtual IntSize size() const;
PDFDocumentImage();
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
void setCurrentPage(int);
int pageCount() const;