layout/base/nsGenConList.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 // vim:cindent:ts=2:et:sw=2:
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* base class for nsCounterList and nsQuoteList */
     9 #include "nsGenConList.h"
    10 #include "nsLayoutUtils.h"
    11 #include "nsIContent.h"
    13 void
    14 nsGenConList::Clear()
    15 {
    16   //Delete entire list
    17   if (!mFirstNode)
    18     return;
    19   for (nsGenConNode *node = Next(mFirstNode); node != mFirstNode;
    20        node = Next(mFirstNode))
    21   {
    22     Remove(node);
    23     delete node;
    24   }
    25   delete mFirstNode;
    27   mFirstNode = nullptr;
    28   mSize = 0;
    29 }
    31 bool
    32 nsGenConList::DestroyNodesFor(nsIFrame* aFrame)
    33 {
    34   if (!mFirstNode)
    35     return false; // list empty
    36   nsGenConNode* node;
    37   bool destroyed = false;
    38   while (mFirstNode->mPseudoFrame == aFrame) {
    39     destroyed = true;
    40     node = Next(mFirstNode);
    41     bool isLastNode = node == mFirstNode; // before they're dangling
    42     Remove(mFirstNode);
    43     delete mFirstNode;
    44     if (isLastNode) {
    45       mFirstNode = nullptr;
    46       return true;
    47     }
    48     else {
    49       mFirstNode = node;
    50     }
    51   }
    52   node = Next(mFirstNode);
    53   while (node != mFirstNode) {
    54     if (node->mPseudoFrame == aFrame) {
    55       destroyed = true;
    56       nsGenConNode *nextNode = Next(node);
    57       Remove(node);
    58       delete node;
    59       node = nextNode;
    60     } else {
    61       node = Next(node);
    62     }
    63   }
    64   return destroyed;
    65 }
    67 /**
    68  * Compute the type of the pseudo and the content for the pseudo that
    69  * we'll use for comparison purposes.
    70  * @param aContent the content to use is stored here; it's the element
    71  * that generated the ::before or ::after content, or (if not for generated
    72  * content), the frame's own element
    73  * @return -1 for ::before, +1 for ::after, and 0 otherwise.
    74  */
    75 inline int32_t PseudoCompareType(nsIFrame* aFrame, nsIContent** aContent)
    76 {
    77   nsIAtom *pseudo = aFrame->StyleContext()->GetPseudo();
    78   if (pseudo == nsCSSPseudoElements::before) {
    79     *aContent = aFrame->GetContent()->GetParent();
    80     return -1;
    81   }
    82   if (pseudo == nsCSSPseudoElements::after) {
    83     *aContent = aFrame->GetContent()->GetParent();
    84     return 1;
    85   }
    86   *aContent = aFrame->GetContent();
    87   return 0;
    88 }
    90 /* static */ bool
    91 nsGenConList::NodeAfter(const nsGenConNode* aNode1, const nsGenConNode* aNode2)
    92 {
    93   nsIFrame *frame1 = aNode1->mPseudoFrame;
    94   nsIFrame *frame2 = aNode2->mPseudoFrame;
    95   if (frame1 == frame2) {
    96     NS_ASSERTION(aNode2->mContentIndex != aNode1->mContentIndex, "identical");
    97     return aNode1->mContentIndex > aNode2->mContentIndex;
    98   }
    99   nsIContent *content1;
   100   nsIContent *content2;
   101   int32_t pseudoType1 = PseudoCompareType(frame1, &content1);
   102   int32_t pseudoType2 = PseudoCompareType(frame2, &content2);
   103   if (pseudoType1 == 0 || pseudoType2 == 0) {
   104     if (content1 == content2) {
   105       NS_ASSERTION(pseudoType1 != pseudoType2, "identical");
   106       return pseudoType2 == 0;
   107     }
   108     // We want to treat an element as coming before its :before (preorder
   109     // traversal), so treating both as :before now works.
   110     if (pseudoType1 == 0) pseudoType1 = -1;
   111     if (pseudoType2 == 0) pseudoType2 = -1;
   112   } else {
   113     if (content1 == content2) {
   114       NS_ASSERTION(pseudoType1 != pseudoType2, "identical");
   115       return pseudoType1 == 1;
   116     }
   117   }
   118   // XXX Switch to the frame version of DoCompareTreePosition?
   119   int32_t cmp = nsLayoutUtils::DoCompareTreePosition(content1, content2,
   120                                                      pseudoType1, -pseudoType2);
   121   NS_ASSERTION(cmp != 0, "same content, different frames");
   122   return cmp > 0;
   123 }
   125 void
   126 nsGenConList::Insert(nsGenConNode* aNode)
   127 {
   128   if (mFirstNode) {
   129     // Check for append.
   130     if (NodeAfter(aNode, Prev(mFirstNode))) {
   131       PR_INSERT_BEFORE(aNode, mFirstNode);
   132     }
   133     else {
   134       // Binary search.
   136       // the range of indices at which |aNode| could end up.
   137       // (We already know it can't be at index mSize.)
   138       uint32_t first = 0, last = mSize - 1;
   140       // A cursor to avoid walking more than the length of the list.
   141       nsGenConNode *curNode = Prev(mFirstNode);
   142       uint32_t curIndex = mSize - 1;
   144       while (first != last) {
   145         uint32_t test = (first + last) / 2;
   146         if (last == curIndex) {
   147           for ( ; curIndex != test; --curIndex)
   148             curNode = Prev(curNode);
   149         } else {
   150           for ( ; curIndex != test; ++curIndex)
   151             curNode = Next(curNode);
   152         }
   154         if (NodeAfter(aNode, curNode)) {
   155           first = test + 1;
   156           // if we exit the loop, we need curNode to be right
   157           ++curIndex;
   158           curNode = Next(curNode);
   159         } else {
   160           last = test;
   161         }
   162       }
   163       PR_INSERT_BEFORE(aNode, curNode);
   164       if (curNode == mFirstNode) {
   165         mFirstNode = aNode;
   166       }
   167     }
   168   }
   169   else {
   170     // initialize list with first node
   171     PR_INIT_CLIST(aNode);
   172     mFirstNode = aNode;
   173   }
   174   ++mSize;
   176   NS_ASSERTION(aNode == mFirstNode || NodeAfter(aNode, Prev(aNode)),
   177                "sorting error");
   178   NS_ASSERTION(IsLast(aNode) || NodeAfter(Next(aNode), aNode),
   179                "sorting error");
   180 }

mercurial