[
  [
    "src.orig/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.cpp", 
    "src/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.cpp", 
    [
      "Index: src/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.cpp", 
      "===================================================================", 
      "--- src.orig/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.cpp", 
      "+++ src/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.cpp", 
      "@@ -30,32 +30,41 @@", 
      "#include \"FloatRect.h\"", 
      "#include \"ImageObserver.h\"", 
      "#include \"IntRect.h\"", 
      "+#include \"MIMETypeRegistry.h\"", 
      "#include \"PlatformString.h\"", 
      "#include \"Timer.h\"", 
      "+#include \"SystemTime.h\"", 
      "#include <wtf/Vector.h>", 
      "-#include \"MIMETypeRegistry.h\"", 
      "", 
      "namespace WebCore {", 
      "", 
      "// Animated images >5MB are considered large enough that we'll only hang on to", 
      "// one frame at a time.", 
      "const unsigned cLargeAnimationCutoff = 5242880;", 
      "+static int frameBytes(const IntSize& frameSize)", 
      "+{", 
      "+    return frameSize.width() * frameSize.height() * 4;", 
      "+}", 
      "", 
      "BitmapImage::BitmapImage(ImageObserver* observer, bool accelerated)", 
      ": Image(observer)", 
      ", m_currentFrame(0)", 
      ", m_frames(0)", 
      ", m_frameTimer(0)", 
      "-    , m_repetitionCount(0)", 
      "+    , m_repetitionCount(cAnimationNone)", 
      "+    , m_repetitionCountStatus(Unknown)", 
      ", m_repetitionsComplete(0)", 
      "+    , m_desiredFrameStartTime(0)", 
      ", m_isSolidColor(false)", 
      "-    , m_animatingImageType(true)", 
      "+    , m_checkedForSolidColor(false)", 
      ", m_animationFinished(false)", 
      ", m_allDataReceived(false)", 
      ", m_haveSize(false)", 
      ", m_sizeAvailable(false)", 
      ", m_decodedSize(0)", 
      "+    , m_haveFrameCount(false)", 
      ", m_accelerated(accelerated)", 
      "+    , m_frameCount(0)", 
      "{", 
      "initPlatformData();", 
      "}", 
      "@@ -99,18 +108,22 @@ void BitmapImage::destroyDecodedData(boo", 
      "}", 
      "}", 
      "", 
      "+", 
      "+void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll)", 
      "+{", 
      "+    // Animated images >5MB are considered large enough that we'll only hang on", 
      "+    // to one frame at a time.", 
      "+    static const unsigned cLargeAnimationCutoff = 5242880;", 
      "+    if (frameCount() * frameBytes(m_size) > cLargeAnimationCutoff)", 
      "+        destroyDecodedData(destroyAll);", 
      "+}", 
      "+", 
      "+", 
      "void BitmapImage::cacheFrame(size_t index)", 
      "{", 
      "size_t numFrames = frameCount();", 
      "ASSERT(m_decodedSize == 0 || numFrames > 1);", 
      "", 
      "-    if (!m_frames.size() && shouldAnimate()) {", 
      "-        // Snag the repetition count.", 
      "-        m_repetitionCount = m_source.repetitionCount();", 
      "-        if (m_repetitionCount == cAnimationNone)", 
      "-            m_animatingImageType = false;", 
      "-    }", 
      "-", 
      "if (m_frames.size() < numFrames)", 
      "m_frames.grow(numFrames);", 
      "", 
      "@@ -118,7 +131,8 @@ void BitmapImage::cacheFrame(size_t inde", 
      "if (numFrames == 1 && m_frames[index].m_frame)", 
      "checkForSolidColor();", 
      "", 
      "-    if (shouldAnimate())", 
      "+    m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index);", 
      "+    if (repetitionCount(false) != cAnimationNone)", 
      "m_frames[index].m_duration = m_source.frameDurationAtIndex(index);", 
      "m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);", 
      "", 
      "@@ -147,6 +161,9 @@ bool BitmapImage::dataChanged(bool allDa", 
      "m_allDataReceived = allDataReceived;", 
      "m_source.setData(m_data.get(), allDataReceived, m_accelerated);", 
      "", 
      "+    // Clear the frame count.", 
      "+    m_haveFrameCount = false;", 
      "+", 
      "// Image properties will not be available until the first frame of the file", 
      "// reaches kCGImageStatusIncomplete.", 
      "return isSizeAvailable();", 
      "@@ -154,7 +171,11 @@ bool BitmapImage::dataChanged(bool allDa", 
      "", 
      "size_t BitmapImage::frameCount()", 
      "{", 
      "-    return m_source.frameCount();", 
      "+    if (!m_haveFrameCount) {", 
      "+        m_haveFrameCount = true;", 
      "+        m_frameCount = m_source.frameCount();", 
      "+    }", 
      "+    return m_frameCount;", 
      "}", 
      "", 
      "bool BitmapImage::isSizeAvailable()", 
      "@@ -178,6 +199,17 @@ NativeImagePtr BitmapImage::frameAtIndex", 
      "return m_frames[index].m_frame;", 
      "}", 
      "", 
      "+bool BitmapImage::frameIsCompleteAtIndex(size_t index)", 
      "+{", 
      "+    if (index >= frameCount())", 
      "+        return true;", 
      "+", 
      "+    if (index >= m_frames.size() || !m_frames[index].m_frame)", 
      "+        cacheFrame(index);", 
      "+", 
      "+    return m_frames[index].m_isComplete;", 
      "+}", 
      "+", 
      "float BitmapImage::frameDurationAtIndex(size_t index)", 
      "{", 
      "if (index >= frameCount())", 
      "@@ -200,22 +232,118 @@ bool BitmapImage::frameHasAlphaAtIndex(s", 
      "return m_frames[index].m_hasAlpha;", 
      "}", 
      "", 
      "+int BitmapImage::repetitionCount(bool imageKnownToBeComplete)", 
      "+{", 
      "+    if ((m_repetitionCountStatus == Unknown) || ((m_repetitionCountStatus == Uncertain) && imageKnownToBeComplete)) {", 
      "+        // Snag the repetition count.  If |imageKnownToBeComplete| is false, the", 
      "+        // repetition count may not be accurate yet for GIFs; in this case the", 
      "+        // decoder will default to cAnimationLoopOnce, and we'll try and read", 
      "+        // the count again once the whole image is decoded.", 
      "+        m_repetitionCount = m_source.repetitionCount();", 
      "+        m_repetitionCountStatus = (imageKnownToBeComplete || m_repetitionCount == cAnimationNone) ? Certain : Uncertain;", 
      "+    }", 
      "+    return m_repetitionCount;", 
      "+}", 
      "+", 
      "bool BitmapImage::shouldAnimate()", 
      "{", 
      "-    return (m_animatingImageType && !m_animationFinished && imageObserver());", 
      "+    return (repetitionCount(false) != cAnimationNone && !m_animationFinished && imageObserver());", 
      "}", 
      "", 
      "-void BitmapImage::startAnimation()", 
      "+void BitmapImage::startAnimation(bool catchUpIfNecessary)", 
      "{", 
      "if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)", 
      "return;", 
      "", 
      "-    // Don't advance the animation until the current frame has completely loaded.", 
      "-    if (!m_source.frameIsCompleteAtIndex(m_currentFrame))", 
      "+    // Determine time for next frame to start.  By ignoring paint and timer lag", 
      "+    // in this calculation, we make the animation appear to run at its desired", 
      "+    // rate regardless of how fast it's being repainted.", 
      "+    const double currentDuration = frameDurationAtIndex(m_currentFrame);", 
      "+    const double time = currentTime();", 
      "+    if (m_desiredFrameStartTime == 0) {", 
      "+        m_desiredFrameStartTime = time + currentDuration;", 
      "+    } else {", 
      "+        m_desiredFrameStartTime += currentDuration;", 
      "+", 
      "+        // When an animated image is more than five minutes out of date, the", 
      "+        // user probably doesn't care about resyncing and we could burn a lot of", 
      "+        // time looping through frames below.  Just reset the timings.", 
      "+        const double cAnimationResyncCutoff = 5 * 60;", 
      "+        if ((time - m_desiredFrameStartTime) > cAnimationResyncCutoff)", 
      "+            m_desiredFrameStartTime = time + currentDuration;", 
      "+    }", 
      "+", 
      "+    // Don't advance the animation to an incomplete frame.", 
      "+    size_t nextFrame = (m_currentFrame + 1) % frameCount();", 
      "+    if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame))", 
      "+        return;", 
      "+", 
      "+    // Don't advance past the last frame if we haven't decoded the whole image", 
      "+    // yet and our repetition count is potentially unset.  The repetition count", 
      "+    // in a GIF can potentially come after all the rest of the image data, so", 
      "+    // wait on it.", 
      "+    if (!m_allDataReceived && repetitionCount(false) == cAnimationLoopOnce && m_currentFrame >= (frameCount() - 1))", 
      "return;", 
      "", 
      "-    m_frameTimer = new Timer<BitmapImage>(this, &BitmapImage::advanceAnimation);", 
      "-    m_frameTimer->startOneShot(frameDurationAtIndex(m_currentFrame));", 
      "+    // The image may load more slowly than it's supposed to animate, so that by", 
      "+    // the time we reach the end of the first repetition, we're well behind.", 
      "+    // Clamp the desired frame start time in this case, so that we don't skip", 
      "+    // frames (or whole iterations) trying to \"catch up\".  This is a tradeoff:", 
      "+    // It guarantees users see the whole animation the second time through and", 
      "+    // don't miss any repetitions, and is closer to what other browsers do; on", 
      "+    // the other hand, it makes animations \"less accurate\" for pages that try to", 
      "+    // sync an image and some other resource (e.g. audio), especially if users", 
      "+    // switch tabs (and thus stop drawing the animation, which will pause it)", 
      "+    // during that initial loop, then switch back later.", 
      "+    if (nextFrame == 0 && m_repetitionsComplete == 0 && m_desiredFrameStartTime < time)", 
      "+      m_desiredFrameStartTime = time;", 
      "+", 
      "+    if (!catchUpIfNecessary || time < m_desiredFrameStartTime) {", 
      "+        // Haven't yet reached time for next frame to start; delay until then.", 
      "+        m_frameTimer = new Timer<BitmapImage>(this, &BitmapImage::advanceAnimation);", 
      "+        m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.));", 
      "+    } else {", 
      "+        // We've already reached or passed the time for the next frame to start.", 
      "+        // See if we've also passed the time for frames after that to start, in", 
      "+        // case we need to skip some frames entirely.  Remember not to advance", 
      "+        // to an incomplete frame.", 
      "+        for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsCompleteAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount()) {", 
      "+            // Should we skip the next frame?", 
      "+            double frameAfterNextStartTime = m_desiredFrameStartTime + frameDurationAtIndex(nextFrame);", 
      "+            if (time < frameAfterNextStartTime)", 
      "+                break;", 
      "+", 
      "+            // Yes; skip over it without notifying our observers.", 
      "+            if (!internalAdvanceAnimation(true))", 
      "+                return;", 
      "+            m_desiredFrameStartTime = frameAfterNextStartTime;", 
      "+            nextFrame = frameAfterNext;", 
      "+        }", 
      "+", 
      "+        // Draw the next frame immediately.  Note that m_desiredFrameStartTime", 
      "+        // may be in the past, meaning the next time through this function we'll", 
      "+        // kick off the next advancement sooner than this frame's duration would", 
      "+        // suggest.", 
      "+        if (internalAdvanceAnimation(false)) {", 
      "+            // The image region has been marked dirty, but once we return to our", 
      "+            // caller, draw() will clear it, and nothing will cause the", 
      "+            // animation to advance again.  We need to start the timer for the", 
      "+            // next frame running, or the animation can hang.  (Compare this", 
      "+            // with when advanceAnimation() is called, and the region is dirtied", 
      "+            // while draw() is not in the callstack, meaning draw() gets called", 
      "+            // to update the region and thus startAnimation() is reached again.)", 
      "+            // NOTE: For large images with slow or heavily-loaded systems,", 
      "+            // throwing away data as we go (see destroyDecodedData()) means we", 
      "+            // can spend so much time re-decoding data above that by the time we", 
      "+            // reach here we're behind again.  If we let startAnimation() run", 
      "+            // the catch-up code again, we can get long delays without painting", 
      "+            // as we race the timer, or even infinite recursion.  In this", 
      "+            // situation the best we can do is to simply change frames as fast", 
      "+            // as possible, so force startAnimation() to set a zero-delay timer", 
      "+            // and bail out if we're not caught up.", 
      "+            startAnimation(false);", 
      "+        }", 
      "+    }", 
      "}", 
      "", 
      "void BitmapImage::stopAnimation()", 
      "@@ -231,53 +359,57 @@ void BitmapImage::resetAnimation()", 
      "stopAnimation();", 
      "m_currentFrame = 0;", 
      "m_repetitionsComplete = 0;", 
      "+    m_desiredFrameStartTime = 0;", 
      "m_animationFinished = false;", 
      "-    int frameSize = m_size.width() * m_size.height() * 4;", 
      "", 
      "// For extremely large animations, when the animation is reset, we just throw everything away.", 
      "-    if (frameCount() * frameSize > cLargeAnimationCutoff)", 
      "-        destroyDecodedData();", 
      "+    destroyDecodedDataIfNecessary(true);", 
      "+}", 
      "+", 
      "+void BitmapImage::advanceAnimation(Timer<BitmapImage>*)", 
      "+{", 
      "+    internalAdvanceAnimation(false);", 
      "+    // At this point the image region has been marked dirty, and if it's", 
      "+    // onscreen, we'll soon make a call to draw(), which will call", 
      "+    // startAnimation() again to keep the animation moving.", 
      "}", 
      "", 
      "-void BitmapImage::advanceAnimation(Timer<BitmapImage>* timer)", 
      "+bool BitmapImage::internalAdvanceAnimation(bool skippingFrames)", 
      "{", 
      "// Stop the animation.", 
      "stopAnimation();", 
      "", 
      "// See if anyone is still paying attention to this animation.  If not, we don't", 
      "// advance and will remain suspended at the current frame until the animation is resumed.", 
      "-    if (imageObserver()->shouldPauseAnimation(this))", 
      "-        return;", 
      "+    if (!skippingFrames && imageObserver()->shouldPauseAnimation(this))", 
      "+        return false;", 
      "", 
      "-    m_currentFrame++;", 
      "+    ++m_currentFrame;", 
      "+    bool advancedAnimation = true;", 
      "+    bool destroyAll = false;", 
      "if (m_currentFrame >= frameCount()) {", 
      "-        m_repetitionsComplete += 1;", 
      "-        if (m_repetitionCount && m_repetitionsComplete >= m_repetitionCount) {", 
      "+        ++m_repetitionsComplete;", 
      "+", 
      "+        // Get the repetition count again.  If we weren't able to get a", 
      "+        // repetition count before, we should have decoded the whole image by", 
      "+        // now, so it should now be available.", 
      "+        if (repetitionCount(true) && m_repetitionsComplete >= m_repetitionCount) {", 
      "m_animationFinished = true;", 
      "-            m_currentFrame--;", 
      "-            return;", 
      "+            m_desiredFrameStartTime = 0;", 
      "+            --m_currentFrame;", 
      "+            advancedAnimation = false;", 
      "+        } else {", 
      "+            m_currentFrame = 0;", 
      "+            destroyAll = true;", 
      "}", 
      "-        m_currentFrame = 0;", 
      "}", 
      "+    destroyDecodedDataIfNecessary(destroyAll);", 
      "", 
      "-    // Notify our observer that the animation has advanced.", 
      "-    imageObserver()->animationAdvanced(this);", 
      "-", 
      "-    // For large animated images, go ahead and throw away frames as we go to save", 
      "-    // footprint.", 
      "-    int frameSize = m_size.width() * m_size.height() * 4;", 
      "-    if (frameCount() * frameSize > cLargeAnimationCutoff) {", 
      "-        // Destroy all of our frames and just redecode every time.", 
      "-        destroyDecodedData();", 
      "-", 
      "-        // Go ahead and decode the next frame.", 
      "-        frameAtIndex(m_currentFrame);", 
      "-    }", 
      "-", 
      "-    // We do not advance the animation explicitly.  We rely on a subsequent draw of the image", 
      "-    // to force a request for the next frame via startAnimation().  This allows images that move offscreen while", 
      "-    // scrolling to stop animating (thus saving memory from additional decoded frames and", 
      "-    // CPU time spent doing the decoding).", 
      "+    // We need to draw this frame if we advanced to it while not skipping, or if", 
      "+    // while trying to skip frames we hit the last frame and thus had to stop.", 
      "+    if (skippingFrames != advancedAnimation)", 
      "+        imageObserver()->animationAdvanced(this);", 
      "+    return advancedAnimation;", 
      "}", 
      "", 
      "}"
    ]
  ], 
  [
    "src.orig/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.h", 
    "src/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.h", 
    [
      "Index: src/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.h", 
      "===================================================================", 
      "--- src.orig/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.h", 
      "+++ src/3rdParty/webkit/work/WebCore/platform/graphics/BitmapImage.h", 
      "@@ -66,6 +66,7 @@ template <typename T> class Timer;", 
      "struct FrameData : Noncopyable {", 
      "FrameData()", 
      ": m_frame(0)", 
      "+        , m_isComplete(false)", 
      ", m_duration(0)", 
      ", m_hasAlpha(true)", 
      "{", 
      "@@ -79,6 +80,7 @@ struct FrameData : Noncopyable {", 
      "void clear();", 
      "", 
      "NativeImagePtr m_frame;", 
      "+    bool m_isComplete;", 
      "float m_duration;", 
      "bool m_hasAlpha;", 
      "};", 
      "@@ -96,6 +98,10 @@ public:", 
      "BitmapImage(ImageObserver* = 0, bool accelerated = false);", 
      "~BitmapImage();", 
      "", 
      "+    virtual bool isBitmapImage() const { return true; }", 
      "+", 
      "+    virtual bool hasSingleSecurityOrigin() const { return true; }", 
      "+", 
      "virtual IntSize size() const;", 
      "virtual bool isAccelerated() const { return m_accelerated; }", 
      "", 
      "@@ -130,7 +136,14 @@ public:", 
      "", 
      "virtual NativeImagePtr nativeImageForCurrentFrame() { return frameAtIndex(currentFrame()); }", 
      "", 
      "-private:", 
      "+protected:", 
      "+    enum RepetitionCountStatus {", 
      "+      Unknown,    // We haven't checked the source's repetition count.", 
      "+      Uncertain,  // We have a repetition count, but it might be wrong (some GIFs have a count after the image data, and will report \"loop once\" until all data has been decoded).", 
      "+      Certain,    // The repetition count is known to be correct.", 
      "+    };", 
      "+", 
      "+//private:", 
      "#if PLATFORM(WIN)", 
      "virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator);", 
      "#endif", 
      "@@ -142,6 +155,7 @@ private:", 
      "size_t currentFrame() const { return m_currentFrame; }", 
      "size_t frameCount();", 
      "NativeImagePtr frameAtIndex(size_t);", 
      "+    bool frameIsCompleteAtIndex(size_t);", 
      "float frameDurationAtIndex(size_t);", 
      "bool frameHasAlphaAtIndex(size_t);", 
      "", 
      "@@ -151,23 +165,43 @@ private:", 
      "// Called to invalidate all our cached data.  If an image is loading incrementally, we only", 
      "// invalidate the last cached frame.", 
      "virtual void destroyDecodedData(bool incremental = false);", 
      "+    // If the image is large enough, calls destroyDecodedData() and passes", 
      "+    // |destroyAll| along.", 
      "+    void destroyDecodedDataIfNecessary(bool destroyAll);", 
      "", 
      "// Whether or not size is available yet.", 
      "bool isSizeAvailable();", 
      "", 
      "// Animation.", 
      "+    int repetitionCount(bool imageKnownToBeComplete);  // |imageKnownToBeComplete| should be set if the caller knows the entire image has been decoded.", 
      "bool shouldAnimate();", 
      "-    virtual void startAnimation();", 
      "+    virtual void startAnimation(bool catchUpIfNecessary = true);", 
      "void advanceAnimation(Timer<BitmapImage>*);", 
      "-", 
      "+", 
      "+    // Function that does the real work of advancing the animation.  When", 
      "+    // skippingFrames is true, we're in the middle of a loop trying to skip over", 
      "+    // a bunch of animation frames, so we should not do things like decode each", 
      "+    // one or notify our observers.", 
      "+    // Returns whether the animation was advanced.", 
      "+    bool internalAdvanceAnimation(bool skippingFrames);", 
      "+", 
      "// Handle platform-specific data", 
      "void initPlatformData();", 
      "void invalidatePlatformData();", 
      "", 
      "// Checks to see if the image is a 1x1 solid color.  We optimize these images and just do a fill rect instead.", 
      "+    // This check should happen regardless whether m_checkedForSolidColor is already set, as the frame may have", 
      "+    // changed.", 
      "void checkForSolidColor();", 
      "", 
      "-    virtual bool mayFillWithSolidColor() const { return m_isSolidColor && m_currentFrame == 0; }", 
      "+    virtual bool mayFillWithSolidColor()", 
      "+    {", 
      "+        if (!m_checkedForSolidColor && frameCount() > 0) {", 
      "+            checkForSolidColor();", 
      "+            ASSERT(m_checkedForSolidColor);", 
      "+        }", 
      "+        return m_isSolidColor && m_currentFrame == 0;", 
      "+    }", 
      "virtual Color solidColor() const { return m_solidColor; }", 
      "", 
      "ImageSource m_source;", 
      "@@ -177,8 +211,10 @@ private:", 
      "Vector<FrameData> m_frames; // An array of the cached frames of the animation. We have to ref frames to pin them in the cache.", 
      "", 
      "Timer<BitmapImage>* m_frameTimer;", 
      "-    int m_repetitionCount; // How many total animation loops we should do.", 
      "+    int m_repetitionCount; // How many total animation loops we should do.  This will be cAnimationNone if this image type is incapable of animation.", 
      "+    RepetitionCountStatus m_repetitionCountStatus;", 
      "int m_repetitionsComplete;  // How many repetitions we've finished.", 
      "+    double m_desiredFrameStartTime;  // The system time at which we hope to see the next call to startAnimation().", 
      "", 
      "#if PLATFORM(MAC)", 
      "mutable RetainPtr<NSImage> m_nsImage; // A cached NSImage of frame 0. Only built lazily if someone actually queries for one.", 
      "@@ -187,8 +223,8 @@ private:", 
      "", 
      "Color m_solidColor;  // If we're a 1x1 solid color, this is the color to use to fill.", 
      "bool m_isSolidColor;  // Whether or not we are a 1x1 solid image.", 
      "+    bool m_checkedForSolidColor; // Whether we've checked the frame for solid color.", 
      "", 
      "-    bool m_animatingImageType;  // Whether or not we're an image type that is capable of animating (GIF).", 
      "bool m_animationFinished;  // Whether or not we've completed the entire animation.", 
      "", 
      "bool m_allDataReceived;  // Whether or not we've received all our data.", 
      "@@ -202,6 +238,8 @@ private:", 
      "QPixmap *m_pixmap;", 
      "#endif", 
      "", 
      "+    mutable bool m_haveFrameCount;", 
      "+    size_t m_frameCount;", 
      "};", 
      "", 
      "}"
    ]
  ], 
  [
    "src.orig/3rdParty/webkit/work/WebCore/platform/graphics/Image.h", 
    "src/3rdParty/webkit/work/WebCore/platform/graphics/Image.h", 
    [
      "Index: src/3rdParty/webkit/work/WebCore/platform/graphics/Image.h", 
      "===================================================================", 
      "--- src.orig/3rdParty/webkit/work/WebCore/platform/graphics/Image.h", 
      "+++ src/3rdParty/webkit/work/WebCore/platform/graphics/Image.h", 
      "@@ -102,9 +102,9 @@ public:", 
      "", 
      "SharedBuffer* data() { return m_data.get(); }", 
      "", 
      "-    // It may look unusual that there is no start animation call as public API.  This is because", 
      "-    // we start and stop animating lazily.  Animation begins whenever someone draws the image.  It will", 
      "-    // automatically pause once all observers no longer want to render the image anywhere.", 
      "+    // Animation begins whenever someone draws the image, so startAnimation() is not normally called.", 
      "+    // It will automatically pause once all observers no longer want to render the image anywhere.", 
      "+    virtual void startAnimation(bool /*catchUpIfNecessary*/ = true) { }", 
      "virtual void stopAnimation() {}", 
      "virtual void resetAnimation() {}", 
      "", 
      "@@ -137,7 +137,7 @@ public:", 
      "protected:", 
      "static void fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op);", 
      "", 
      "-private:", 
      "+//private:", 
      "#if PLATFORM(WIN)", 
      "virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator) { }", 
      "#endif", 
      "@@ -149,8 +149,6 @@ private:", 
      "virtual bool mayFillWithSolidColor() const { return false; }", 
      "virtual Color solidColor() const { return Color(); }", 
      "", 
      "-    virtual void startAnimation() { }", 
      "-", 
      "virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,", 
      "const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);", 
      "#if PLATFORM(CG)"
    ]
  ], 
  [
    "src.orig/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp", 
    "src/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp", 
    [
      "Index: src/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp", 
      "===================================================================", 
      "--- src.orig/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp", 
      "+++ src/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp", 
      "@@ -150,11 +150,25 @@ int GIFImageDecoder::frameCount()", 
      "// The number of repetitions to perform for an animation loop.", 
      "int GIFImageDecoder::repetitionCount() const", 
      "{", 
      "-    // We don't have to do any decoding to determine this, since the loop count was determined after", 
      "-    // the initial query for size.", 
      "-    if (m_reader)", 
      "-        return m_reader->repetitionCount();", 
      "-    return cAnimationNone;", 
      "+    // This value can arrive at any point in the image data stream.  Most GIFs", 
      "+    // in the wild declare it near the beginning of the file, so it usually is", 
      "+    // set by the time we've decoded the size, but (depending on the GIF and the", 
      "+    // packets sent back by the webserver) not always.  Our caller is", 
      "+    // responsible for waiting until image decoding has finished to ask this if", 
      "+    // it needs an authoritative answer.  In the meantime, we should default to", 
      "+    // \"loop once\".", 
      "+    if (m_reader) {", 
      "+        // Added wrinkle: ImageSource::clear() may destroy the reader, making", 
      "+        // the result from the reader _less_ authoritative on future calls.  To", 
      "+        // detect this, the reader returns cLoopCountNotSeen (-2) instead of", 
      "+        // cAnimationLoopOnce (-1) when its current incarnation hasn't actually", 
      "+        // seen a loop count yet; in this case we return our previously-cached", 
      "+        // value.", 
      "+        const int repetitionCount = m_reader->repetitionCount();", 
      "+        if (repetitionCount != cLoopCountNotSeen)", 
      "+            m_repetitionCount = repetitionCount;", 
      "+    }", 
      "+    return m_repetitionCount;", 
      "}", 
      "", 
      "RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index)", 
      "@@ -400,6 +414,8 @@ void GIFImageDecoder::frameComplete(unsi", 
      "", 
      "void GIFImageDecoder::gifComplete()", 
      "{", 
      "+    if (m_reader)", 
      "+        m_repetitionCount = m_reader->repetitionCount();", 
      "delete m_reader;", 
      "m_reader = 0;", 
      "}"
    ]
  ], 
  [
    "src.orig/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageReader.h", 
    "src/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageReader.h", 
    [
      "Index: src/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageReader.h", 
      "===================================================================", 
      "--- src.orig/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageReader.h", 
      "+++ src/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageReader.h", 
      "@@ -47,6 +47,8 @@", 
      "#define MAX_COLORS           256", 
      "#define MAX_HOLD_SIZE        256", 
      "", 
      "+const int cLoopCountNotSeen = -2;", 
      "+", 
      "/* gif2.h", 
      "The interface for the GIF87/89a decoder.", 
      "*/", 
      "@@ -187,7 +189,7 @@ struct GIFImageReader {", 
      "screen_bgcolor = version = 0;", 
      "screen_width = screen_height = 0;", 
      "global_colormap_size = images_decoded = images_count = 0;", 
      "-        loop_count = -1;", 
      "+        loop_count = cLoopCountNotSeen;", 
      "count = 0;", 
      "}", 
      ""
    ]
  ], 
  [
    "src.orig/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.h", 
    "src/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.h", 
    [
      "Index: src/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.h", 
      "===================================================================", 
      "--- src.orig/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.h", 
      "+++ src/3rdParty/webkit/work/WebCore/platform/image-decoders/gif/GIFImageDecoder.h", 
      "@@ -79,6 +79,7 @@ private:", 
      "", 
      "bool m_frameCountValid;", 
      "bool m_currentBufferSawAlpha;", 
      "+    mutable int m_repetitionCount;", 
      "mutable GIFImageDecoderPrivate* m_reader;", 
      "};", 
      ""
    ]
  ]
]