diff options
Diffstat (limited to 'WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp')
-rw-r--r-- | WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp | 147 |
1 files changed, 97 insertions, 50 deletions
diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index df14f9d..c4008cc 100644 --- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -34,6 +34,7 @@ #include <CoreGraphics/CGBitmapContext.h> #include <CoreGraphics/CGContext.h> +#include <CoreGraphics/CGDataProvider.h> #include <CoreGraphics/CGImage.h> #include <wtf/RetainPtr.h> @@ -48,62 +49,108 @@ bool GraphicsContext3D::getImageData(Image* image, { if (!image) return false; - CGImageRef cgImage = image->nativeImageForCurrentFrame(); + CGImageRef cgImage; + RetainPtr<CGImageRef> decodedImage; + if (image->data()) { + ImageSource decoder(false); + decoder.setData(image->data(), true); + if (!decoder.frameCount()) + return false; + decodedImage = decoder.createFrameAtIndex(0); + cgImage = decodedImage.get(); + } else + cgImage = image->nativeImageForCurrentFrame(); if (!cgImage) return false; - int width = CGImageGetWidth(cgImage); - int height = CGImageGetHeight(cgImage); - // FIXME: we should get rid of this temporary copy where possible. - int tempRowBytes = width * 4; - Vector<uint8_t> tempVector; - tempVector.resize(height * tempRowBytes); - // Try to reuse the color space from the image to preserve its colors. - // Some images use a color space (such as indexed) unsupported by the bitmap context. - CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage); - bool releaseColorSpace = false; - CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); - switch (colorSpaceModel) { - case kCGColorSpaceModelMonochrome: - case kCGColorSpaceModelRGB: - case kCGColorSpaceModelCMYK: - case kCGColorSpaceModelLab: - case kCGColorSpaceModelDeviceN: + size_t width = CGImageGetWidth(cgImage); + size_t height = CGImageGetHeight(cgImage); + if (!width || !height || CGImageGetBitsPerComponent(cgImage) != 8) + return false; + size_t componentsPerPixel = CGImageGetBitsPerPixel(cgImage) / 8; + SourceDataFormat srcDataFormat = kSourceFormatRGBA8; + AlphaOp neededAlphaOp = kAlphaDoNothing; + switch (CGImageGetAlphaInfo(cgImage)) { + case kCGImageAlphaPremultipliedFirst: + case kCGImageAlphaFirst: + case kCGImageAlphaNoneSkipFirst: + return false; + case kCGImageAlphaPremultipliedLast: + // This is a special case for texImage2D with HTMLCanvasElement input, + // in which case image->data() should be null. + ASSERT(!image->data()); + if (!premultiplyAlpha) + neededAlphaOp = kAlphaDoUnmultiply; + switch (componentsPerPixel) { + case 2: + srcDataFormat = kSourceFormatRA8; + break; + case 4: + srcDataFormat = kSourceFormatRGBA8; + break; + default: + return false; + } break; - default: - colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear); - releaseColorSpace = true; + case kCGImageAlphaLast: + if (premultiplyAlpha) + neededAlphaOp = kAlphaDoPremultiply; + switch (componentsPerPixel) { + case 1: + srcDataFormat = kSourceFormatA8; + break; + case 2: + srcDataFormat = kSourceFormatRA8; + break; + case 4: + srcDataFormat = kSourceFormatRGBA8; + break; + default: + return false; + } break; - } - CGContextRef tempContext = CGBitmapContextCreate(tempVector.data(), - width, height, 8, tempRowBytes, - colorSpace, - // FIXME: change this! - kCGImageAlphaPremultipliedLast); - if (releaseColorSpace) - CGColorSpaceRelease(colorSpace); - if (!tempContext) + case kCGImageAlphaNoneSkipLast: + switch (componentsPerPixel) { + case 2: + srcDataFormat = kSourceFormatRA8; + break; + case 4: + srcDataFormat = kSourceFormatRGBA8; + break; + default: + return false; + } + case kCGImageAlphaNone: + switch (componentsPerPixel) { + case 1: + srcDataFormat = kSourceFormatR8; + break; + case 3: + srcDataFormat = kSourceFormatRGB8; + break; + default: + return false; + } + break; + default: return false; - CGContextSetBlendMode(tempContext, kCGBlendModeCopy); - CGContextDrawImage(tempContext, - CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)), - cgImage); - CGContextRelease(tempContext); - // Pack the pixel data into the output vector. - unsigned long componentsPerPixel, bytesPerComponent; - if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) + } + RetainPtr<CFDataRef> pixelData; + pixelData.adoptCF(CGDataProviderCopyData(CGImageGetDataProvider(cgImage))); + if (!pixelData) return false; - int rowBytes = width * componentsPerPixel * bytesPerComponent; - outputVector.resize(height * rowBytes); - CGImageAlphaInfo info = CGImageGetAlphaInfo(cgImage); - bool hasAlphaChannel = (info != kCGImageAlphaNone - && info != kCGImageAlphaNoneSkipLast - && info != kCGImageAlphaNoneSkipFirst); - AlphaOp neededAlphaOp = kAlphaDoNothing; - if (!premultiplyAlpha && hasAlphaChannel) - // FIXME: must fetch the image data before the premultiplication step. - neededAlphaOp = kAlphaDoUnmultiply; - return packPixels(tempVector.data(), kSourceFormatRGBA8, width, height, 0, - format, type, neededAlphaOp, outputVector.data()); + const UInt8* rgba = CFDataGetBytePtr(pixelData.get()); + outputVector.resize(width * height * 4); + unsigned int srcUnpackAlignment = 0; + size_t bytesPerRow = CGImageGetBytesPerRow(cgImage); + unsigned int padding = bytesPerRow - componentsPerPixel * width; + if (padding) { + srcUnpackAlignment = padding + 1; + while (bytesPerRow % srcUnpackAlignment) + ++srcUnpackAlignment; + } + bool rt = packPixels(rgba, srcDataFormat, width, height, srcUnpackAlignment, + format, type, neededAlphaOp, outputVector.data()); + return rt; } void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, CGContextRef context) |