diff options
Diffstat (limited to 'WebCore/platform/graphics/cg')
-rw-r--r-- | WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp | 3 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/GraphicsContextCG.cpp | 185 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/ImageBufferCG.cpp | 314 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/ImageBufferData.h | 2 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/ImageSourceCG.cpp | 13 | ||||
-rw-r--r-- | WebCore/platform/graphics/cg/TransformationMatrixCG.cpp | 10 |
6 files changed, 359 insertions, 168 deletions
diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index 7a58eed..f997277 100644 --- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -99,7 +99,8 @@ bool GraphicsContext3D::getImageData(Image* image, CGImageRef cgImage; RetainPtr<CGImageRef> decodedImage; if (image->data()) { - ImageSource decoder(false, ignoreGammaAndColorProfile); + ImageSource decoder(ImageSource::AlphaNotPremultiplied, + ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied); decoder.setData(image->data(), true); if (!decoder.frameCount()) return false; diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index 8d72b85..7898d62 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -31,7 +31,6 @@ #include "AffineTransform.h" #include "FloatConversion.h" #include "GraphicsContextPlatformPrivateCG.h" -#include "GraphicsContextPrivate.h" #include "ImageBuffer.h" #include "KURL.h" #include "Path.h" @@ -42,6 +41,7 @@ #include <wtf/MathExtras.h> #include <wtf/OwnArrayPtr.h> #include <wtf/RetainPtr.h> +#include <wtf/UnusedParam.h> #if PLATFORM(MAC) || PLATFORM(CHROMIUM) #include "WebCoreSystemInterface.h" @@ -107,10 +107,9 @@ CGColorSpaceRef linearRGBColorSpaceRef() #endif } -GraphicsContext::GraphicsContext(CGContextRef cgContext) - : m_common(createGraphicsContextPrivate()) - , m_data(new GraphicsContextPlatformPrivate(cgContext)) +void GraphicsContext::platformInit(CGContextRef cgContext) { + m_data = new GraphicsContextPlatformPrivate(cgContext); setPaintingDisabled(!cgContext); if (cgContext) { // Make sure the context starts in sync with our state. @@ -119,9 +118,8 @@ GraphicsContext::GraphicsContext(CGContextRef cgContext) } } -GraphicsContext::~GraphicsContext() +void GraphicsContext::platformDestroy() { - destroyGraphicsContextPrivate(m_common); delete m_data; } @@ -299,21 +297,12 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) // This method is only used to draw the little circles used in lists. void GraphicsContext::drawEllipse(const IntRect& rect) { - // FIXME: CG added CGContextAddEllipseinRect in Tiger, so we should be able to quite easily draw an ellipse. - // This code can only handle circles, not ellipses. But khtml only - // uses it for circles. - ASSERT(rect.width() == rect.height()); - if (paintingDisabled()) return; - CGContextRef context = platformContext(); - CGContextBeginPath(context); - float r = (float)rect.width() / 2; - CGContextAddArc(context, rect.x() + r, rect.y() + r, r, 0.0f, 2.0f * piFloat, 0); - CGContextClosePath(context); - - drawPath(); + Path path; + path.addEllipse(rect); + drawPath(path); } @@ -405,21 +394,22 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp CGContextRestoreGState(context); } -static void addConvexPolygonToContext(CGContextRef context, size_t numPoints, const FloatPoint* points) +static void addConvexPolygonToPath(Path& path, size_t numberOfPoints, const FloatPoint* points) { - CGContextBeginPath(context); - CGContextMoveToPoint(context, points[0].x(), points[0].y()); - for (size_t i = 1; i < numPoints; i++) - CGContextAddLineToPoint(context, points[i].x(), points[i].y()); - CGContextClosePath(context); + ASSERT(numberOfPoints > 0); + + path.moveTo(points[0]); + for (size_t i = 1; i < numberOfPoints; ++i) + path.addLineTo(points[i]); + path.closeSubpath(); } -void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool antialiased) +void GraphicsContext::drawConvexPolygon(size_t numberOfPoints, const FloatPoint* points, bool antialiased) { if (paintingDisabled()) return; - if (npoints <= 1) + if (numberOfPoints <= 1) return; CGContextRef context = platformContext(); @@ -427,28 +417,30 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points if (antialiased != shouldAntialias()) CGContextSetShouldAntialias(context, antialiased); - addConvexPolygonToContext(context, npoints, points); - drawPath(); + Path path; + addConvexPolygonToPath(path, numberOfPoints, points); + drawPath(path); if (antialiased != shouldAntialias()) CGContextSetShouldAntialias(context, shouldAntialias()); } -void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialias) +void GraphicsContext::clipConvexPolygon(size_t numberOfPoints, const FloatPoint* points, bool antialias) { if (paintingDisabled()) return; - if (numPoints <= 1) + if (numberOfPoints <= 1) return; CGContextRef context = platformContext(); if (antialias != shouldAntialias()) CGContextSetShouldAntialias(context, antialias); - - addConvexPolygonToContext(context, numPoints, points); - clipPath(RULE_NONZERO); + + Path path; + addConvexPolygonToPath(path, numberOfPoints, points); + clipPath(path, RULE_NONZERO); if (antialias != shouldAntialias()) CGContextSetShouldAntialias(context, shouldAntialias()); @@ -458,7 +450,7 @@ void GraphicsContext::applyStrokePattern() { CGContextRef cgContext = platformContext(); - RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.strokePattern->createPlatformPattern(getCTM())); + RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_state.strokePattern->createPlatformPattern(getCTM())); if (!platformPattern) return; @@ -473,7 +465,7 @@ void GraphicsContext::applyFillPattern() { CGContextRef cgContext = platformContext(); - RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.fillPattern->createPlatformPattern(getCTM())); + RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_state.fillPattern->createPlatformPattern(getCTM())); if (!platformPattern) return; @@ -511,21 +503,25 @@ static inline bool calculateDrawingMode(const GraphicsContextState& state, CGPat return shouldFill || shouldStroke; } -void GraphicsContext::drawPath() +void GraphicsContext::drawPath(const Path& path) { if (paintingDisabled()) return; CGContextRef context = platformContext(); - const GraphicsContextState& state = m_common->state; + const GraphicsContextState& state = m_state; if (state.fillGradient || state.strokeGradient) { // We don't have any optimized way to fill & stroke a path using gradients - fillPath(); - strokePath(); + // FIXME: Be smarter about this. + fillPath(path); + strokePath(path); return; } + CGContextBeginPath(context); + CGContextAddPath(context, path.platformPath()); + if (state.fillPattern) applyFillPattern(); if (state.strokePattern) @@ -544,48 +540,54 @@ static inline void fillPathWithFillRule(CGContextRef context, WindRule fillRule) CGContextFillPath(context); } -void GraphicsContext::fillPath() +void GraphicsContext::fillPath(const Path& path) { if (paintingDisabled()) return; CGContextRef context = platformContext(); - if (m_common->state.fillGradient) { + CGContextBeginPath(context); + CGContextAddPath(context, path.platformPath()); + + if (m_state.fillGradient) { CGContextSaveGState(context); if (fillRule() == RULE_EVENODD) CGContextEOClip(context); else CGContextClip(context); - CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform()); - m_common->state.fillGradient->paint(this); + CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform()); + m_state.fillGradient->paint(this); CGContextRestoreGState(context); return; } - if (m_common->state.fillPattern) + if (m_state.fillPattern) applyFillPattern(); fillPathWithFillRule(context, fillRule()); } -void GraphicsContext::strokePath() +void GraphicsContext::strokePath(const Path& path) { if (paintingDisabled()) return; CGContextRef context = platformContext(); - if (m_common->state.strokeGradient) { + CGContextBeginPath(context); + CGContextAddPath(context, path.platformPath()); + + if (m_state.strokeGradient) { CGContextSaveGState(context); CGContextReplacePathWithStrokedPath(context); CGContextClip(context); - CGContextConcatCTM(context, m_common->state.strokeGradient->gradientSpaceTransform()); - m_common->state.strokeGradient->paint(this); + CGContextConcatCTM(context, m_state.strokeGradient->gradientSpaceTransform()); + m_state.strokeGradient->paint(this); CGContextRestoreGState(context); return; } - if (m_common->state.strokePattern) + if (m_state.strokePattern) applyStrokePattern(); CGContextStrokePath(context); } @@ -597,16 +599,16 @@ void GraphicsContext::fillRect(const FloatRect& rect) CGContextRef context = platformContext(); - if (m_common->state.fillGradient) { + if (m_state.fillGradient) { CGContextSaveGState(context); CGContextClipToRect(context, rect); - CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform()); - m_common->state.fillGradient->paint(this); + CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform()); + m_state.fillGradient->paint(this); CGContextRestoreGState(context); return; } - if (m_common->state.fillPattern) + if (m_state.fillPattern) applyFillPattern(); CGContextFillRect(context, rect); } @@ -643,8 +645,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef Path path; path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight); - addPath(path); - fillPath(); + fillPath(path); if (oldFillColor != color || oldColorSpace != colorSpace) setCGFillColor(context, oldFillColor, oldColorSpace); @@ -669,19 +670,23 @@ void GraphicsContext::clipOut(const IntRect& rect) CGContextEOClip(platformContext()); } -void GraphicsContext::clipPath(WindRule clipRule) +void GraphicsContext::clipPath(const Path& path, WindRule clipRule) { if (paintingDisabled()) return; + if (path.isEmpty()) + return; + CGContextRef context = platformContext(); - if (!CGContextIsPathEmpty(context)) { - if (clipRule == RULE_EVENODD) - CGContextEOClip(context); - else - CGContextClip(context); - } + CGContextBeginPath(platformContext()); + CGContextAddPath(platformContext(), path.platformPath()); + + if (clipRule == RULE_EVENODD) + CGContextEOClip(context); + else + CGContextClip(context); } void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) @@ -733,7 +738,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con CGFloat blurRadius = blur; CGContextRef context = platformContext(); - if (!m_common->state.shadowsIgnoreTransforms) { + if (!m_state.shadowsIgnoreTransforms) { CGAffineTransform userToBaseCTM = wkGetUserToBaseCTM(context); CGFloat A = userToBaseCTM.a * userToBaseCTM.a + userToBaseCTM.b * userToBaseCTM.b; @@ -808,18 +813,18 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth) CGContextRef context = platformContext(); - if (m_common->state.strokeGradient) { + if (m_state.strokeGradient) { CGContextSaveGState(context); setStrokeThickness(lineWidth); CGContextAddRect(context, r); CGContextReplacePathWithStrokedPath(context); CGContextClip(context); - m_common->state.strokeGradient->paint(this); + m_state.strokeGradient->paint(this); CGContextRestoreGState(context); return; } - if (m_common->state.strokePattern) + if (m_state.strokePattern) applyStrokePattern(); CGContextStrokeRectWithWidth(context, r, lineWidth); } @@ -863,16 +868,6 @@ void GraphicsContext::setLineJoin(LineJoin join) } } -void GraphicsContext::beginPath() -{ - CGContextBeginPath(platformContext()); -} - -void GraphicsContext::addPath(const Path& path) -{ - CGContextAddPath(platformContext(), path.platformPath()); -} - void GraphicsContext::clip(const Path& path) { if (paintingDisabled()) @@ -1119,7 +1114,16 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const return InterpolationDefault; } -void GraphicsContext::setPlatformTextDrawingMode(int mode) +void GraphicsContext::setAllowsFontSmoothing(bool allowsFontSmoothing) +{ + UNUSED_PARAM(allowsFontSmoothing); +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + CGContextRef context = platformContext(); + CGContextSetAllowsFontSmoothing(context, allowsFontSmoothing); +#endif +} + +void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode) { if (paintingDisabled()) return; @@ -1127,28 +1131,28 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode) // Wow, wish CG had used bits here. CGContextRef context = platformContext(); switch (mode) { - case cTextInvisible: // Invisible + case TextModeInvisible: CGContextSetTextDrawingMode(context, kCGTextInvisible); break; - case cTextFill: // Fill + case TextModeFill: CGContextSetTextDrawingMode(context, kCGTextFill); break; - case cTextStroke: // Stroke + case TextModeStroke: CGContextSetTextDrawingMode(context, kCGTextStroke); break; - case 3: // Fill | Stroke + case TextModeFill | TextModeStroke: CGContextSetTextDrawingMode(context, kCGTextFillStroke); break; - case cTextClip: // Clip + case TextModeClip: CGContextSetTextDrawingMode(context, kCGTextClip); break; - case 5: // Fill | Clip + case TextModeFill | TextModeClip: CGContextSetTextDrawingMode(context, kCGTextFillClip); break; - case 6: // Stroke | Clip + case TextModeStroke | TextModeClip: CGContextSetTextDrawingMode(context, kCGTextStrokeClip); break; - case 7: // Fill | Stroke | Clip + case TextModeFill | TextModeStroke | TextModeClip: CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip); break; default: @@ -1184,8 +1188,15 @@ void GraphicsContext::setPlatformShouldAntialias(bool enable) CGContextSetShouldAntialias(platformContext(), enable); } -#ifndef BUILDING_ON_TIGER // Tiger's setCompositeOperation() is defined in GraphicsContextMac.mm. -void GraphicsContext::setCompositeOperation(CompositeOperator mode) +void GraphicsContext::setPlatformShouldSmoothFonts(bool enable) +{ + if (paintingDisabled()) + return; + CGContextSetShouldSmoothFonts(platformContext(), enable); +} + +#ifndef BUILDING_ON_TIGER // Tiger's setPlatformCompositeOperation() is defined in GraphicsContextMac.mm. +void GraphicsContext::setPlatformCompositeOperation(CompositeOperator mode) { if (paintingDisabled()) return; diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp index 640692a..7bc47f2 100644 --- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp +++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp @@ -42,10 +42,57 @@ #include <wtf/Threading.h> #include <math.h> +#if defined(USE_IOSURFACE) +#include <IOSurface/IOSurface.h> +#endif + +#if PLATFORM(MAC) || PLATFORM(CHROMIUM) +#include "WebCoreSystemInterface.h" +#endif + using namespace std; namespace WebCore { +#if defined(USE_IOSURFACE) +static RetainPtr<IOSurfaceRef> createIOSurface(const IntSize& size) +{ + unsigned pixelFormat = 'BGRA'; + unsigned bytesPerElement = 4; + int width = size.width(); + int height = size.height(); + + unsigned long bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, size.width() * bytesPerElement); + if (!bytesPerRow) + return 0; + + unsigned long allocSize = IOSurfaceAlignProperty(kIOSurfaceAllocSize, size.height() * bytesPerRow); + if (!allocSize) + return 0; + + const void *keys[6]; + const void *values[6]; + keys[0] = kIOSurfaceWidth; + values[0] = CFNumberCreate(0, kCFNumberIntType, &width); + keys[1] = kIOSurfaceHeight; + values[1] = CFNumberCreate(0, kCFNumberIntType, &height); + keys[2] = kIOSurfacePixelFormat; + values[2] = CFNumberCreate(0, kCFNumberIntType, &pixelFormat); + keys[3] = kIOSurfaceBytesPerElement; + values[3] = CFNumberCreate(0, kCFNumberIntType, &bytesPerElement); + keys[4] = kIOSurfaceBytesPerRow; + values[4] = CFNumberCreate(0, kCFNumberLongType, &bytesPerRow); + keys[5] = kIOSurfaceAllocSize; + values[5] = CFNumberCreate(0, kCFNumberLongType, &allocSize); + + RetainPtr<CFDictionaryRef> dict(AdoptCF, CFDictionaryCreate(0, keys, values, 6, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + for (unsigned i = 0; i < 6; i++) + CFRelease(values[i]); + + return RetainPtr<IOSurfaceRef>(AdoptCF, IOSurfaceCreate(dict.get())); +} +#endif + static void releaseImageData(void*, const void* data, size_t) { fastFree(const_cast<void*>(data)); @@ -53,32 +100,32 @@ static void releaseImageData(void*, const void* data, size_t) ImageBufferData::ImageBufferData(const IntSize&) : m_data(0) +#if defined(USE_IOSURFACE) + , m_surface(0) +#endif { } -ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, bool& success) +ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, bool& success) : m_data(size) , m_size(size) + , m_accelerateRendering(renderingMode == Accelerated) { +#if !defined(USE_IOSURFACE) + ASSERT(renderingMode == Unaccelerated); +#endif success = false; // Make early return mean failure. if (size.width() < 0 || size.height() < 0) return; unsigned bytesPerRow = size.width(); - - // Protect against overflow - if (bytesPerRow > 0x3FFFFFFF) + if (bytesPerRow > 0x3FFFFFFF) // Protect against overflow return; bytesPerRow *= 4; m_data.m_bytesPerRow = bytesPerRow; - size_t dataSize = size.height() * bytesPerRow; - if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data)) - return; - - ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0); - switch(imageColorSpace) { + switch (imageColorSpace) { case ColorSpaceDeviceRGB: m_data.m_colorSpace = deviceRGBColorSpaceRef(); break; @@ -90,9 +137,25 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, bool& break; } - m_data.m_bitmapInfo = kCGImageAlphaPremultipliedLast; - RetainPtr<CGContextRef> cgContext(AdoptCF, CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow, - m_data.m_colorSpace, m_data.m_bitmapInfo)); + RetainPtr<CGContextRef> cgContext; + if (!m_accelerateRendering) { + if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data)) + return; + ASSERT(!(reinterpret_cast<size_t>(m_data.m_data) & 2)); + + m_data.m_bitmapInfo = kCGImageAlphaPremultipliedLast; + cgContext.adoptCF(CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow, m_data.m_colorSpace, m_data.m_bitmapInfo)); + // Create a live image that wraps the data. + m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, dataSize, releaseImageData)); + } else { +#if defined(USE_IOSURFACE) + m_data.m_surface = createIOSurface(size); + cgContext.adoptCF(wkIOSurfaceContextCreate(m_data.m_surface.get(), size.width(), size.height(), m_data.m_colorSpace)); +#else + m_accelerateRendering = false; // Force to false on older platforms +#endif + } + if (!cgContext) return; @@ -100,9 +163,6 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, bool& m_context->scale(FloatSize(1, -1)); m_context->translate(0, -size.height()); success = true; - - // Create a live image that wraps the data. - m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, dataSize, releaseImageData)); } ImageBuffer::~ImageBuffer() @@ -122,7 +182,14 @@ bool ImageBuffer::drawsUsingCopy() const PassRefPtr<Image> ImageBuffer::copyImage() const { // BitmapImage will release the passed in CGImage on destruction - return BitmapImage::create(CGBitmapContextCreateImage(context()->platformContext())); + CGImageRef ctxImage = 0; + if (!m_accelerateRendering) + ctxImage = CGBitmapContextCreateImage(context()->platformContext()); +#if defined(USE_IOSURFACE) + else + ctxImage = wkIOSurfaceContextCreateImage(context()->platformContext()); +#endif + return BitmapImage::create(ctxImage); } static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data) @@ -134,34 +201,50 @@ static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data) void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, bool useLowQualityScale) { - 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(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale); + if (!m_accelerateRendering) { + 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(), 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); + } } else { - RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data)); - destContext->drawImage(imageForRendering.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale); + RefPtr<Image> copy = copyImage(); + ColorSpace colorSpace = (destContext == context()) ? ColorSpaceDeviceRGB : styleColorSpace; + destContext->drawImage(copy.get(), colorSpace, destRect, srcRect, op, useLowQualityScale); } } void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) { - if (destContext == context()) { - // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first. + if (!m_accelerateRendering) { + 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(); + copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); + } else { + RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data)); + imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); + } + } else { RefPtr<Image> copy = copyImage(); copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); - } else { - RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data)); - imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); } } void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const { - RetainPtr<CGImageRef> image(AdoptCF, cgImage(m_size, m_data)); - CGContextRef platformContext = context->platformContext(); + RetainPtr<CGImageRef> image; + if (!m_accelerateRendering) + image.adoptCF(cgImage(m_size, m_data)); +#if defined(USE_IOSURFACE) + else + image.adoptCF(wkIOSurfaceContextCreateImage(platformContext)); +#endif CGContextTranslateCTM(platformContext, rect.x(), rect.y() + rect.height()); CGContextScaleCTM(platformContext, 1, -1); CGContextClipToMask(platformContext, FloatRect(FloatPoint(), rect.size()), image.get()); @@ -170,7 +253,7 @@ void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const } template <Multiply multiplied> -PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size) +PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size, bool accelerateRendering) { PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height()); unsigned char* data = result->data()->data()->data(); @@ -199,43 +282,83 @@ PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& i if (endy > size.height()) endy = size.height(); int numRows = endy - originy; - - unsigned srcBytesPerRow = 4 * size.width(); + unsigned destBytesPerRow = 4 * rect.width(); - - // ::create ensures that all ImageBuffers have valid data, so we don't need to check it here. - unsigned char* srcRows = reinterpret_cast<unsigned char*>(imageData.m_data) + originy * srcBytesPerRow + originx * 4; unsigned char* destRows = data + desty * destBytesPerRow + destx * 4; - for (int y = 0; y < numRows; ++y) { - for (int x = 0; x < numColumns; x++) { - int basex = x * 4; - unsigned char alpha = srcRows[basex + 3]; - if (multiplied == Unmultiplied && alpha) { - destRows[basex] = (srcRows[basex] * 255) / alpha; - destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; - destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha; - destRows[basex + 3] = alpha; - } else - reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; + + unsigned srcBytesPerRow; + unsigned char* srcRows; + + if (!accelerateRendering) { + srcBytesPerRow = 4 * size.width(); + srcRows = reinterpret_cast<unsigned char*>(imageData.m_data) + originy * srcBytesPerRow + originx * 4; + + for (int y = 0; y < numRows; ++y) { + for (int x = 0; x < numColumns; x++) { + int basex = x * 4; + unsigned char alpha = srcRows[basex + 3]; + if (multiplied == Unmultiplied && alpha) { + destRows[basex] = (srcRows[basex] * 255) / alpha; + destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; + destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha; + destRows[basex + 3] = alpha; + } else + reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; + } + srcRows += srcBytesPerRow; + destRows += destBytesPerRow; + } + } else { +#if defined(USE_IOSURFACE) + IOSurfaceRef surface = imageData.m_surface.get(); + IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0); + srcBytesPerRow = IOSurfaceGetBytesPerRow(surface); + srcRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + originy * srcBytesPerRow + originx * 4; + + for (int y = 0; y < numRows; ++y) { + for (int x = 0; x < numColumns; x++) { + int basex = x * 4; + unsigned char alpha = srcRows[basex + 3]; + if (multiplied == Unmultiplied && alpha) { + destRows[basex] = (srcRows[basex + 2] * 255) / alpha; + destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; + destRows[basex + 2] = (srcRows[basex] * 255) / alpha; + destRows[basex + 3] = alpha; + } else { + destRows[basex] = srcRows[basex + 2]; + destRows[basex + 1] = srcRows[basex + 1]; + destRows[basex + 2] = srcRows[basex]; + destRows[basex + 3] = alpha; + } + } + srcRows += srcBytesPerRow; + destRows += destBytesPerRow; } - srcRows += srcBytesPerRow; - destRows += destBytesPerRow; + IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0); +#else + ASSERT_NOT_REACHED(); +#endif } + return result; } PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const { - return getImageData<Unmultiplied>(rect, m_data, m_size); + if (m_accelerateRendering) + CGContextFlush(context()->platformContext()); + return getImageData<Unmultiplied>(rect, m_data, m_size, m_accelerateRendering); } PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const { - return getImageData<Premultiplied>(rect, m_data, m_size); + if (m_accelerateRendering) + CGContextFlush(context()->platformContext()); + return getImageData<Premultiplied>(rect, m_data, m_size, m_accelerateRendering); } template <Multiply multiplied> -void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size) +void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size, bool accelerateRendering) { ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); @@ -264,35 +387,73 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& int numRows = endy - desty; unsigned srcBytesPerRow = 4 * source->width(); - unsigned destBytesPerRow = 4 * size.width(); - unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4; - unsigned char* destRows = reinterpret_cast<unsigned char*>(imageData.m_data) + desty * destBytesPerRow + destx * 4; - for (int y = 0; y < numRows; ++y) { - for (int x = 0; x < numColumns; x++) { - int basex = x * 4; - unsigned char alpha = srcRows[basex + 3]; - if (multiplied == Unmultiplied && alpha != 255) { - destRows[basex] = (srcRows[basex] * alpha + 254) / 255; - destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; - destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255; - destRows[basex + 3] = alpha; - } else - reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; + unsigned destBytesPerRow; + unsigned char* destRows; + + if (!accelerateRendering) { + destBytesPerRow = 4 * size.width(); + destRows = reinterpret_cast<unsigned char*>(imageData.m_data) + desty * destBytesPerRow + destx * 4; + for (int y = 0; y < numRows; ++y) { + for (int x = 0; x < numColumns; x++) { + int basex = x * 4; + unsigned char alpha = srcRows[basex + 3]; + if (multiplied == Unmultiplied && alpha != 255) { + destRows[basex] = (srcRows[basex] * alpha + 254) / 255; + destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; + destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255; + destRows[basex + 3] = alpha; + } else + reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; + } + destRows += destBytesPerRow; + srcRows += srcBytesPerRow; + } + } else { +#if defined(USE_IOSURFACE) + IOSurfaceRef surface = imageData.m_surface.get(); + IOSurfaceLock(surface, 0, 0); + destBytesPerRow = IOSurfaceGetBytesPerRow(surface); + destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + desty * destBytesPerRow + destx * 4; + + for (int y = 0; y < numRows; ++y) { + for (int x = 0; x < numColumns; x++) { + int basex = x * 4; + unsigned char alpha = srcRows[basex + 3]; + if (multiplied == Unmultiplied && alpha != 255) { + destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255; + destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; + destRows[basex + 2] = (srcRows[basex] * alpha + 254) / 255; + destRows[basex + 3] = alpha; + } else { + destRows[basex] = srcRows[basex + 2]; + destRows[basex + 1] = srcRows[basex + 1]; + destRows[basex + 2] = srcRows[basex]; + destRows[basex + 3] = alpha; + } + } + destRows += destBytesPerRow; + srcRows += srcBytesPerRow; } - destRows += destBytesPerRow; - srcRows += srcBytesPerRow; + IOSurfaceUnlock(surface, 0, 0); +#else + ASSERT_NOT_REACHED(); +#endif } } void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) { - putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size); + if (m_accelerateRendering) + CGContextFlush(context()->platformContext()); + putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size, m_accelerateRendering); } void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) { - putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size); + if (m_accelerateRendering) + CGContextFlush(context()->platformContext()); + putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size, m_accelerateRendering); } static inline CFStringRef jpegUTI() @@ -332,7 +493,14 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); - RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(context()->platformContext())); + RetainPtr<CGImageRef> image; + if (!m_accelerateRendering) + image.adoptCF(CGBitmapContextCreateImage(context()->platformContext())); +#if defined(USE_IOSURFACE) + else + image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext())); +#endif + if (!image) return "data:,"; @@ -361,9 +529,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con Vector<char> out; base64Encode(reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())), CFDataGetLength(data.get()), out); - out.append('\0'); - return makeString("data:", mimeType, ";base64,", out.data()); + return makeString("data:", mimeType, ";base64,", out); } - } // namespace WebCore diff --git a/WebCore/platform/graphics/cg/ImageBufferData.h b/WebCore/platform/graphics/cg/ImageBufferData.h index 456c934..1f706ec 100644 --- a/WebCore/platform/graphics/cg/ImageBufferData.h +++ b/WebCore/platform/graphics/cg/ImageBufferData.h @@ -30,6 +30,7 @@ #include <wtf/RefPtr.h> #include <wtf/RetainPtr.h> +typedef struct __IOSurface *IOSurfaceRef; typedef struct CGColorSpace *CGColorSpaceRef; typedef struct CGDataProvider *CGDataProviderRef; typedef uint32_t CGBitmapInfo; @@ -48,6 +49,7 @@ public: CGBitmapInfo m_bitmapInfo; unsigned m_bytesPerRow; CGColorSpaceRef m_colorSpace; + RetainPtr<IOSurfaceRef> m_surface; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp index f01c442..4ed8684 100644 --- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp +++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp @@ -63,11 +63,11 @@ void sharedBufferRelease(void* info) } #endif -ImageSource::ImageSource(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) +ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) : m_decoder(0) // FIXME: m_premultiplyAlpha is ignored in cg at the moment. - , m_premultiplyAlpha(premultiplyAlpha) - , m_ignoreGammaAndColorProfile(ignoreGammaAndColorProfile) + , m_alphaOption(alphaOption) + , m_gammaAndColorProfileOption(gammaAndColorProfileOption) { } @@ -308,9 +308,10 @@ float ImageSource::frameDurationAtIndex(size_t index) } // Many annoying ads specify a 0 duration to make an image flash as quickly as possible. - // We follow WinIE's behavior and use a duration of 100 ms for any frames that specify - // a duration of <= 50 ms. See <http://bugs.webkit.org/show_bug.cgi?id=14413> or Radar 4051389 for more. - if (duration < 0.051f) + // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify + // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082> + // for more information. + if (duration < 0.011f) return 0.100f; return duration; } diff --git a/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp b/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp index 5fe2122..ec40836 100644 --- a/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp +++ b/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp @@ -34,6 +34,16 @@ namespace WebCore { +TransformationMatrix::TransformationMatrix(const CGAffineTransform& t) +{ + setA(t.a); + setB(t.b); + setC(t.c); + setD(t.d); + setE(t.tx); + setF(t.ty); +} + TransformationMatrix::operator CGAffineTransform() const { return CGAffineTransformMake(narrowPrecisionToCGFloat(a()), |