1 /* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * Copyright (C) 2010 Google Inc. All rights reserved. 4 * Copyright (C) 2011 Igalia S.L. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "config.h" 29 #include "GraphicsContext3D.h" 30 #include "PlatformContextCairo.h" 31 32 #if ENABLE(WEBGL) 33 34 #include "Image.h" 35 #include "RefPtrCairo.h" 36 #include <cairo.h> 37 #include <wtf/PassOwnPtr.h> 38 39 namespace WebCore { 40 41 bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) 42 { 43 if (!image) 44 return false; 45 // We need this to stay in scope because the native image is just a shallow copy of the data. 46 ImageSource decoder(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, 47 ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied); 48 AlphaOp alphaOp = AlphaDoNothing; 49 RefPtr<cairo_surface_t> imageSurface; 50 if (image->data()) { 51 decoder.setData(image->data(), true); 52 if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0)) 53 return false; 54 imageSurface = decoder.createFrameAtIndex(0); 55 } else { 56 imageSurface = image->nativeImageForCurrentFrame(); 57 if (!premultiplyAlpha) 58 alphaOp = AlphaDoUnmultiply; 59 } 60 61 if (!imageSurface) 62 return false; 63 64 int width = cairo_image_surface_get_width(imageSurface.get()); 65 int height = cairo_image_surface_get_height(imageSurface.get()); 66 if (!width || !height) 67 return false; 68 69 if (cairo_image_surface_get_format(imageSurface.get()) != CAIRO_FORMAT_ARGB32) 70 return false; 71 72 unsigned int srcUnpackAlignment = 1; 73 size_t bytesPerRow = cairo_image_surface_get_stride(imageSurface.get()); 74 size_t bitsPerPixel = 32; 75 unsigned int padding = bytesPerRow - bitsPerPixel / 8 * width; 76 if (padding) { 77 srcUnpackAlignment = padding + 1; 78 while (bytesPerRow % srcUnpackAlignment) 79 ++srcUnpackAlignment; 80 } 81 82 outputVector.resize(width * height * 4); 83 return packPixels(cairo_image_surface_get_data(imageSurface.get()), SourceFormatBGRA8, 84 width, height, srcUnpackAlignment, format, type, alphaOp, outputVector.data()); 85 } 86 87 void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context) 88 { 89 if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context) 90 return; 91 92 cairo_t *cr = context->cr(); 93 context->save(); 94 95 cairo_rectangle(cr, 0, 0, canvasWidth, canvasHeight); 96 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); 97 cairo_paint(cr); 98 99 RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data( 100 const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageWidth, imageHeight, imageWidth * 4)); 101 102 // OpenGL keeps the pixels stored bottom up, so we need to flip the image here. 103 cairo_translate(cr, 0, imageHeight); 104 cairo_scale(cr, 1, -1); 105 106 cairo_set_operator(cr, CAIRO_OPERATOR_OVER); 107 cairo_set_source_surface(cr, imageSurface.get(), 0, 0); 108 cairo_rectangle(cr, 0, 0, canvasWidth, -canvasHeight); 109 110 cairo_fill(cr); 111 context->restore(); 112 } 113 114 void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) 115 { 116 } 117 118 } // namespace WebCore 119 120 #endif // ENABLE(WEBGL) 121