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