michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * a list of the recomputation that needs to be done in response to a michael@0: * style change michael@0: */ michael@0: michael@0: #include "nsStyleChangeList.h" michael@0: #include "nsIContent.h" michael@0: michael@0: static const uint32_t kGrowArrayBy = 10; michael@0: michael@0: nsStyleChangeList::nsStyleChangeList() michael@0: : mArray(mBuffer), michael@0: mArraySize(kStyleChangeBufferSize), michael@0: mCount(0) michael@0: { michael@0: MOZ_COUNT_CTOR(nsStyleChangeList); michael@0: } michael@0: michael@0: nsStyleChangeList::~nsStyleChangeList() michael@0: { michael@0: MOZ_COUNT_DTOR(nsStyleChangeList); michael@0: Clear(); michael@0: } michael@0: michael@0: nsresult michael@0: nsStyleChangeList::ChangeAt(int32_t aIndex, nsIFrame*& aFrame, nsIContent*& aContent, michael@0: nsChangeHint& aHint) const michael@0: { michael@0: if ((0 <= aIndex) && (aIndex < mCount)) { michael@0: aFrame = mArray[aIndex].mFrame; michael@0: aContent = mArray[aIndex].mContent; michael@0: aHint = mArray[aIndex].mHint; michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_ILLEGAL_VALUE; michael@0: } michael@0: michael@0: nsresult michael@0: nsStyleChangeList::ChangeAt(int32_t aIndex, const nsStyleChangeData** aChangeData) const michael@0: { michael@0: if ((0 <= aIndex) && (aIndex < mCount)) { michael@0: *aChangeData = &mArray[aIndex]; michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_ILLEGAL_VALUE; michael@0: } michael@0: michael@0: nsresult michael@0: nsStyleChangeList::AppendChange(nsIFrame* aFrame, nsIContent* aContent, nsChangeHint aHint) michael@0: { michael@0: NS_ASSERTION(aFrame || (aHint & nsChangeHint_ReconstructFrame), michael@0: "must have frame"); michael@0: NS_ASSERTION(aContent || !(aHint & nsChangeHint_ReconstructFrame), michael@0: "must have content"); michael@0: // XXXbz we should make this take Element instead of nsIContent michael@0: NS_ASSERTION(!aContent || aContent->IsElement(), michael@0: "Shouldn't be trying to restyle non-elements directly"); michael@0: NS_ASSERTION(!(aHint & nsChangeHint_AllReflowHints) || michael@0: (aHint & nsChangeHint_NeedReflow), michael@0: "Reflow hint bits set without actually asking for a reflow"); michael@0: michael@0: if ((0 < mCount) && (aHint & nsChangeHint_ReconstructFrame)) { // filter out all other changes for same content michael@0: if (aContent) { michael@0: for (int32_t index = mCount - 1; index >= 0; --index) { michael@0: if (aContent == mArray[index].mContent) { // remove this change michael@0: aContent->Release(); michael@0: mCount--; michael@0: if (index < mCount) { // move later changes down michael@0: ::memmove(&mArray[index], &mArray[index + 1], michael@0: (mCount - index) * sizeof(nsStyleChangeData)); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: int32_t last = mCount - 1; michael@0: if ((0 < mCount) && aFrame && (aFrame == mArray[last].mFrame)) { // same as last frame michael@0: NS_UpdateHint(mArray[last].mHint, aHint); michael@0: } michael@0: else { michael@0: if (mCount == mArraySize) { michael@0: int32_t newSize = mArraySize + kGrowArrayBy; michael@0: nsStyleChangeData* newArray = new nsStyleChangeData[newSize]; michael@0: if (newArray) { michael@0: memcpy(newArray, mArray, mCount * sizeof(nsStyleChangeData)); michael@0: if (mArray != mBuffer) { michael@0: delete [] mArray; michael@0: } michael@0: mArray = newArray; michael@0: mArraySize = newSize; michael@0: } michael@0: else { michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: } michael@0: mArray[mCount].mFrame = aFrame; michael@0: mArray[mCount].mContent = aContent; michael@0: if (aContent) { michael@0: aContent->AddRef(); michael@0: } michael@0: mArray[mCount].mHint = aHint; michael@0: mCount++; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsStyleChangeList::Clear() michael@0: { michael@0: for (int32_t index = mCount - 1; index >= 0; --index) { michael@0: nsIContent* content = mArray[index].mContent; michael@0: if (content) { michael@0: content->Release(); michael@0: } michael@0: } michael@0: if (mArray != mBuffer) { michael@0: delete [] mArray; michael@0: mArray = mBuffer; michael@0: mArraySize = kStyleChangeBufferSize; michael@0: } michael@0: mCount = 0; michael@0: } michael@0: