Changeset 89750 in webkit


Ignore:
Timestamp:
Jun 25, 2011 3:02:29 PM (13 years ago)
Author:
krit@webkit.org
Message:

2011-06-25 Dirk Schulze <krit@webkit.org>

Reviewed by Nikolas Zimmermann.

SVGAnimatedType should support SVGNumberList animation
https://bugs.webkit.org/show_bug.cgi?id=63387


Follow up of "SVGAnimation should use direct unit animation for SVGLength": https://bugs.webkit.org/show_bug.cgi?id=61368
This patch continues the conversion to the new concept of SVGAnimatorFactory with SVGNumberList.


Animations of attributes with type SVGNumberList can be interpolated now.

Tests: svg/animations/svgnumberlist-animation-1.html

svg/animations/svgnumberlist-animation-2.html

  • CMakeLists.txt: Added new file to build system.
  • GNUmakefile.list.am: Ditto.
  • WebCore.gypi: Ditto.
  • WebCore.pro: Ditto.
  • WebCore.xcodeproj/project.pbxproj: Ditto.
  • svg/SVGAllInOne.cpp: Ditto.
  • svg/SVGAnimateElement.cpp: Make use of attribute type AnimatedNumberList. (WebCore::SVGAnimateElement::determineAnimatedAttributeType): (WebCore::SVGAnimateElement::calculateAnimatedValue): (WebCore::SVGAnimateElement::calculateFromAndToValues): (WebCore::SVGAnimateElement::calculateFromAndByValues): (WebCore::SVGAnimateElement::resetToBaseValue): (WebCore::SVGAnimateElement::applyResultsToTarget): (WebCore::SVGAnimateElement::calculateDistance):
  • svg/SVGAnimatedNumber.cpp: (WebCore::SVGAnimatedNumberAnimator::calculateAnimatedNumber): Made method static for reuse in SVGAnimatedNumberList (and SVGAnimatedNumberOptionalNumber later). (WebCore::SVGAnimatedNumberAnimator::calculateAnimatedValue): Use new static function.
  • svg/SVGAnimatedNumber.h:
  • svg/SVGAnimatedNumberList.cpp: Added. New animator for SVGNumberList. (WebCore::SVGAnimatedNumberListAnimator::SVGAnimatedNumberListAnimator): (WebCore::SVGAnimatedNumberListAnimator::constructFromString): (WebCore::SVGAnimatedNumberListAnimator::calculateFromAndToValues): (WebCore::SVGAnimatedNumberListAnimator::calculateFromAndByValues): (WebCore::SVGAnimatedNumberListAnimator::calculateAnimatedValue): (WebCore::SVGAnimatedNumberListAnimator::calculateDistance):
  • svg/SVGAnimatedNumberList.h: (WebCore::SVGAnimatedNumberListAnimator::~SVGAnimatedNumberListAnimator):
  • svg/SVGAnimatedType.cpp: Use new Animator. (WebCore::SVGAnimatedType::~SVGAnimatedType): (WebCore::SVGAnimatedType::createNumberList): (WebCore::SVGAnimatedType::numberList): (WebCore::SVGAnimatedType::valueAsString): (WebCore::SVGAnimatedType::setValueAsString):
  • svg/SVGAnimatedType.h:
  • svg/SVGAnimatorFactory.h: (WebCore::SVGAnimatorFactory::create):

2011-06-25 Dirk Schulze <krit@webkit.org>

Reviewed by Nikolas Zimmermann.

SVGAnimatedType should support SVGNumberList animation
https://bugs.webkit.org/show_bug.cgi?id=63387

Test animation of attributes with type SVGNumberList.

  • svg/animations/script-tests/svgnumberlist-animation-1.js: Added. (sample1): (sample2): (sample3): (executeTest):
  • svg/animations/script-tests/svgnumberlist-animation-2.js: Added. (sample1): (sample2): (sample3): (executeTest):
  • svg/animations/svgnumberlist-animation-1-expected.txt: Added.
  • svg/animations/svgnumberlist-animation-1.html: Added.
  • svg/animations/svgnumberlist-animation-2-expected.txt: Added.
  • svg/animations/svgnumberlist-animation-2.html: Added.
Location:
trunk
Files:
7 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r89747 r89750  
     12011-06-25  Dirk Schulze  <krit@webkit.org>
     2
     3        Reviewed by Nikolas Zimmermann.
     4
     5        SVGAnimatedType should support SVGNumberList animation
     6        https://bugs.webkit.org/show_bug.cgi?id=63387
     7
     8        Test animation of attributes with type SVGNumberList.
     9
     10        * svg/animations/script-tests/svgnumberlist-animation-1.js: Added.
     11        (sample1):
     12        (sample2):
     13        (sample3):
     14        (executeTest):
     15        * svg/animations/script-tests/svgnumberlist-animation-2.js: Added.
     16        (sample1):
     17        (sample2):
     18        (sample3):
     19        (executeTest):
     20        * svg/animations/svgnumberlist-animation-1-expected.txt: Added.
     21        * svg/animations/svgnumberlist-animation-1.html: Added.
     22        * svg/animations/svgnumberlist-animation-2-expected.txt: Added.
     23        * svg/animations/svgnumberlist-animation-2.html: Added.
     24
    1252011-06-25  Balazs Kelemen  <kbalazs@webkit.org>
    226
  • trunk/Source/WebCore/CMakeLists.txt

    r89749 r89750  
    16611661        svg/SVGAnimatedLength.cpp
    16621662        svg/SVGAnimatedNumber.cpp
     1663        svg/SVGAnimatedNumberList.cpp
    16631664        svg/SVGAnimatedPath.cpp
    16641665        svg/SVGAnimatedPointList.cpp
  • trunk/Source/WebCore/ChangeLog

    r89749 r89750  
     12011-06-25  Dirk Schulze  <krit@webkit.org>
     2
     3        Reviewed by Nikolas Zimmermann.
     4
     5        SVGAnimatedType should support SVGNumberList animation
     6        https://bugs.webkit.org/show_bug.cgi?id=63387
     7       
     8        Follow up of "SVGAnimation should use direct unit animation for SVGLength": https://bugs.webkit.org/show_bug.cgi?id=61368
     9        This patch continues the conversion to the new concept of SVGAnimatorFactory with SVGNumberList.
     10       
     11        Animations of attributes with type SVGNumberList can be interpolated now.
     12
     13        Tests: svg/animations/svgnumberlist-animation-1.html
     14               svg/animations/svgnumberlist-animation-2.html
     15
     16        * CMakeLists.txt: Added new file to build system.
     17        * GNUmakefile.list.am: Ditto.
     18        * WebCore.gypi: Ditto.
     19        * WebCore.pro: Ditto.
     20        * WebCore.xcodeproj/project.pbxproj: Ditto.
     21        * svg/SVGAllInOne.cpp: Ditto.
     22        * svg/SVGAnimateElement.cpp: Make use of attribute type AnimatedNumberList.
     23        (WebCore::SVGAnimateElement::determineAnimatedAttributeType):
     24        (WebCore::SVGAnimateElement::calculateAnimatedValue):
     25        (WebCore::SVGAnimateElement::calculateFromAndToValues):
     26        (WebCore::SVGAnimateElement::calculateFromAndByValues):
     27        (WebCore::SVGAnimateElement::resetToBaseValue):
     28        (WebCore::SVGAnimateElement::applyResultsToTarget):
     29        (WebCore::SVGAnimateElement::calculateDistance):
     30        * svg/SVGAnimatedNumber.cpp:
     31        (WebCore::SVGAnimatedNumberAnimator::calculateAnimatedNumber): Made method static for reuse in SVGAnimatedNumberList (and SVGAnimatedNumberOptionalNumber later).
     32        (WebCore::SVGAnimatedNumberAnimator::calculateAnimatedValue): Use new static function.
     33        * svg/SVGAnimatedNumber.h:
     34        * svg/SVGAnimatedNumberList.cpp: Added. New animator for SVGNumberList.
     35        (WebCore::SVGAnimatedNumberListAnimator::SVGAnimatedNumberListAnimator):
     36        (WebCore::SVGAnimatedNumberListAnimator::constructFromString):
     37        (WebCore::SVGAnimatedNumberListAnimator::calculateFromAndToValues):
     38        (WebCore::SVGAnimatedNumberListAnimator::calculateFromAndByValues):
     39        (WebCore::SVGAnimatedNumberListAnimator::calculateAnimatedValue):
     40        (WebCore::SVGAnimatedNumberListAnimator::calculateDistance):
     41        * svg/SVGAnimatedNumberList.h:
     42        (WebCore::SVGAnimatedNumberListAnimator::~SVGAnimatedNumberListAnimator):
     43        * svg/SVGAnimatedType.cpp: Use new Animator.
     44        (WebCore::SVGAnimatedType::~SVGAnimatedType):
     45        (WebCore::SVGAnimatedType::createNumberList):
     46        (WebCore::SVGAnimatedType::numberList):
     47        (WebCore::SVGAnimatedType::valueAsString):
     48        (WebCore::SVGAnimatedType::setValueAsString):
     49        * svg/SVGAnimatedType.h:
     50        * svg/SVGAnimatorFactory.h:
     51        (WebCore::SVGAnimatorFactory::create):
     52
    1532011-06-25  Nikolas Zimmermann  <nzimmermann@rim.com>
    254
  • trunk/Source/WebCore/GNUmakefile.list.am

    r89749 r89750  
    34343434        Source/WebCore/svg/SVGAnimatedNumber.cpp \
    34353435        Source/WebCore/svg/SVGAnimatedNumber.h \
     3436        Source/WebCore/svg/SVGAnimatedNumberList.cpp \
    34363437        Source/WebCore/svg/SVGAnimatedNumberList.h \
    34373438        Source/WebCore/svg/SVGAnimatedPath.cpp \
  • trunk/Source/WebCore/WebCore.gypi

    r89749 r89750  
    57135713            'svg/SVGAnimatedLength.cpp',
    57145714            'svg/SVGAnimatedNumber.cpp',
     5715            'svg/SVGAnimatedNumberList.cpp',
    57155716            'svg/SVGAnimatedPath.cpp',
    57165717            'svg/SVGAnimatedPointList.cpp',
  • trunk/Source/WebCore/WebCore.pro

    r89749 r89750  
    33403340              svg/SVGAnimatedLength.cpp \
    33413341              svg/SVGAnimatedNumber.cpp \
     3342              svg/SVGAnimatedNumberList.cpp \
    33423343              svg/SVGAnimatedPath.cpp \
    33433344              svg/SVGAnimatedPointList.cpp \
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r89749 r89750  
    932932                41FA303F1316C29C00C0BFC5 /* RenderMediaControls.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FA303D1316C29C00C0BFC5 /* RenderMediaControls.h */; };
    933933                43142E7A13B1E97700F1C871 /* SVGAnimatedRect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43142E7913B1E97700F1C871 /* SVGAnimatedRect.cpp */; };
     934                4331AC7813B6870000A9E5AE /* SVGAnimatedNumberList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4331AC7713B6870000A9E5AE /* SVGAnimatedNumberList.cpp */; };
    934935                4358E86A1360A21600E4748C /* DOMSVGFEDropShadowElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 4358E8671360A21600E4748C /* DOMSVGFEDropShadowElement.h */; };
    935936                4358E86B1360A21600E4748C /* DOMSVGFEDropShadowElement.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4358E8681360A21600E4748C /* DOMSVGFEDropShadowElement.mm */; };
     
    73917392                41FA303D1316C29C00C0BFC5 /* RenderMediaControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMediaControls.h; sourceTree = "<group>"; };
    73927393                43142E7913B1E97700F1C871 /* SVGAnimatedRect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedRect.cpp; sourceTree = "<group>"; };
     7394                4331AC7713B6870000A9E5AE /* SVGAnimatedNumberList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedNumberList.cpp; sourceTree = "<group>"; };
    73937395                4358E8671360A21600E4748C /* DOMSVGFEDropShadowElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMSVGFEDropShadowElement.h; sourceTree = "<group>"; };
    73947396                4358E8681360A21600E4748C /* DOMSVGFEDropShadowElement.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMSVGFEDropShadowElement.mm; sourceTree = "<group>"; };
     
    1740617408                                08B35B12127B6A7C005314DD /* SVGAnimatedNumber.h */,
    1740717409                                B22277EC0D00BF1F0071B782 /* SVGAnimatedNumber.idl */,
     17410                                4331AC7713B6870000A9E5AE /* SVGAnimatedNumberList.cpp */,
    1740817411                                08B35B16127B6A88005314DD /* SVGAnimatedNumberList.h */,
    1740917412                                B22277ED0D00BF1F0071B782 /* SVGAnimatedNumberList.idl */,
     
    2582825831                                08B5F25513B5FFF2002959EC /* SVGAnimatedPath.cpp in Sources */,
    2582925832                                376DCCE113B4F966002EBEFC /* TextRun.cpp in Sources */,
     25833                                4331AC7813B6870000A9E5AE /* SVGAnimatedNumberList.cpp in Sources */,
    2583025834                        );
    2583125835                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/WebCore/svg/SVGAllInOne.cpp

    r89749 r89750  
    3535#include "SVGAnimatedLength.cpp"
    3636#include "SVGAnimatedNumber.cpp"
     37#include "SVGAnimatedNumberList.cpp"
    3738#include "SVGAnimatedPath.cpp"
    3839#include "SVGAnimatedPointList.cpp"
  • trunk/Source/WebCore/svg/SVGAnimateElement.cpp

    r89749 r89750  
    112112    case AnimatedBoolean:
    113113    case AnimatedEnumeration:
    114     case AnimatedNumberList:
    115114    case AnimatedNumberOptionalNumber:
    116115    case AnimatedLengthList:
     
    125124    case AnimatedNumber:
    126125        return AnimatedNumber;
     126    case AnimatedNumberList:
     127        return AnimatedNumberList;
    127128    case AnimatedPath:
    128129        return AnimatedPath;
     
    164165    case AnimatedLength:
    165166    case AnimatedNumber:
     167    case AnimatedNumberList:           
    166168    case AnimatedPath:
    167169    case AnimatedPoints:
     
    229231    case AnimatedLength:
    230232    case AnimatedNumber:
     233    case AnimatedNumberList:
    231234    case AnimatedPath:
    232235    case AnimatedPoints:
     
    255258    case AnimatedLength:
    256259    case AnimatedNumber:
     260    case AnimatedNumberList:
    257261    case AnimatedPoints:
    258262    case AnimatedRect:
     
    280284    case AnimatedLength:
    281285    case AnimatedNumber:
     286    case AnimatedNumberList:
    282287    case AnimatedPath:
    283288    case AnimatedPoints:
     
    304309    case AnimatedLength:
    305310    case AnimatedNumber:
     311    case AnimatedNumberList:
    306312    case AnimatedPath:
    307313    case AnimatedPoints:
     
    328334    case AnimatedLength:
    329335    case AnimatedNumber:
     336    case AnimatedNumberList:
    330337    case AnimatedPath:
    331338    case AnimatedPoints:
  • trunk/Source/WebCore/svg/SVGAnimatedNumber.cpp

    r89587 r89750  
    6868}
    6969
     70void SVGAnimatedNumberAnimator::calculateAnimatedNumber(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, float& animatedNumber, float fromNumber, float toNumber)
     71{
     72    float number;
     73    if (animationElement->calcMode() == CalcModeDiscrete)
     74        number = percentage < 0.5 ? fromNumber : toNumber;
     75    else
     76        number = (toNumber - fromNumber) * percentage + fromNumber;
     77       
     78    // FIXME: This is not correct for values animation. Right now we transform values-animation to multiple from-to-animations and
     79    // accumulate every single value to the previous one. But accumulation should just take into account after a complete cycle
     80    // of values-animaiton. See example at: http://www.w3.org/TR/2001/REC-smil-animation-20010904/#RepeatingAnim
     81    if (animationElement->isAccumulated() && repeatCount)
     82        number += toNumber * repeatCount;
     83    if (animationElement->isAdditive() && animationElement->animationMode() != ToAnimation)
     84        animatedNumber += number;
     85    else
     86        animatedNumber = number;
     87}
     88
    7089void SVGAnimatedNumberAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount,
    7190                                                       OwnPtr<SVGAnimatedType>& from, OwnPtr<SVGAnimatedType>& to, OwnPtr<SVGAnimatedType>& animated)
     
    94113        parseNumberFromString(toNumberString, toNumber);
    95114    }
    96 
    97     float number;
    98     if (animationElement->calcMode() == CalcModeDiscrete)
    99         number = percentage < 0.5f ? fromNumber : toNumber;
    100     else
    101         number = (toNumber - fromNumber) * percentage + fromNumber;
    102115   
    103     // FIXME: This is not correct for values animation. Right now we transform values-animation to multiple from-to-animations and
    104     // accumulate every single value to the previous one. But accumulation should just take into account after a complete cycle
    105     // of values-animaiton. See example at: http://www.w3.org/TR/2001/REC-smil-animation-20010904/#RepeatingAnim
    106     if (animationElement->isAccumulated() && repeatCount)
    107         number += toNumber * repeatCount;
    108     if (animationElement->isAdditive() && animationMode != ToAnimation)
    109         animatedNumber += number;
    110     else
    111         animatedNumber = number;
     116    calculateAnimatedNumber(animationElement, percentage, repeatCount, animatedNumber, fromNumber, toNumber);
    112117}
    113118
  • trunk/Source/WebCore/svg/SVGAnimatedNumber.h

    r89587 r89750  
    4949    virtual ~SVGAnimatedNumberAnimator() { }
    5050   
     51    static void calculateAnimatedNumber(SVGAnimationElement*, float percentage, unsigned repeatCount, float& animatedNumber, float fromNumber, float toNumber);
     52   
    5153    virtual PassOwnPtr<SVGAnimatedType> constructFromString(const String&);
    5254   
  • trunk/Source/WebCore/svg/SVGAnimatedNumberList.h

    r73020 r89750  
    2323#if ENABLE(SVG)
    2424#include "SVGAnimatedListPropertyTearOff.h"
     25#include "SVGAnimatedTypeAnimator.h"
    2526#include "SVGNumberList.h"
    2627
     
    3536#define DEFINE_ANIMATED_NUMBER_LIST(OwnerType, DOMAttribute, UpperProperty, LowerProperty) \
    3637DEFINE_ANIMATED_LIST_PROPERTY(OwnerType, DOMAttribute, DOMAttribute.localName(), SVGAnimatedNumberList, SVGNumberList, UpperProperty, LowerProperty)
     38   
     39#if ENABLE(SVG_ANIMATION)
     40class SVGAnimationElement;
     41
     42class SVGAnimatedNumberListAnimator : public SVGAnimatedTypeAnimator {
     43   
     44public:
     45    SVGAnimatedNumberListAnimator(SVGAnimationElement*, SVGElement*);
     46    virtual ~SVGAnimatedNumberListAnimator() { }
     47   
     48    virtual PassOwnPtr<SVGAnimatedType> constructFromString(const String&);
     49   
     50    virtual void calculateFromAndToValues(OwnPtr<SVGAnimatedType>& fromValue, OwnPtr<SVGAnimatedType>& toValue, const String& fromString, const String& toString);
     51    virtual void calculateFromAndByValues(OwnPtr<SVGAnimatedType>& fromValue, OwnPtr<SVGAnimatedType>& toValue, const String& fromString, const String& byString);
     52    virtual void calculateAnimatedValue(float percentage, unsigned repeatCount,
     53                                        OwnPtr<SVGAnimatedType>& fromValue, OwnPtr<SVGAnimatedType>& toValue, OwnPtr<SVGAnimatedType>& animatedValue);
     54    virtual float calculateDistance(const String& fromString, const String& toString);
     55};
     56#endif // ENABLE(SVG_ANIMATION)
    3757
    3858} // namespace WebCore
  • trunk/Source/WebCore/svg/SVGAnimatedType.cpp

    r89749 r89750  
    2727#include "SVGColor.h"
    2828#include "SVGLength.h"
     29#include "SVGNumberList.h"
    2930#include "SVGParserUtilities.h"
    3031#include "SVGPathParserFactory.h"
     
    5354        delete m_data.number;
    5455        break;
     56    case AnimatedNumberList:
     57        delete m_data.numberList;
     58        break;
    5559    case AnimatedPath:
    5660        delete m_data.path;
     
    103107}
    104108
     109PassOwnPtr<SVGAnimatedType> SVGAnimatedType::createNumberList(SVGNumberList* numberList)
     110{
     111    ASSERT(numberList);
     112    OwnPtr<SVGAnimatedType> animatedType = adoptPtr(new SVGAnimatedType(AnimatedNumberList));
     113    animatedType->m_data.numberList = numberList;
     114    return animatedType.release();
     115}
     116
    105117PassOwnPtr<SVGAnimatedType> SVGAnimatedType::createPath(PassOwnPtr<SVGPathByteStream> path)
    106118{
     
    157169    ASSERT(m_type == AnimatedNumber);
    158170    return *m_data.number;
     171}
     172
     173SVGNumberList& SVGAnimatedType::numberList()
     174{
     175    ASSERT(m_type == AnimatedNumberList);
     176    return *m_data.numberList;
    159177}
    160178
     
    198216        ASSERT(m_data.number);
    199217        return String::number(*m_data.number);
     218    case AnimatedNumberList:
     219        ASSERT(m_data.numberList);
     220        return m_data.numberList->valueAsString();
    200221    case AnimatedPath: {
    201222        ASSERT(m_data.path);
     
    241262        parseNumberFromString(value, *m_data.number);
    242263        break;
     264    case AnimatedNumberList:
     265        ASSERT(m_data.numberList);
     266        m_data.numberList->parse(value);
     267        break;
    243268    case AnimatedPath: {
    244269        ASSERT(m_data.path);
  • trunk/Source/WebCore/svg/SVGAnimatedType.h

    r89749 r89750  
    3131class SVGAngle;
    3232class SVGLength;
     33class SVGNumberList;
    3334class SVGPointList;
    3435
     
    4243    static PassOwnPtr<SVGAnimatedType> createLength(SVGLength*);
    4344    static PassOwnPtr<SVGAnimatedType> createNumber(float*);
     45    static PassOwnPtr<SVGAnimatedType> createNumberList(SVGNumberList*);
    4446    static PassOwnPtr<SVGAnimatedType> createPath(PassOwnPtr<SVGPathByteStream>);
    4547    static PassOwnPtr<SVGAnimatedType> createPointList(SVGPointList*);
     
    5355    SVGLength& length();
    5456    float& number();
     57    SVGNumberList& numberList();
    5558    SVGPathByteStream* path();
    5659    SVGPointList& pointList();
     
    7780        SVGLength* length;
    7881        float* number;
     82        SVGNumberList* numberList;
    7983        SVGPathByteStream* path;
    8084        SVGPointList* pointList;
  • trunk/Source/WebCore/svg/SVGAnimatorFactory.h

    r89749 r89750  
    2626#include "SVGAnimatedLength.h"
    2727#include "SVGAnimatedNumber.h"
     28#include "SVGAnimatedNumberList.h"
    2829#include "SVGAnimatedPath.h"
    2930#include "SVGAnimatedPointList.h"
     
    5253        case AnimatedNumber:
    5354            return adoptPtr(new SVGAnimatedNumberAnimator(animationElement, contextElement));
     55        case AnimatedNumberList:
     56            return adoptPtr(new SVGAnimatedNumberListAnimator(animationElement, contextElement));
    5457        case AnimatedPath:
    5558            return adoptPtr(new SVGAnimatedPathAnimator(animationElement, contextElement));
Note: See TracChangeset for help on using the changeset viewer.