15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 2591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * Copyright (c) 2008, Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 4591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 7591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * modification, are permitted provided that the following conditions are 8591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * met: 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 10591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * * Redistributions of source code must retain the above copyright 11591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * notice, this list of conditions and the following disclaimer. 12591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * * Redistributions in binary form must reproduce the above 13591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * copyright notice, this list of conditions and the following disclaimer 14591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * in the documentation and/or other materials provided with the 15591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * distribution. 16591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * * Neither the name of Google Inc. nor the names of its 17591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * contributors may be used to endorse or promote products derived from 18591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * this software without specific prior written permission. 19591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * 20591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 34a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/ImageBuffer.h" 35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 3651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/MIMETypeRegistry.h" 371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/IntRect.h" 38a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/BitmapImage.h" 39a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/Extensions3D.h" 40a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h" 41a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext3D.h" 42a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/UnacceleratedImageBufferSurface.h" 43a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/gpu/DrawingBuffer.h" 44a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/gpu/SharedGraphicsContext3D.h" 45a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/skia/NativeImageSkia.h" 46a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/skia/SkiaUtils.h" 47a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/image-encoders/skia/JPEGImageEncoder.h" 48a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/image-encoders/skia/PNGImageEncoder.h" 49a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/image-encoders/skia/WEBPImageEncoder.h" 50591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "public/platform/Platform.h" 51c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)#include "third_party/skia/include/effects/SkTableColorFilter.h" 52591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/MathExtras.h" 53591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/text/Base64.h" 54591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/text/WTFString.h" 55591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 56591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochusing namespace std; 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 60a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)PassOwnPtr<ImageBuffer> ImageBuffer::create(PassOwnPtr<ImageBufferSurface> surface) 61591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 62a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (!surface->isValid()) 63591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return nullptr; 64a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return adoptPtr(new ImageBuffer(surface)); 65591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 66591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 67a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opacityMode) 6851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){ 69a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) OwnPtr<ImageBufferSurface> surface = adoptPtr(new UnacceleratedImageBufferSurface(size, opacityMode)); 70a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (!surface->isValid()) 7151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return nullptr; 72a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return adoptPtr(new ImageBuffer(surface.release())); 73591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 74591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 75a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface) 76a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) : m_surface(surface) 77591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 78a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (m_surface->canvas()) { 79a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_context = adoptPtr(new GraphicsContext(m_surface->canvas())); 80a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_context->setCertainlyOpaque(m_surface->opacityMode() == Opaque); 81a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_context->setAccelerated(m_surface->isAccelerated()); 8251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) } 83591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 84591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 85591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochImageBuffer::~ImageBuffer() 86591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 87591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 88591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 89591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochGraphicsContext* ImageBuffer::context() const 90591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 91a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_surface->willUse(); 925aec9d262fb41a60afe1effb4cfcddf611b725e0Torne (Richard Coles) ASSERT(m_context.get()); 93591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return m_context.get(); 94591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 95591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 965aec9d262fb41a60afe1effb4cfcddf611b725e0Torne (Richard Coles)const SkBitmap& ImageBuffer::bitmap() const 975aec9d262fb41a60afe1effb4cfcddf611b725e0Torne (Richard Coles){ 985aec9d262fb41a60afe1effb4cfcddf611b725e0Torne (Richard Coles) m_surface->willUse(); 995aec9d262fb41a60afe1effb4cfcddf611b725e0Torne (Richard Coles) return m_surface->bitmap(); 1005aec9d262fb41a60afe1effb4cfcddf611b725e0Torne (Richard Coles)} 101fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch 102fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochbool ImageBuffer::isValid() const 103fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch{ 104a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return m_surface->isValid(); 105fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch} 106fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch 107591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap) 108591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 109591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkBitmap tmp; 110591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!bitmap.deepCopyTo(&tmp, bitmap.config())) 111591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch bitmap.copyTo(&tmp, bitmap.config()); 112591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 113591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return tmp; 114591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 115591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 116591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochPassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior) const 117591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 118fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch if (!isValid()) 119fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch return BitmapImage::create(NativeImageSkia::create()); 120fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch 121a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) const SkBitmap& bitmap = m_surface->bitmap(); 122a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyBackingStore ? deepSkBitmapCopy(bitmap) : bitmap)); 123591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 124591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 125591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochBackingStoreCopy ImageBuffer::fastCopyImageMode() 126591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 127591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return DontCopyBackingStore; 128591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 129591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 13051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)blink::WebLayer* ImageBuffer::platformLayer() const 131591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 132a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return m_surface->layer(); 133591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 134591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 135591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochbool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DObject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool premultiplyAlpha, bool flipY) 136591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 137a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (!m_surface->isAccelerated() || !platformLayer() || !isValid()) 138591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return false; 139591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 140591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!context.makeContextCurrent()) 141591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return false; 142591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 14306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) Extensions3D* extensions = context.extensions(); 144591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->supports("GL_CHROMIUM_flipy") 145591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, level)) 146591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return false; 147591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 148591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // The canvas is stored in a premultiplied format, so unpremultiply if necessary. 149591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, !premultiplyAlpha); 150591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 151591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // The canvas is stored in an inverted position, so the flip semantics are reversed. 152591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, !flipY); 153e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles) extensions->copyTextureCHROMIUM(GL_TEXTURE_2D, getBackingTexture(), texture, level, internalFormat, destType); 154591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 155591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, false); 156591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false); 157591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch context.flush(); 158591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return true; 159591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 160591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 161591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic bool drawNeedsCopy(GraphicsContext* src, GraphicsContext* dst) 162591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 163a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ASSERT(dst); 164591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return (src == dst); 165591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 166591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 16751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)Platform3DObject ImageBuffer::getBackingTexture() 16851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){ 169a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return m_surface->getBackingTexture(); 17051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)} 17151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 17251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)bool ImageBuffer::copyRenderingResultsFromDrawingBuffer(DrawingBuffer* drawingBuffer) 17351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){ 17451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (!drawingBuffer) 17551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return false; 17651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get(); 177a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) Platform3DObject tex = m_surface->getBackingTexture(); 17851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (!context3D || !tex) 17951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return false; 18051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 181e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles) return drawingBuffer->copyToPlatformTexture(*(context3D.get()), tex, GL_RGBA, 182e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles) GL_UNSIGNED_BYTE, 0, true, false); 18351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)} 18451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 185591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, const FloatRect& srcRect, 186a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) CompositeOperator op, blink::WebBlendMode blendMode, bool useLowQualityScale) 187591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 188fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch if (!isValid()) 189fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch return; 190fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch 191a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) const SkBitmap& bitmap = m_surface->bitmap(); 192591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsCopy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); 193591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch context->drawImage(image.get(), destRect, srcRect, op, blendMode, DoNotRespectImageOrientation, useLowQualityScale); 194591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 195591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 196a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void ImageBuffer::flush() 197a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){ 198a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (m_surface->canvas()) { 199a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_surface->canvas()->flush(); 200a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) } 201a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)} 202a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 203591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const FloatSize& scale, 204a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, blink::WebBlendMode blendMode, const IntSize& repeatSpacing) 205591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 206fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch if (!isValid()) 207fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch return; 208fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch 209a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) const SkBitmap& bitmap = m_surface->bitmap(); 210591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsCopy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); 2111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) image->drawPattern(context, srcRect, scale, phase, op, destRect, blendMode, repeatSpacing); 212591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 213591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 214c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)static const Vector<uint8_t>& getLinearRgbLUT() 215c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles){ 216c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) DEFINE_STATIC_LOCAL(Vector<uint8_t>, linearRgbLUT, ()); 217c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) if (linearRgbLUT.isEmpty()) { 218c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) linearRgbLUT.reserveCapacity(256); 219c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) for (unsigned i = 0; i < 256; i++) { 220c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) float color = i / 255.0f; 221c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) color = (color <= 0.04045f ? color / 12.92f : pow((color + 0.055f) / 1.055f, 2.4f)); 222c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) color = std::max(0.0f, color); 223c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) color = std::min(1.0f, color); 224c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) linearRgbLUT.append(static_cast<uint8_t>(round(color * 255))); 225c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) } 226c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) } 227c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) return linearRgbLUT; 228c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)} 229c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) 230c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)static const Vector<uint8_t>& getDeviceRgbLUT() 231c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles){ 232c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) DEFINE_STATIC_LOCAL(Vector<uint8_t>, deviceRgbLUT, ()); 233c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) if (deviceRgbLUT.isEmpty()) { 234c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) deviceRgbLUT.reserveCapacity(256); 235c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) for (unsigned i = 0; i < 256; i++) { 236c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) float color = i / 255.0f; 237c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) color = (powf(color, 1.0f / 2.4f) * 1.055f) - 0.055f; 238c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) color = std::max(0.0f, color); 239c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) color = std::min(1.0f, color); 240c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) deviceRgbLUT.append(static_cast<uint8_t>(round(color * 255))); 241c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) } 242c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) } 243c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) return deviceRgbLUT; 244c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)} 245c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) 246591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace) 247591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 248591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (srcColorSpace == dstColorSpace) 249591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return; 250591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 251591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // only sRGB <-> linearRGB are supported at the moment 252591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if ((srcColorSpace != ColorSpaceLinearRGB && srcColorSpace != ColorSpaceDeviceRGB) 253591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch || (dstColorSpace != ColorSpaceLinearRGB && dstColorSpace != ColorSpaceDeviceRGB)) 254591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return; 255591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 256591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // FIXME: Disable color space conversions on accelerated canvases (for now). 257fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch if (context()->isAccelerated() || !isValid()) 258591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return; 259591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 260a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) const SkBitmap& bitmap = m_surface->bitmap(); 261591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (bitmap.isNull()) 262591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return; 263591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 264591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch const Vector<uint8_t>& lookUpTable = dstColorSpace == ColorSpaceLinearRGB ? 265591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch getLinearRgbLUT() : getDeviceRgbLUT(); 266591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 267591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); 268a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) IntSize size = m_surface->size(); 269591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkAutoLockPixels bitmapLock(bitmap); 270a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) for (int y = 0; y < size.height(); ++y) { 271591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch uint32_t* srcRow = bitmap.getAddr32(0, y); 272a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) for (int x = 0; x < size.width(); ++x) { 273591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkColor color = SkPMColorToColor(srcRow[x]); 274591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch srcRow[x] = SkPreMultiplyARGB( 275591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkColorGetA(color), 276591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch lookUpTable[SkColorGetR(color)], 277591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch lookUpTable[SkColorGetG(color)], 278591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch lookUpTable[SkColorGetB(color)]); 279591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 280591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 281591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 282591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 283c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)PassRefPtr<SkColorFilter> ImageBuffer::createColorSpaceFilter(ColorSpace srcColorSpace, 284c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) ColorSpace dstColorSpace) 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 286c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) if ((srcColorSpace == dstColorSpace) 287c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) || (srcColorSpace != ColorSpaceLinearRGB && srcColorSpace != ColorSpaceDeviceRGB) 288c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) || (dstColorSpace != ColorSpaceLinearRGB && dstColorSpace != ColorSpaceDeviceRGB)) 289c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) return 0; 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 291c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) const uint8_t* lut = 0; 292c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) if (dstColorSpace == ColorSpaceLinearRGB) 293c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) lut = &getLinearRgbLUT()[0]; 294c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) else if (dstColorSpace == ColorSpaceDeviceRGB) 295c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) lut = &getDeviceRgbLUT()[0]; 296c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) else 297c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) return 0; 2985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 299c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) return adoptRef(SkTableColorFilter::CreateARGB(0, lut, lut, lut)); 300c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)} 301591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 302591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochtemplate <Multiply multiplied> 303591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochPassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, GraphicsContext* context, const IntSize& size) 3045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 305591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch float area = 4.0f * rect.width() * rect.height(); 306591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (area > static_cast<float>(std::numeric_limits<int>::max())) 307591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return 0; 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 309591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4); 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 311591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch unsigned char* data = result->data(); 312591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 313591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (rect.x() < 0 314591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch || rect.y() < 0 315591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch || rect.maxX() > size.width() 316591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch || rect.maxY() > size.height()) 317591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch result->zeroFill(); 318591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 319591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch unsigned destBytesPerRow = 4 * rect.width(); 320591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkBitmap destBitmap; 321591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch destBitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height(), destBytesPerRow); 322591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch destBitmap.setPixels(data); 323591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 324591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkCanvas::Config8888 config8888; 325591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (multiplied == Premultiplied) 326591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch config8888 = SkCanvas::kRGBA_Premul_Config8888; 327591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch else 328591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch config8888 = SkCanvas::kRGBA_Unpremul_Config8888; 329591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 330591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch context->readPixels(&destBitmap, rect.x(), rect.y(), config8888); 331591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return result.release(); 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 334a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const 335591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 336fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch if (!isValid()) 337fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch return Uint8ClampedArray::create(rect.width() * rect.height() * 4); 338a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return getImageData<Unmultiplied>(rect, context(), m_surface->size()); 339591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 340591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 341a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const 342591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 343fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch if (!isValid()) 344fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch return Uint8ClampedArray::create(rect.width() * rect.height() * 4); 345a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return getImageData<Premultiplied>(rect, context(), m_surface->size()); 346591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 347591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 348a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) 349591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 350fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch if (!isValid()) 351fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch return; 352fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch 353591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(sourceRect.width() > 0); 354591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(sourceRect.height() > 0); 355591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 356591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int originX = sourceRect.x(); 357591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int destX = destPoint.x() + sourceRect.x(); 358591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(destX >= 0); 359a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ASSERT(destX < m_surface->size().width()); 360591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(originX >= 0); 361591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(originX < sourceRect.maxX()); 362591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 363591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int endX = destPoint.x() + sourceRect.maxX(); 364a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ASSERT(endX <= m_surface->size().width()); 365591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 366591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int numColumns = endX - destX; 367591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 368591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int originY = sourceRect.y(); 369591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int destY = destPoint.y() + sourceRect.y(); 370591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(destY >= 0); 371a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ASSERT(destY < m_surface->size().height()); 372591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(originY >= 0); 373591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(originY < sourceRect.maxY()); 374591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 375591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int endY = destPoint.y() + sourceRect.maxY(); 376a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ASSERT(endY <= m_surface->size().height()); 377591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int numRows = endY - destY; 378591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 379591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch unsigned srcBytesPerRow = 4 * sourceSize.width(); 380591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkBitmap srcBitmap; 381591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch srcBitmap.setConfig(SkBitmap::kARGB_8888_Config, numColumns, numRows, srcBytesPerRow); 382591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch srcBitmap.setPixels(source->data() + originY * srcBytesPerRow + originX * 4); 383591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 384591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkCanvas::Config8888 config8888; 385591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (multiplied == Premultiplied) 386591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch config8888 = SkCanvas::kRGBA_Premul_Config8888; 387591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch else 388591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch config8888 = SkCanvas::kRGBA_Unpremul_Config8888; 389591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 390591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch context()->writePixels(srcBitmap, destX, destY, config8888); 391591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 392591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 393591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochtemplate <typename T> 394591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic bool encodeImage(T& source, const String& mimeType, const double* quality, Vector<char>* output) 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 396591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch Vector<unsigned char>* encodedImage = reinterpret_cast<Vector<unsigned char>*>(output); 397591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 398591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (mimeType == "image/jpeg") { 399591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality; 400591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (quality && *quality >= 0.0 && *quality <= 1.0) 401591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch compressionQuality = static_cast<int>(*quality * 100 + 0.5); 402591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!JPEGImageEncoder::encode(source, compressionQuality, encodedImage)) 403591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return false; 404591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } else if (mimeType == "image/webp") { 405591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch int compressionQuality = WEBPImageEncoder::DefaultCompressionQuality; 406591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (quality && *quality >= 0.0 && *quality <= 1.0) 407591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch compressionQuality = static_cast<int>(*quality * 100 + 0.5); 408591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!WEBPImageEncoder::encode(source, compressionQuality, encodedImage)) 409591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return false; 410591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } else { 411591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!PNGImageEncoder::encode(source, encodedImage)) 412591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return false; 413591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(mimeType == "image/png"); 414591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 415591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 416591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return true; 417591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 418591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 419a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const 420591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 421591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); 422591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 423591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch Vector<char> encodedImage; 424a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (!isValid() || !encodeImage(m_surface->bitmap(), mimeType, quality, &encodedImage)) 425591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return "data:,"; 426591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch Vector<char> base64Data; 427591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch base64Encode(encodedImage, base64Data); 428591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 429591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return "data:" + mimeType + ";base64," + base64Data; 430591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 431591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 43251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)String ImageDataToDataURL(const ImageDataBuffer& imageData, const String& mimeType, const double* quality) 433591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 434591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); 435591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 436591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch Vector<char> encodedImage; 437591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!encodeImage(imageData, mimeType, quality, &encodedImage)) 438591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return "data:,"; 439591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 440591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch Vector<char> base64Data; 441591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch base64Encode(encodedImage, base64Data); 442591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 443591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch return "data:" + mimeType + ";base64," + base64Data; 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 446591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} // namespace WebCore 447