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 50 namespace WebCore { 51 52 // this is in GraphicsContextWx.cpp 53 int getWxCompositingOperation(CompositeOperator op, bool hasAlpha); 54 55 bool 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 72 PassRefPtr<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 83 void BitmapImage::initPlatformData() 84 { 85 // FIXME: NYI 86 } 87 88 // Drawing Routines 89 90 void 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 180 void 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 254 void BitmapImage::checkForSolidColor() 255 { 256 m_checkedForSolidColor = true; 257 } 258 259 void BitmapImage::invalidatePlatformData() 260 { 261 262 } 263 264 } 265