OSDN Git Service

am ffbc540c: (-s ours) am 3f8366e5: Revert to skia\'s decoder for gifs with 1 frame.
[android-x86/external-webkit.git] / WebCore / platform / graphics / cg / GraphicsContext3DCG.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28
29 #if ENABLE(3D_CANVAS)
30
31 #include "GraphicsContext3D.h"
32
33 #include "Image.h"
34
35 #include <CoreGraphics/CGBitmapContext.h>
36 #include <CoreGraphics/CGContext.h>
37 #include <CoreGraphics/CGDataProvider.h>
38 #include <CoreGraphics/CGImage.h>
39
40 #include <wtf/RetainPtr.h>
41
42 namespace WebCore {
43
44 bool GraphicsContext3D::getImageData(Image* image,
45                                      unsigned int format,
46                                      unsigned int type,
47                                      bool premultiplyAlpha,
48                                      Vector<uint8_t>& outputVector)
49 {
50     if (!image)
51         return false;
52     CGImageRef cgImage;
53     RetainPtr<CGImageRef> decodedImage;
54     if (image->data()) {
55         ImageSource decoder(false);
56         decoder.setData(image->data(), true);
57         if (!decoder.frameCount())
58             return false;
59         decodedImage = decoder.createFrameAtIndex(0);
60         cgImage = decodedImage.get();
61     } else
62         cgImage = image->nativeImageForCurrentFrame();
63     if (!cgImage)
64         return false;
65     size_t width = CGImageGetWidth(cgImage);
66     size_t height = CGImageGetHeight(cgImage);
67     if (!width || !height || CGImageGetBitsPerComponent(cgImage) != 8)
68         return false;
69     size_t componentsPerPixel = CGImageGetBitsPerPixel(cgImage) / 8;
70     SourceDataFormat srcDataFormat = kSourceFormatRGBA8;
71     AlphaOp neededAlphaOp = kAlphaDoNothing;
72     switch (CGImageGetAlphaInfo(cgImage)) {
73     case kCGImageAlphaPremultipliedFirst:
74         // This path is only accessible for MacOS earlier than 10.6.4.
75         // This is a special case for texImage2D with HTMLCanvasElement input,
76         // in which case image->data() should be null.
77         ASSERT(!image->data());
78         if (!premultiplyAlpha)
79             neededAlphaOp = kAlphaDoUnmultiply;
80         switch (componentsPerPixel) {
81         case 2:
82             srcDataFormat = kSourceFormatAR8;
83             break;
84         case 4:
85             srcDataFormat = kSourceFormatARGB8;
86             break;
87         default:
88             return false;
89         }
90         break;
91     case kCGImageAlphaFirst:
92         // This path is only accessible for MacOS earlier than 10.6.4.
93         if (premultiplyAlpha)
94             neededAlphaOp = kAlphaDoPremultiply;
95         switch (componentsPerPixel) {
96         case 1:
97             srcDataFormat = kSourceFormatA8;
98             break;
99         case 2:
100             srcDataFormat = kSourceFormatAR8;
101             break;
102         case 4:
103             srcDataFormat = kSourceFormatARGB8;
104             break;
105         default:
106             return false;
107         }
108         break;
109     case kCGImageAlphaNoneSkipFirst:
110         // This path is only accessible for MacOS earlier than 10.6.4.
111         switch (componentsPerPixel) {
112         case 2:
113             srcDataFormat = kSourceFormatAR8;
114             break;
115         case 4:
116             srcDataFormat = kSourceFormatARGB8;
117             break;
118         default:
119             return false;
120         }
121         break;
122     case kCGImageAlphaPremultipliedLast:
123         // This is a special case for texImage2D with HTMLCanvasElement input,
124         // in which case image->data() should be null.
125         ASSERT(!image->data());
126         if (!premultiplyAlpha)
127             neededAlphaOp = kAlphaDoUnmultiply;
128         switch (componentsPerPixel) {
129         case 2:
130             srcDataFormat = kSourceFormatRA8;
131             break;
132         case 4:
133             srcDataFormat = kSourceFormatRGBA8;
134             break;
135         default:
136             return false;
137         }
138         break;
139     case kCGImageAlphaLast:
140         if (premultiplyAlpha)
141             neededAlphaOp = kAlphaDoPremultiply;
142         switch (componentsPerPixel) {
143         case 1:
144             srcDataFormat = kSourceFormatA8;
145             break;
146         case 2:
147             srcDataFormat = kSourceFormatRA8;
148             break;
149         case 4:
150             srcDataFormat = kSourceFormatRGBA8;
151             break;
152         default:
153             return false;
154         }
155         break;
156     case kCGImageAlphaNoneSkipLast:
157         switch (componentsPerPixel) {
158         case 2:
159             srcDataFormat = kSourceFormatRA8;
160             break;
161         case 4:
162             srcDataFormat = kSourceFormatRGBA8;
163             break;
164         default:
165             return false;
166         }
167         break;
168     case kCGImageAlphaNone:
169         switch (componentsPerPixel) {
170         case 1:
171             srcDataFormat = kSourceFormatR8;
172             break;
173         case 3:
174             srcDataFormat = kSourceFormatRGB8;
175             break;
176         default:
177             return false;
178         }
179         break;
180     default:
181         return false;
182     }
183     RetainPtr<CFDataRef> pixelData;
184     pixelData.adoptCF(CGDataProviderCopyData(CGImageGetDataProvider(cgImage)));
185     if (!pixelData)
186         return false;
187     const UInt8* rgba = CFDataGetBytePtr(pixelData.get());
188     outputVector.resize(width * height * 4);
189     unsigned int srcUnpackAlignment = 0;
190     size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
191     unsigned int padding = bytesPerRow - componentsPerPixel * width;
192     if (padding) {
193         srcUnpackAlignment = padding + 1;
194         while (bytesPerRow % srcUnpackAlignment)
195             ++srcUnpackAlignment;
196     }
197     bool rt = packPixels(rgba, srcDataFormat, width, height, srcUnpackAlignment,
198                          format, type, neededAlphaOp, outputVector.data());
199     return rt;
200 }
201
202 void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, CGContextRef context)
203 {
204     if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context)
205         return;
206     int rowBytes = imageWidth * 4;
207     RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithData(0, imagePixels, rowBytes * imageHeight, 0));
208     RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
209     RetainPtr<CGImageRef> cgImage(AdoptCF, CGImageCreate(imageWidth, imageHeight, 8, 32, rowBytes, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
210         dataProvider.get(), 0, false, kCGRenderingIntentDefault));
211     // CSS styling may cause the canvas's content to be resized on
212     // the page. Go back to the Canvas to figure out the correct
213     // width and height to draw.
214     CGRect rect = CGRectMake(0, 0, canvasWidth, canvasHeight);
215     // We want to completely overwrite the previous frame's
216     // rendering results.
217     CGContextSaveGState(context);
218     CGContextSetBlendMode(context, kCGBlendModeCopy);
219     CGContextSetInterpolationQuality(context, kCGInterpolationNone);
220     CGContextDrawImage(context, rect, cgImage.get());
221     CGContextRestoreGState(context);
222 }
223
224 } // namespace WebCore
225
226 #endif // ENABLE(3D_CANVAS)