diff options
author | Steve Block <steveblock@google.com> | 2009-12-15 10:12:09 +0000 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-12-17 17:41:10 +0000 |
commit | 643ca7872b450ea4efacab6188849e5aac2ba161 (patch) | |
tree | 6982576c228bcd1a7efe98afed544d840751094c /WebCore/platform/graphics/cg | |
parent | d026980fde6eb3b01c1fe49441174e89cd1be298 (diff) | |
download | external_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.cpp | 229 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h | 19 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/ImageCG.cpp | 49 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/ImageSourceCG.cpp | 31 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/ImageSourceCG.h | 4 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/PDFDocumentImage.cpp | 17 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/PDFDocumentImage.h | 2 |
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; |