1/* 2 * Copyright (C) 2004, 2005, 2006 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "BitmapImage.h" 28 29#if USE(CG) 30 31#include "FloatConversion.h" 32#include "GraphicsContextCG.h" 33#include "ImageObserver.h" 34#include "SubimageCacheWithTimer.h" 35#include <ApplicationServices/ApplicationServices.h> 36#include <wtf/RetainPtr.h> 37 38#if PLATFORM(MAC) 39#include "WebCoreSystemInterface.h" 40#endif 41 42#if PLATFORM(WIN) 43#include <WebKitSystemInterface/WebKitSystemInterface.h> 44#endif 45 46namespace WebCore { 47 48bool FrameData::clear(bool clearMetadata) 49{ 50 if (clearMetadata) 51 m_haveMetadata = false; 52 53 m_orientation = DefaultImageOrientation; 54 55 if (m_frame) { 56#if CACHE_SUBIMAGES 57 subimageCache().clearImage(m_frame); 58#endif 59 CGImageRelease(m_frame); 60 m_frame = 0; 61 return true; 62 } 63 return false; 64} 65 66BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer) 67 : Image(observer) 68 , m_currentFrame(0) 69 , m_frames(0) 70 , m_frameTimer(0) 71 , m_repetitionCount(cAnimationNone) 72 , m_repetitionCountStatus(Unknown) 73 , m_repetitionsComplete(0) 74 , m_decodedSize(0) 75 , m_decodedPropertiesSize(0) 76 , m_frameCount(1) 77 , m_isSolidColor(false) 78 , m_checkedForSolidColor(false) 79 , m_animationFinished(true) 80 , m_allDataReceived(true) 81 , m_haveSize(true) 82 , m_sizeAvailable(true) 83 , m_haveFrameCount(true) 84{ 85 CGFloat width = CGImageGetWidth(cgImage); 86 CGFloat height = CGImageGetHeight(cgImage); 87 m_decodedSize = width * height * 4; 88 m_size = IntSize(width, height); 89 90 // Since we don't have a decoder, we can't figure out the image orientation. 91 // Set m_sizeRespectingOrientation to be the same as m_size so it's not 0x0. 92 m_sizeRespectingOrientation = IntSize(width, height); 93 94 m_frames.grow(1); 95 m_frames[0].m_frame = cgImage; 96 m_frames[0].m_hasAlpha = true; 97 m_frames[0].m_haveMetadata = true; 98 99 checkForSolidColor(); 100} 101 102// Drawing Routines 103 104void BitmapImage::checkForSolidColor() 105{ 106 m_checkedForSolidColor = true; 107 if (frameCount() > 1) { 108 m_isSolidColor = false; 109 return; 110 } 111 112 CGImageRef image = frameAtIndex(0); 113 114 // Currently we only check for solid color in the important special case of a 1x1 image. 115 if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) { 116 unsigned char pixel[4]; // RGBA 117 RetainPtr<CGContextRef> bmap = adoptCF(CGBitmapContextCreate(pixel, 1, 1, 8, sizeof(pixel), deviceRGBColorSpaceRef(), 118 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big)); 119 if (!bmap) 120 return; 121 GraphicsContext(bmap.get()).setCompositeOperation(CompositeCopy); 122 CGRect dst = { {0, 0}, {1, 1} }; 123 CGContextDrawImage(bmap.get(), dst, image); 124 if (pixel[3] == 0) 125 m_solidColor = Color(0, 0, 0, 0); 126 else 127 m_solidColor = Color(pixel[0] * 255 / pixel[3], pixel[1] * 255 / pixel[3], pixel[2] * 255 / pixel[3], pixel[3]); 128 m_isSolidColor = true; 129 } 130} 131 132CGImageRef BitmapImage::getCGImageRef() 133{ 134 return frameAtIndex(0); 135} 136 137CGImageRef BitmapImage::getFirstCGImageRefOfSize(const IntSize& size) 138{ 139 size_t count = frameCount(); 140 for (size_t i = 0; i < count; ++i) { 141 CGImageRef cgImage = frameAtIndex(i); 142 if (cgImage && IntSize(CGImageGetWidth(cgImage), CGImageGetHeight(cgImage)) == size) 143 return cgImage; 144 } 145 146 // Fallback to the default CGImageRef if we can't find the right size 147 return getCGImageRef(); 148} 149 150RetainPtr<CFArrayRef> BitmapImage::getCGImageArray() 151{ 152 size_t count = frameCount(); 153 if (!count) 154 return 0; 155 156 CFMutableArrayRef array = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks); 157 for (size_t i = 0; i < count; ++i) { 158 if (CGImageRef currFrame = frameAtIndex(i)) 159 CFArrayAppendValue(array, currFrame); 160 } 161 return adoptCF(array); 162} 163 164void BitmapImage::draw(GraphicsContext* ctx, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator op, BlendMode blendMode) 165{ 166 draw(ctx, dstRect, srcRect, styleColorSpace, op, blendMode, DoNotRespectImageOrientation); 167} 168 169void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp, BlendMode blendMode, RespectImageOrientationEnum shouldRespectImageOrientation) 170{ 171 startAnimation(); 172 173 CGImageRef image = frameAtIndex(m_currentFrame); 174 if (!image) // If it's too early we won't have an image yet. 175 return; 176 177 if (mayFillWithSolidColor()) { 178 fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, compositeOp); 179 return; 180 } 181 182 FloatSize selfSize = currentFrameSize(); 183 ImageOrientation orientation = DefaultImageOrientation; 184 185 if (shouldRespectImageOrientation == RespectImageOrientation) 186 orientation = frameOrientationAtIndex(m_currentFrame); 187 188 ctxt->drawNativeImage(image, selfSize, styleColorSpace, destRect, srcRect, compositeOp, blendMode, orientation); 189 190 if (imageObserver()) 191 imageObserver()->didDraw(this); 192} 193 194} 195 196#endif // USE(CG) 197