1/* 2 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 4 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 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 "BitmapImage.h" 30 31#include "ImageObserver.h" 32#include "PlatformContextCairo.h" 33#include <cairo.h> 34 35namespace WebCore { 36 37BitmapImage::BitmapImage(PassRefPtr<cairo_surface_t> nativeImage, ImageObserver* observer) 38 : Image(observer) 39 , m_currentFrame(0) 40 , m_frames(0) 41 , m_frameTimer(0) 42 , m_repetitionCount(cAnimationNone) 43 , m_repetitionCountStatus(Unknown) 44 , m_repetitionsComplete(0) 45 , m_decodedSize(0) 46 , m_frameCount(1) 47 , m_isSolidColor(false) 48 , m_checkedForSolidColor(false) 49 , m_animationFinished(true) 50 , m_allDataReceived(true) 51 , m_haveSize(true) 52 , m_sizeAvailable(true) 53 , m_haveFrameCount(true) 54{ 55 int width = cairo_image_surface_get_width(nativeImage.get()); 56 int height = cairo_image_surface_get_height(nativeImage.get()); 57 m_decodedSize = width * height * 4; 58 m_size = IntSize(width, height); 59 60 m_frames.grow(1); 61 m_frames[0].m_hasAlpha = cairo_surface_get_content(nativeImage.get()) != CAIRO_CONTENT_COLOR; 62 m_frames[0].m_frame = nativeImage; 63 m_frames[0].m_haveMetadata = true; 64 checkForSolidColor(); 65} 66 67void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op, BlendMode blendMode) 68{ 69 draw(context, dst, src, styleColorSpace, op, blendMode, DoNotRespectImageOrientation); 70} 71 72void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op, 73 BlendMode blendMode, RespectImageOrientationEnum shouldRespectImageOrientation) 74{ 75 if (!dst.width() || !dst.height() || !src.width() || !src.height()) 76 return; 77 78 startAnimation(); 79 80 RefPtr<cairo_surface_t> surface = frameAtIndex(m_currentFrame); 81 if (!surface) // If it's too early we won't have an image yet. 82 return; 83 84 if (mayFillWithSolidColor()) { 85 fillWithSolidColor(context, dst, solidColor(), styleColorSpace, op); 86 return; 87 } 88 89 context->save(); 90 91 // Set the compositing operation. 92 if (op == CompositeSourceOver && blendMode == BlendModeNormal && !frameHasAlphaAtIndex(m_currentFrame)) 93 context->setCompositeOperation(CompositeCopy); 94 else 95 context->setCompositeOperation(op, blendMode); 96 97#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) 98 IntSize scaledSize(cairo_image_surface_get_width(surface.get()), cairo_image_surface_get_height(surface.get())); 99 FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(src, scaledSize); 100#else 101 FloatRect adjustedSrcRect(src); 102#endif 103 104 ImageOrientation orientation = DefaultImageOrientation; 105 if (shouldRespectImageOrientation == RespectImageOrientation) 106 orientation = frameOrientationAtIndex(m_currentFrame); 107 108 FloatRect dstRect = dst; 109 110 if (orientation != DefaultImageOrientation) { 111 // ImageOrientation expects the origin to be at (0, 0). 112 context->translate(dstRect.x(), dstRect.y()); 113 dstRect.setLocation(FloatPoint()); 114 context->concatCTM(orientation.transformFromDefault(dstRect.size())); 115 if (orientation.usesWidthAsHeight()) { 116 // The destination rectangle will have it's width and height already reversed for the orientation of 117 // the image, as it was needed for page layout, so we need to reverse it back here. 118 dstRect = FloatRect(dstRect.x(), dstRect.y(), dstRect.height(), dstRect.width()); 119 } 120 } 121 122 context->platformContext()->drawSurfaceToContext(surface.get(), dstRect, adjustedSrcRect, context); 123 124 context->restore(); 125 126 if (imageObserver()) 127 imageObserver()->didDraw(this); 128} 129 130void BitmapImage::checkForSolidColor() 131{ 132 m_isSolidColor = false; 133 m_checkedForSolidColor = true; 134 135 if (frameCount() > 1) 136 return; 137 138 RefPtr<cairo_surface_t> surface = frameAtIndex(m_currentFrame); 139 if (!surface) // If it's too early we won't have an image yet. 140 return; 141 142 ASSERT(cairo_surface_get_type(surface.get()) == CAIRO_SURFACE_TYPE_IMAGE); 143 144 int width = cairo_image_surface_get_width(surface.get()); 145 int height = cairo_image_surface_get_height(surface.get()); 146 147 if (width != 1 || height != 1) 148 return; 149 150 unsigned* pixelColor = reinterpret_cast<unsigned*>(cairo_image_surface_get_data(surface.get())); 151 m_solidColor = colorFromPremultipliedARGB(*pixelColor); 152 153 m_isSolidColor = true; 154} 155 156bool FrameData::clear(bool clearMetadata) 157{ 158 if (clearMetadata) 159 m_haveMetadata = false; 160 161 if (m_frame) { 162 m_frame.clear(); 163 return true; 164 } 165 return false; 166} 167 168} // namespace WebCore 169 170