Changeset 103062 in webkit


Ignore:
Timestamp:
Dec 16, 2011 5:43:37 AM (12 years ago)
Author:
alexis.menard@openbossa.org
Message:

Add support for <ol reversed>.
https://bugs.webkit.org/show_bug.cgi?id=36724

The reversed attribute makes an ordered list appear with marker values
decreasing from n, where n is the number of items.
See: http://www.whatwg.org/specs/web-apps/current-work/#attr-ol-reversed

Patch by Alexis Menard <alexis.menard@openbossa.org>, Jakub Wieczorek <jwieczorek@webkit.org> on 2011-12-16
Reviewed by Darin Adler.

Source/WebCore:

Tests: fast/lists/ol-reversed-dynamic-simple.html

fast/lists/ol-reversed-dynamic.html
fast/lists/ol-reversed-nested-items.html
fast/lists/ol-reversed-nested-list.html
fast/lists/ol-reversed-simple.html

  • html/HTMLAttributeNames.in:
  • html/HTMLOListElement.cpp:

(WebCore::HTMLOListElement::HTMLOListElement):
(WebCore::HTMLOListElement::parseMappedAttribute):
(WebCore::HTMLOListElement::updateItemValues):
(WebCore::HTMLOListElement::recalculateItemCount):

  • html/HTMLOListElement.h:

(WebCore::HTMLOListElement::start):
(WebCore::HTMLOListElement::isReversed):
(WebCore::HTMLOListElement::itemCountChanged):
(WebCore::HTMLOListElement::itemCount):

  • html/HTMLOListElement.idl:
  • rendering/RenderListItem.cpp:

(WebCore::RenderListItem::nextListItem):
(WebCore::previousListItem):
(WebCore::RenderListItem::calcValue):
(WebCore::RenderListItem::explicitValueChanged):
(WebCore::previousOrNextItem):
(WebCore::RenderListItem::updateListMarkerNumbers):

  • rendering/RenderListItem.h:

LayoutTests:

  • fast/lists/ol-reversed-dynamic-expected.txt: Added.
  • fast/lists/ol-reversed-dynamic-simple-expected.txt: Added.
  • fast/lists/ol-reversed-dynamic-simple.html: Added.
  • fast/lists/ol-reversed-dynamic.html: Added.
  • fast/lists/ol-reversed-nested-items-expected.txt: Added.
  • fast/lists/ol-reversed-nested-items.html: Added.
  • fast/lists/ol-reversed-nested-list-expected.txt: Added.
  • fast/lists/ol-reversed-nested-list.html: Added.
  • fast/lists/ol-reversed-simple-expected.txt: Added.
  • fast/lists/ol-reversed-simple.html: Added.
Location:
trunk
Files:
11 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r103057 r103062  
     12011-12-16  Alexis Menard  <alexis.menard@openbossa.org>, Jakub Wieczorek  <jwieczorek@webkit.org>
     2
     3        Add support for <ol reversed>.
     4        https://bugs.webkit.org/show_bug.cgi?id=36724
     5
     6        The reversed attribute makes an ordered list appear with marker values
     7        decreasing from n, where n is the number of items.
     8        See: http://www.whatwg.org/specs/web-apps/current-work/#attr-ol-reversed
     9
     10        Reviewed by Darin Adler.
     11
     12        * fast/lists/ol-reversed-dynamic-expected.txt: Added.
     13        * fast/lists/ol-reversed-dynamic-simple-expected.txt: Added.
     14        * fast/lists/ol-reversed-dynamic-simple.html: Added.
     15        * fast/lists/ol-reversed-dynamic.html: Added.
     16        * fast/lists/ol-reversed-nested-items-expected.txt: Added.
     17        * fast/lists/ol-reversed-nested-items.html: Added.
     18        * fast/lists/ol-reversed-nested-list-expected.txt: Added.
     19        * fast/lists/ol-reversed-nested-list.html: Added.
     20        * fast/lists/ol-reversed-simple-expected.txt: Added.
     21        * fast/lists/ol-reversed-simple.html: Added.
     22
    1232011-12-16  Hajime Morrita  <morrita@chromium.org>
    224
  • trunk/Source/WebCore/ChangeLog

    r103059 r103062  
     12011-12-16  Alexis Menard  <alexis.menard@openbossa.org>, Jakub Wieczorek  <jwieczorek@webkit.org>
     2
     3        Add support for <ol reversed>.
     4        https://bugs.webkit.org/show_bug.cgi?id=36724
     5
     6        The reversed attribute makes an ordered list appear with marker values
     7        decreasing from n, where n is the number of items.
     8        See: http://www.whatwg.org/specs/web-apps/current-work/#attr-ol-reversed
     9
     10        Reviewed by Darin Adler.
     11
     12        Tests: fast/lists/ol-reversed-dynamic-simple.html
     13               fast/lists/ol-reversed-dynamic.html
     14               fast/lists/ol-reversed-nested-items.html
     15               fast/lists/ol-reversed-nested-list.html
     16               fast/lists/ol-reversed-simple.html
     17
     18        * html/HTMLAttributeNames.in:
     19        * html/HTMLOListElement.cpp:
     20        (WebCore::HTMLOListElement::HTMLOListElement):
     21        (WebCore::HTMLOListElement::parseMappedAttribute):
     22        (WebCore::HTMLOListElement::updateItemValues):
     23        (WebCore::HTMLOListElement::recalculateItemCount):
     24        * html/HTMLOListElement.h:
     25        (WebCore::HTMLOListElement::start):
     26        (WebCore::HTMLOListElement::isReversed):
     27        (WebCore::HTMLOListElement::itemCountChanged):
     28        (WebCore::HTMLOListElement::itemCount):
     29        * html/HTMLOListElement.idl:
     30        * rendering/RenderListItem.cpp:
     31        (WebCore::RenderListItem::nextListItem):
     32        (WebCore::previousListItem):
     33        (WebCore::RenderListItem::calcValue):
     34        (WebCore::RenderListItem::explicitValueChanged):
     35        (WebCore::previousOrNextItem):
     36        (WebCore::RenderListItem::updateListMarkerNumbers):
     37        * rendering/RenderListItem.h:
     38
    1392011-12-15  Stephen White  <senorblanco@chromium.org>
    240
  • trunk/Source/WebCore/html/HTMLAttributeNames.in

    r101987 r103062  
    267267results
    268268rev
     269reversed
    269270role
    270271rows
  • trunk/Source/WebCore/html/HTMLOListElement.cpp

    r61959 r103062  
    3636HTMLOListElement::HTMLOListElement(const QualifiedName& tagName, Document* document)
    3737    : HTMLElement(tagName, document)
    38     , m_start(1)
     38    , m_start(0xBADBEEF)
     39    , m_itemCount(0)
     40    , m_hasExplicitStart(false)
     41    , m_isReversed(false)
     42    , m_shouldRecalculateItemCount(false)
    3943{
    4044    ASSERT(hasTagName(olTag));
     
    7579            addCSSProperty(attr, CSSPropertyListStyleType, CSSValueDecimal);
    7680    } else if (attr->name() == startAttr) {
     81        int oldStart = start();
    7782        bool canParse;
    78         int start = attr->value().toInt(&canParse);
    79         if (!canParse)
    80             start = 1;
    81         if (start == m_start)
     83        int parsedStart = attr->value().toInt(&canParse);
     84        m_hasExplicitStart = canParse;
     85        m_start = canParse ? parsedStart : 0xBADBEEF;
     86        if (oldStart == start())
    8287            return;
    83         m_start = start;
    84         for (RenderObject* child = renderer(); child; child = child->nextInPreOrder(renderer())) {
    85             if (child->isListItem())
    86                 toRenderListItem(child)->updateValue();
    87         }
     88        updateItemValues();
     89    } else if (attr->name() == reversedAttr) {
     90        bool reversed = !attr->isNull();
     91        if (reversed == m_isReversed)
     92            return;
     93        m_isReversed = reversed;
     94        updateItemValues();
    8895    } else
    8996        HTMLElement::parseMappedAttribute(attr);
     
    95102}
    96103
     104void HTMLOListElement::updateItemValues()
     105{
     106    for (RenderListItem* listItem = RenderListItem::nextListItem(renderer()); listItem; listItem = RenderListItem::nextListItem(renderer(), listItem))
     107        listItem->updateValue();
    97108}
     109
     110void HTMLOListElement::recalculateItemCount()
     111{
     112    m_itemCount = 0;
     113
     114    for (RenderListItem* listItem = RenderListItem::nextListItem(renderer()); listItem; listItem = RenderListItem::nextListItem(renderer(), listItem))
     115        m_itemCount++;
     116
     117    m_shouldRecalculateItemCount = false;
     118}
     119
     120}
  • trunk/Source/WebCore/html/HTMLOListElement.h

    r66057 r103062  
    3333    static PassRefPtr<HTMLOListElement> create(const QualifiedName&, Document*);
    3434
    35     int start() const { return m_start; }
     35    int start() const { return m_hasExplicitStart ? m_start : (m_isReversed ? itemCount() : 1); }
    3636    void setStart(int);
     37
     38    bool isReversed() const { return m_isReversed; }
     39
     40    void itemCountChanged() { m_shouldRecalculateItemCount = true; }
    3741
    3842private:
    3943    HTMLOListElement(const QualifiedName&, Document*);
    4044       
     45    void updateItemValues();
     46
     47    unsigned itemCount() const
     48    {
     49        if (m_shouldRecalculateItemCount)
     50            const_cast<HTMLOListElement*>(this)->recalculateItemCount();
     51        return m_itemCount;
     52    }
     53
     54    void recalculateItemCount();
     55
    4156    virtual bool mapToEntry(const QualifiedName&, MappedAttributeEntry&) const;
    4257    virtual void parseMappedAttribute(Attribute*);
    4358
    4459    int m_start;
     60    unsigned m_itemCount;
     61
     62    bool m_hasExplicitStart : 1;
     63    bool m_isReversed : 1;
     64    bool m_shouldRecalculateItemCount : 1;
    4565};
    4666
  • trunk/Source/WebCore/html/HTMLOListElement.idl

    r89269 r103062  
    2323        attribute [Reflect] boolean compact;
    2424        attribute long start;
     25        attribute [Reflect] boolean reversed;
    2526        attribute [Reflect] DOMString type;
    2627    };
  • trunk/Source/WebCore/rendering/RenderListItem.cpp

    r94640 r103062  
    102102}
    103103
    104 static RenderListItem* previousListItem(Node* list, const RenderListItem* item)
    105 {
    106     for (RenderObject* renderer = item->previousInPreOrder(); renderer && renderer != list->renderer(); renderer = renderer->previousInPreOrder()) {
     104RenderListItem* RenderListItem::nextListItem(RenderObject* list, RenderListItem* item)
     105{
     106    if (!list)
     107        return 0;
     108
     109    RenderObject* renderer = item ? item : list;
     110    while ((renderer = renderer->nextInPreOrder(list))) {
     111        if (renderer->node() && isList(renderer->node())) {
     112            // We've found a nested, independent list: nothing to do here.
     113            renderer = renderer->nextInPreOrderAfterChildren(list);
     114            continue;
     115        }
     116
     117        if (renderer->isListItem())
     118            return toRenderListItem(renderer);
     119    }
     120    return 0;
     121}
     122
     123static RenderListItem* previousListItem(RenderObject* list, const RenderListItem* item)
     124{
     125    for (RenderObject* renderer = item->previousInPreOrder(); renderer && renderer != list; renderer = renderer->previousInPreOrder()) {
    107126        if (!renderer->isListItem())
    108127            continue;
    109128        Node* otherList = enclosingList(toRenderListItem(renderer));
    110129        // This item is part of our current list, so it's what we're looking for.
    111         if (list == otherList)
     130        if (list->node() == otherList)
    112131            return toRenderListItem(renderer);
    113132        // We found ourself inside another list; lets skip the rest of it.
     
    125144    if (m_hasExplicitValue)
    126145        return m_explicitValue;
     146
    127147    Node* list = enclosingList(this);
     148    RenderObject* listRenderer = list ? list->renderer() : 0;
     149    HTMLOListElement* oListElement = (list && list->hasTagName(olTag)) ? static_cast<HTMLOListElement*>(list) : 0;
     150    int valueStep = 1;
     151    if (oListElement && oListElement->isReversed())
     152        valueStep = -1;
     153
    128154    // FIXME: This recurses to a possible depth of the length of the list.
    129155    // That's not good -- we need to change this to an iterative algorithm.
    130     if (RenderListItem* previousItem = previousListItem(list, this))
    131         return previousItem->value() + 1;
    132     if (list && list->hasTagName(olTag))
    133         return static_cast<HTMLOListElement*>(list)->start();
     156    if (RenderListItem* previousItem = previousListItem(listRenderer, this))
     157        return previousItem->value() + valueStep;
     158
     159    if (oListElement)
     160        return oListElement->start();
     161
    134162    return 1;
    135163}
     
    393421    if (listNode)
    394422        listRenderer = listNode->renderer();
    395     for (RenderObject* renderer = this; renderer; renderer = renderer->nextInPreOrder(listRenderer))
    396         if (renderer->isListItem()) {
    397             RenderListItem* item = toRenderListItem(renderer);
    398             if (!item->m_hasExplicitValue) {
    399                 item->m_isValueUpToDate = false;
    400                 if (RenderListMarker* marker = item->m_marker)
    401                     marker->setNeedsLayoutAndPrefWidthsRecalc();
    402             }
    403         }
     423    for (RenderListItem* item = this; item; item = nextListItem(listRenderer, item))
     424        item->updateValue();
    404425}
    405426
     
    427448}
    428449
     450static RenderListItem* previousOrNextItem(bool isListReversed, RenderObject* list, RenderListItem* item)
     451{
     452    return isListReversed ? previousListItem(list, item) : RenderListItem::nextListItem(list, item);
     453}
     454
    429455void RenderListItem::updateListMarkerNumbers()
    430456{
     
    434460        return;
    435461
     462    bool isListReversed = false;
    436463    RenderObject* list = listNode->renderer();
    437     RenderObject* child = nextInPreOrder(list);
    438     while (child) {
    439         if (child->node() && isList(child->node())) {
    440             // We've found a nested, independent list: nothing to do here.
    441             child = child->nextInPreOrderAfterChildren(list);
    442             continue;
    443         }
    444 
    445         if (child->isListItem()) {
    446             RenderListItem* item = toRenderListItem(child);
    447 
    448             if (!item->m_isValueUpToDate) {
    449                 // If an item has been marked for update before, we can safely
    450                 // assume that all the following ones have too.
    451                 // This gives us the opportunity to stop here and avoid
    452                 // marking the same nodes again.
    453                 break;
    454             }
    455 
    456             item->updateValue();
    457         }
    458 
    459         child = child->nextInPreOrder(list);
     464    HTMLOListElement* oListElement = (listNode && listNode->hasTagName(olTag)) ? static_cast<HTMLOListElement*>(listNode) : 0;
     465    if (oListElement) {
     466        oListElement->itemCountChanged();
     467        isListReversed = oListElement->isReversed();
     468    }
     469    for (RenderListItem* item = previousOrNextItem(isListReversed, list, this); item; item = previousOrNextItem(isListReversed, list, item)) {
     470        if (!item->m_isValueUpToDate) {
     471            // If an item has been marked for update before, we can safely
     472            // assume that all the following ones have too.
     473            // This gives us the opportunity to stop here and avoid
     474            // marking the same nodes again.
     475            break;
     476        }
     477        item->updateValue();
    460478    }
    461479}
  • trunk/Source/WebCore/rendering/RenderListItem.h

    r97054 r103062  
    5050    void updateListMarkerNumbers();
    5151
     52    static RenderListItem* nextListItem(RenderObject* listRenderer, RenderListItem* = 0);
     53
    5254private:
    5355    virtual const char* renderName() const { return "RenderListItem"; }
Note: See TracChangeset for help on using the changeset viewer.