| Differences between
and this patch
- a/Source/WebCore/ChangeLog +56 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2013-04-17  NĂ¡ndor Huszka  <hnandor@inf.u-szeged.hu>
2
3
        Reorganize animation starting
4
        https://bugs.webkit.org/show_bug.cgi?id=112327
5
6
        The patch reorganizes animation starting.
7
        After it we don't need to start them explicitly,
8
        because FrameView will do this automatically.
9
10
        So far starting animation is done by painting.
11
        Now it is done by FrameView instead of image drawing.
12
13
        It is needed to know every animation, so RenderImage
14
        passes itself to FrameView by calling its animateLater method.
15
16
        FrameView resumes only visible animations after painting
17
        (in paintContents) and after scrolling (in wheelEvent)
18
        with resumeAnimationsIfNeeded.
19
20
        Animation stops after it hase became invisible, it is checked
21
        by RenderObject::willRenderImage. By calling FrameView's
22
        shouldRenderAnimation method we get the answer whether it is needed
23
        to render the animation. On the other hand FrameView
24
        saves it if animation isn't visible.
25
        So the animation can be resumed when it becomes visible again.
26
27
        Dead RenderObjects are removed from FrameView's register
28
        with removeSavedAnimation in RenderObject::willBeDestroyed,
29
        and startAnimation isn't handled by BitmapImage already.
30
31
        Reviewed by NOBODY (OOPS!).
32
33
        No new tests (OOPS!).
34
35
        * page/FrameView.cpp:
36
        (WebCore::FrameView::paintContents):
37
        (WebCore):
38
        (WebCore::FrameView::saveStoppedAnimation):
39
        (WebCore::FrameView::animateLater):
40
        (WebCore::FrameView::removeSavedAnimation):
41
        (WebCore::FrameView::resumeAnimatingImagesIfNeeded):
42
        (WebCore::FrameView::shouldRenderAnimation):
43
        (WebCore::FrameView::computeScrolledViewPort):
44
        (WebCore::FrameView::wheelEvent):
45
        * page/FrameView.h:
46
        (FrameView):
47
        * platform/graphics/BitmapImage.cpp:
48
        (WebCore::BitmapImage::startAnimation):
49
        * platform/graphics/cairo/BitmapImageCairo.cpp:
50
        (WebCore::BitmapImage::draw):
51
        * rendering/RenderImage.cpp:
52
        (WebCore::RenderImage::paintIntoRect):
53
        * rendering/RenderObject.cpp:
54
        (WebCore::RenderObject::willBeDestroyed):
55
        (WebCore::RenderObject::willRenderImage):
56
1
2013-04-15  Timothy Hatcher  <timothy@apple.com>
57
2013-04-15  Timothy Hatcher  <timothy@apple.com>
2
58
3
        Web Inspector: Make var and function declarations work again in the Console.
59
        Web Inspector: Make var and function declarations work again in the Console.
- a/Source/WebCore/page/FrameView.cpp -1 / +123 lines
Lines 29-34 a/Source/WebCore/page/FrameView.cpp_sec1
29
29
30
#include "AXObjectCache.h"
30
#include "AXObjectCache.h"
31
#include "BackForwardController.h"
31
#include "BackForwardController.h"
32
#include "BitmapImage.h"
32
#include "CachedImage.h"
33
#include "CachedImage.h"
33
#include "CachedResourceLoader.h"
34
#include "CachedResourceLoader.h"
34
#include "Chrome.h"
35
#include "Chrome.h"
Lines 58-63 a/Source/WebCore/page/FrameView.cpp_sec2
58
#include "RenderEmbeddedObject.h"
59
#include "RenderEmbeddedObject.h"
59
#include "RenderFullScreen.h"
60
#include "RenderFullScreen.h"
60
#include "RenderIFrame.h"
61
#include "RenderIFrame.h"
62
#include "RenderImage.h"
61
#include "RenderLayer.h"
63
#include "RenderLayer.h"
62
#include "RenderLayerBacking.h"
64
#include "RenderLayerBacking.h"
63
#include "RenderPart.h"
65
#include "RenderPart.h"
Lines 3555-3560 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) a/Source/WebCore/page/FrameView.cpp_sec3
3555
3557
3556
    m_isPainting = false;
3558
    m_isPainting = false;
3557
3559
3560
    // resume animations after painting
3561
    resumeAnimatingImagesIfNeeded(rect);
3562
3558
    if (flatteningPaint && isRootFrame)
3563
    if (flatteningPaint && isRootFrame)
3559
        notifyWidgetsInAllFrames(DidPaintFlattened);
3564
        notifyWidgetsInAllFrames(DidPaintFlattened);
3560
3565
Lines 4041-4046 void FrameView::removeChild(Widget* widget) a/Source/WebCore/page/FrameView.cpp_sec4
4041
    ScrollView::removeChild(widget);
4046
    ScrollView::removeChild(widget);
4042
}
4047
}
4043
4048
4049
// place animation in the vector of stopped animations
4050
void FrameView::saveStoppedAnimation(RenderObject* animation)
4051
{
4052
    const size_t index = m_animationsToResume.find(animation);
4053
    ASSERT(index > -1);
4054
    m_animationsToResume.remove(index);
4055
    m_stoppedAnimations.append(animation);
4056
}
4057
4058
// remember animation, it may be saved already
4059
void FrameView::animateLater(RenderObject* animation)
4060
{
4061
    if (m_animationsToResume.contains(animation))
4062
        return;
4063
4064
    if (m_stoppedAnimations.contains(animation))
4065
        return;
4066
4067
    // we didn't deal with it yet
4068
    m_stoppedAnimations.append(animation);
4069
}
4070
4071
void FrameView::removeSavedAnimation(RenderObject* animation)
4072
{
4073
    size_t index = m_animationsToResume.find(animation);
4074
    if (index != WTF::notFound) {
4075
        m_animationsToResume.remove(index);
4076
        return;
4077
    }
4078
4079
    index = m_stoppedAnimations.find(animation);
4080
    if (index != WTF::notFound)
4081
        m_stoppedAnimations.remove(index);
4082
}
4083
4084
void FrameView::resumeAnimatingImagesIfNeeded(const IntRect& area)
4085
{
4086
    RenderObject* stoppedAnimation;
4087
    IntRect stoppedAnimationBoundingBox;
4088
    bool intersectsArea;
4089
4090
    // search for animations that are now stopped but should be resumed
4091
    unsigned lastElementNeedToKeep = 0;
4092
    while (m_stoppedAnimations.size() != lastElementNeedToKeep) {
4093
        stoppedAnimation = m_stoppedAnimations[lastElementNeedToKeep];
4094
        stoppedAnimationBoundingBox = stoppedAnimation->absoluteBoundingBoxRect();
4095
        intersectsArea = stoppedAnimationBoundingBox.intersects(area);
4096
        if (intersectsArea) {
4097
            m_stoppedAnimations.remove(lastElementNeedToKeep);
4098
            m_animationsToResume.append(stoppedAnimation);
4099
        } else {
4100
            // skip actual animation
4101
            lastElementNeedToKeep++;
4102
        }
4103
    }
4104
4105
    RenderObject* animationToResume;
4106
    IntRect animationToResumeBoundingBox;
4107
    unsigned size = m_animationsToResume.size();
4108
    for (unsigned n = 0; n < size; ++n) {
4109
        animationToResume = m_animationsToResume[n];
4110
        animationToResumeBoundingBox = animationToResume->absoluteBoundingBoxRect();
4111
        intersectsArea = animationToResumeBoundingBox.intersects(area);
4112
        // start every animation that should be resumed
4113
        if (intersectsArea) {
4114
            CachedImage* cachedImage = toRenderImage(animationToResume)->cachedImage();
4115
            if (!cachedImage)
4116
                continue;
4117
            if (!cachedImage->hasImage())
4118
                continue;
4119
            Image* image = cachedImage->image();
4120
            if (!image->isBitmapImage())
4121
                continue;
4122
            BitmapImage* bitmapImage = static_cast<BitmapImage*>(image);
4123
            if (!bitmapImage->canAnimate())
4124
                continue;
4125
            image->startAnimation();
4126
        }
4127
    }
4128
}
4129
4130
bool FrameView::shouldRenderAnimation(RenderObject* animation)
4131
{
4132
    bool visible = visibleContentRect().intersects(animation->absoluteBoundingBoxRect());
4133
    if (m_isViewPortScrolled)
4134
        visible = m_scrolledViewPort.intersects(animation->absoluteBoundingBoxRect());
4135
4136
    bool animationShouldResume = m_animationsToResume.find(animation) != WTF::notFound;
4137
    if (visible && animationShouldResume)
4138
        return true;
4139
4140
    // save animation in order to deal with it later
4141
    saveStoppedAnimation(animation);
4142
4143
    return false;
4144
}
4145
4146
IntRect FrameView::computeScrolledViewPort(float deltaX, float deltaY)
4147
{
4148
    IntRect viewPort = visibleContentRect();
4149
    int newX = viewPort.x() - deltaX;
4150
    int newY = viewPort.y() - deltaY;
4151
    IntRect scrolledViewPort(IntPoint(newX, newY), viewPort.size());
4152
4153
    return scrolledViewPort;
4154
}
4155
4044
bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
4156
bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
4045
{
4157
{
4046
    // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views
4158
    // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views
Lines 4052-4060 bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent) a/Source/WebCore/page/FrameView.cpp_sec5
4052
4164
4053
    if (delegatesScrolling()) {
4165
    if (delegatesScrolling()) {
4054
        IntSize offset = scrollOffset();
4166
        IntSize offset = scrollOffset();
4055
        IntSize newOffset = IntSize(offset.width() - wheelEvent.deltaX(), offset.height() - wheelEvent.deltaY());
4167
        float deltaX = wheelEvent.deltaX();
4168
        float deltaY = wheelEvent.deltaY();
4169
        IntSize newOffset = IntSize(offset.width() - deltaX, offset.height() - deltaY);
4056
        if (offset != newOffset) {
4170
        if (offset != newOffset) {
4057
            ScrollView::scrollTo(newOffset);
4171
            ScrollView::scrollTo(newOffset);
4172
4173
            m_isViewPortScrolled = true;
4174
            m_scrolledViewPort = computeScrolledViewPort(deltaX, deltaY);
4175
            const IntRect scrolledViewPort(m_scrolledViewPort.location(), m_scrolledViewPort.size());
4176
            // it is needed to resume animations before scrolling
4177
            resumeAnimatingImagesIfNeeded(scrolledViewPort);
4178
            m_isViewPortScrolled = false;
4179
4058
            scrollPositionChanged();
4180
            scrollPositionChanged();
4059
            frame()->loader()->client()->didChangeScrollOffset();
4181
            frame()->loader()->client()->didChangeScrollOffset();
4060
        }
4182
        }
- a/Source/WebCore/page/FrameView.h +13 lines
Lines 378-383 public: a/Source/WebCore/page/FrameView.h_sec1
378
    // we need this function in order to do the scroll ourselves.
378
    // we need this function in order to do the scroll ourselves.
379
    bool wheelEvent(const PlatformWheelEvent&);
379
    bool wheelEvent(const PlatformWheelEvent&);
380
380
381
    bool shouldRenderAnimation(RenderObject*);
382
    void animateLater(RenderObject*);
383
    void removeSavedAnimation(RenderObject*);
384
381
    void setScrollingPerformanceLoggingEnabled(bool);
385
    void setScrollingPerformanceLoggingEnabled(bool);
382
386
383
    // Page and FrameView both store a Pagination value. Page::pagination() is set only by API,
387
    // Page and FrameView both store a Pagination value. Page::pagination() is set only by API,
Lines 503-508 private: a/Source/WebCore/page/FrameView.h_sec2
503
    void scrollToAnchor();
507
    void scrollToAnchor();
504
    void scrollPositionChanged();
508
    void scrollPositionChanged();
505
509
510
    IntRect computeScrolledViewPort(float, float);
511
    void resumeAnimatingImagesIfNeeded(const IntRect&);
512
    void saveStoppedAnimation(RenderObject*);
513
506
    bool hasCustomScrollbars() const;
514
    bool hasCustomScrollbars() const;
507
515
508
    virtual void updateScrollCorner();
516
    virtual void updateScrollCorner();
Lines 592-597 private: a/Source/WebCore/page/FrameView.h_sec3
592
    PaintBehavior m_paintBehavior;
600
    PaintBehavior m_paintBehavior;
593
    bool m_isPainting;
601
    bool m_isPainting;
594
602
603
    Vector<RenderObject*> m_stoppedAnimations;
604
    Vector<RenderObject*> m_animationsToResume;
605
    IntRect m_scrolledViewPort;
606
    bool m_isViewPortScrolled;
607
595
    unsigned m_visuallyNonEmptyCharacterCount;
608
    unsigned m_visuallyNonEmptyCharacterCount;
596
    unsigned m_visuallyNonEmptyPixelCount;
609
    unsigned m_visuallyNonEmptyPixelCount;
597
    bool m_isVisuallyNonEmpty;
610
    bool m_isVisuallyNonEmpty;
- a/Source/WebCore/platform/graphics/BitmapImage.cpp -19 / +1 lines
Lines 459-483 void BitmapImage::startAnimation(bool catchUpIfNecessary) a/Source/WebCore/platform/graphics/BitmapImage.cpp_sec1
459
        // may be in the past, meaning the next time through this function we'll
459
        // may be in the past, meaning the next time through this function we'll
460
        // kick off the next advancement sooner than this frame's duration would
460
        // kick off the next advancement sooner than this frame's duration would
461
        // suggest.
461
        // suggest.
462
        if (internalAdvanceAnimation(false)) {
462
        internalAdvanceAnimation(false);
463
            // The image region has been marked dirty, but once we return to our
464
            // caller, draw() will clear it, and nothing will cause the
465
            // animation to advance again.  We need to start the timer for the
466
            // next frame running, or the animation can hang.  (Compare this
467
            // with when advanceAnimation() is called, and the region is dirtied
468
            // while draw() is not in the callstack, meaning draw() gets called
469
            // to update the region and thus startAnimation() is reached again.)
470
            // NOTE: For large images with slow or heavily-loaded systems,
471
            // throwing away data as we go (see destroyDecodedData()) means we
472
            // can spend so much time re-decoding data above that by the time we
473
            // reach here we're behind again.  If we let startAnimation() run
474
            // the catch-up code again, we can get long delays without painting
475
            // as we race the timer, or even infinite recursion.  In this
476
            // situation the best we can do is to simply change frames as fast
477
            // as possible, so force startAnimation() to set a zero-delay timer
478
            // and bail out if we're not caught up.
479
            startAnimation(false);
480
        }
481
    }
463
    }
482
}
464
}
483
465
- a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp -1 / +1 lines
Lines 75-81 void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp_sec1
75
    if (!dst.width() || !dst.height() || !src.width() || !src.height())
75
    if (!dst.width() || !dst.height() || !src.width() || !src.height())
76
        return;
76
        return;
77
77
78
    startAnimation();
78
    // we handle animation starting in FrameView
79
79
80
    RefPtr<cairo_surface_t> surface = frameAtIndex(m_currentFrame);
80
    RefPtr<cairo_surface_t> surface = frameAtIndex(m_currentFrame);
81
    if (!surface) // If it's too early we won't have an image yet.
81
    if (!surface) // If it's too early we won't have an image yet.
- a/Source/WebCore/rendering/RenderImage.cpp +2 lines
Lines 476-481 void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect a/Source/WebCore/rendering/RenderImage.cpp_sec1
476
    Image* image = m_imageResource->image().get();
476
    Image* image = m_imageResource->image().get();
477
    bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
477
    bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
478
    context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), style()->colorSpace(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling);
478
    context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), style()->colorSpace(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling);
479
    // register itself in FrameView, because it isn't animated yet
480
    view()->frameView()->animateLater(this);
479
}
481
}
480
482
481
bool RenderImage::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const
483
bool RenderImage::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const
- a/Source/WebCore/rendering/RenderObject.cpp +8 lines
Lines 2416-2421 void RenderObject::willBeDestroyed() a/Source/WebCore/rendering/RenderObject.cpp_sec1
2416
    if (frame() && frame()->eventHandler()->autoscrollRenderer() == this)
2416
    if (frame() && frame()->eventHandler()->autoscrollRenderer() == this)
2417
        frame()->eventHandler()->stopAutoscrollTimer(true);
2417
        frame()->eventHandler()->stopAutoscrollTimer(true);
2418
2418
2419
    // remove dead animations from FrameView
2420
    ASSERT(frame()->view());
2421
    frame()->view()->removeSavedAnimation(this);
2422
2419
    animation()->cancelAnimations(this);
2423
    animation()->cancelAnimations(this);
2420
2424
2421
    // For accessibility management, notify the parent of the imminent change to its child set.
2425
    // For accessibility management, notify the parent of the imminent change to its child set.
Lines 2943-2948 bool RenderObject::willRenderImage(CachedImage*) a/Source/WebCore/rendering/RenderObject.cpp_sec2
2943
    if (document()->activeDOMObjectsAreSuspended())
2947
    if (document()->activeDOMObjectsAreSuspended())
2944
        return false;
2948
        return false;
2945
2949
2950
    // FrameView knows whether animation is visible
2951
    if (!view()->frameView()->shouldRenderAnimation(this))
2952
        return false;
2953
2946
    // If we're not in a window (i.e., we're dormant from being put in the b/f cache or in a background tab)
2954
    // If we're not in a window (i.e., we're dormant from being put in the b/f cache or in a background tab)
2947
    // then we don't want to render either.
2955
    // then we don't want to render either.
2948
    return !document()->inPageCache() && !document()->view()->isOffscreen();
2956
    return !document()->inPageCache() && !document()->view()->isOffscreen();

Return to Bug 112327