1/* 2 * Copyright (C) 2007 Apple Computer, Kevin Ollivier. 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 "Image.h" 28 29#include "AffineTransform.h" 30#include "BitmapImage.h" 31#include "FloatConversion.h" 32#include "FloatRect.h" 33#include "GraphicsContext.h" 34#include "ImageObserver.h" 35#include "NotImplemented.h" 36#include "SharedBuffer.h" 37 38#include <math.h> 39#include <stdio.h> 40 41#include <wx/defs.h> 42#include <wx/bitmap.h> 43#include <wx/dc.h> 44#include <wx/dcmemory.h> 45#include <wx/dcgraph.h> 46#include <wx/graphics.h> 47#include <wx/image.h> 48#include <wx/thread.h> 49 50namespace WebCore { 51 52// this is in GraphicsContextWx.cpp 53int getWxCompositingOperation(CompositeOperator op, bool hasAlpha); 54 55bool FrameData::clear(bool clearMetadata) 56{ 57 if (clearMetadata) 58 m_haveMetadata = false; 59 60 if (m_frame) { 61 delete m_frame; 62 m_frame = 0; 63 return true; 64 } 65 return false; 66} 67 68// ================================================ 69// Image Class 70// ================================================ 71 72PassRefPtr<Image> Image::loadPlatformResource(const char *name) 73{ 74 // FIXME: We need to have some 'placeholder' graphics for things like missing 75 // plugins or broken images. 76 Vector<char> arr; 77 RefPtr<Image> img = BitmapImage::create(); 78 RefPtr<SharedBuffer> buffer = SharedBuffer::create(arr.data(), arr.size()); 79 img->setData(buffer, true); 80 return img.release(); 81} 82 83void BitmapImage::initPlatformData() 84{ 85 // FIXME: NYI 86} 87 88// Drawing Routines 89 90void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) 91{ 92 if (!m_source.initialized()) 93 return; 94 95 if (mayFillWithSolidColor()) { 96 fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op); 97 return; 98 } 99 100#if USE(WXGC) 101 wxGCDC* context = (wxGCDC*)ctxt->platformContext(); 102 wxGraphicsContext* gc = context->GetGraphicsContext(); 103 wxGraphicsBitmap* bitmap = frameAtIndex(m_currentFrame); 104#else 105 wxWindowDC* context = ctxt->platformContext(); 106 wxBitmap* bitmap = frameAtIndex(m_currentFrame); 107#endif 108 109 startAnimation(); 110 if (!bitmap) // If it's too early we won't have an image yet. 111 return; 112 113 // If we're drawing a sub portion of the image or scaling then create 114 // a pattern transformation on the image and draw the transformed pattern. 115 // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html 116 // FIXME: NYI 117 118 ctxt->save(); 119 120 // Set the compositing operation. 121 ctxt->setCompositeOperation(op); 122 123#if USE(WXGC) 124 float scaleX = src.width() / dst.width(); 125 float scaleY = src.height() / dst.height(); 126 127 FloatRect adjustedDestRect = dst; 128 FloatSize selfSize = currentFrameSize(); 129 130 if (src.size() != selfSize) { 131 adjustedDestRect.setLocation(FloatPoint(dst.x() - src.x() / scaleX, dst.y() - src.y() / scaleY)); 132 adjustedDestRect.setSize(FloatSize(selfSize.width() / scaleX, selfSize.height() / scaleY)); 133 } 134 135 gc->Clip(dst.x(), dst.y(), dst.width(), dst.height()); 136#if wxCHECK_VERSION(2,9,0) 137 gc->DrawBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height()); 138#else 139 gc->DrawGraphicsBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height()); 140#endif 141 142#else // USE(WXGC) 143 IntRect srcIntRect(src); 144 IntRect dstIntRect(dst); 145 bool rescaling = false; 146 if ((dstIntRect.width() != srcIntRect.width()) || (dstIntRect.height() != srcIntRect.height())) 147 { 148 rescaling = true; 149 wxImage img = bitmap->ConvertToImage(); 150 img.Rescale(dstIntRect.width(), dstIntRect.height()); 151 bitmap = new wxBitmap(img); 152 } 153 154 wxMemoryDC mydc; 155 ASSERT(bitmap->GetRefData()); 156 mydc.SelectObject(*bitmap); 157 158 context->Blit((wxCoord)dstIntRect.x(),(wxCoord)dstIntRect.y(), (wxCoord)dstIntRect.width(), (wxCoord)dstIntRect.height(), &mydc, 159 (wxCoord)srcIntRect.x(), (wxCoord)srcIntRect.y(), wxCOPY, true); 160 mydc.SelectObject(wxNullBitmap); 161 162 // NB: delete is causing crashes during page load, but not during the deletion 163 // itself. It occurs later on when a valid bitmap created in frameAtIndex 164 // suddenly becomes invalid after returning. It's possible these errors deal 165 // with reentrancy and threding problems. 166 //delete bitmap; 167 if (rescaling) 168 { 169 delete bitmap; 170 bitmap = NULL; 171 } 172#endif 173 174 ctxt->restore(); 175 176 if (ImageObserver* observer = imageObserver()) 177 observer->didDraw(this); 178} 179 180void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& dstRect) 181{ 182 183 184#if USE(WXGC) 185 wxGCDC* context = (wxGCDC*)ctxt->platformContext(); 186 wxGraphicsBitmap* bitmap = nativeImageForCurrentFrame(); 187#else 188 wxWindowDC* context = ctxt->platformContext(); 189 wxBitmap* bitmap = nativeImageForCurrentFrame(); 190#endif 191 192 if (!bitmap) // If it's too early we won't have an image yet. 193 return; 194 195 ctxt->save(); 196 ctxt->clip(IntRect(dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height())); 197 198 float currentW = 0; 199 float currentH = 0; 200 201#if USE(WXGC) 202 wxGraphicsContext* gc = context->GetGraphicsContext(); 203 204 float adjustedX = phase.x() + srcRect.x() * 205 narrowPrecisionToFloat(patternTransform.a()); 206 float adjustedY = phase.y() + srcRect.y() * 207 narrowPrecisionToFloat(patternTransform.d()); 208 209 gc->ConcatTransform(patternTransform); 210#else 211 wxMemoryDC mydc; 212 mydc.SelectObject(*bitmap); 213#endif 214 215 wxPoint origin(context->GetDeviceOrigin()); 216 wxSize clientSize(context->GetSize()); 217 218 while ( currentW < dstRect.width() && currentW < clientSize.x - origin.x ) { 219 while ( currentH < dstRect.height() && currentH < clientSize.y - origin.y) { 220#if USE(WXGC) 221#if wxCHECK_VERSION(2,9,0) 222 gc->DrawBitmap(*bitmap, adjustedX + currentW, adjustedY + currentH, (wxDouble)srcRect.width(), (wxDouble)srcRect.height()); 223#else 224 gc->DrawGraphicsBitmap(*bitmap, adjustedX + currentW, adjustedY + currentH, (wxDouble)srcRect.width(), (wxDouble)srcRect.height()); 225#endif 226#else 227 context->Blit((wxCoord)dstRect.x() + currentW, (wxCoord)dstRect.y() + currentH, 228 (wxCoord)srcRect.width(), (wxCoord)srcRect.height(), &mydc, 229 (wxCoord)srcRect.x(), (wxCoord)srcRect.y(), wxCOPY, true); 230#endif 231 currentH += srcRect.height(); 232 } 233 currentW += srcRect.width(); 234 currentH = 0; 235 } 236 ctxt->restore(); 237 238#if !USE(WXGC) 239 mydc.SelectObject(wxNullBitmap); 240#endif 241 242 // NB: delete is causing crashes during page load, but not during the deletion 243 // itself. It occurs later on when a valid bitmap created in frameAtIndex 244 // suddenly becomes invalid after returning. It's possible these errors deal 245 // with reentrancy and threding problems. 246 //delete bitmap; 247 248 startAnimation(); 249 250 if (ImageObserver* observer = imageObserver()) 251 observer->didDraw(this); 252} 253 254void BitmapImage::checkForSolidColor() 255{ 256 m_checkedForSolidColor = true; 257} 258 259void BitmapImage::invalidatePlatformData() 260{ 261 262} 263 264} 265