Separate nsCSSPropertySet out from nsCSSDataBlock so that it can be used elsewhere (for transitions). (Bug 435441) r=bzbarsky

This commit is contained in:
L. David Baron 2009-09-11 06:46:36 -04:00
parent 0b77a89d40
commit 7f32fb197e
3 changed files with 150 additions and 66 deletions

View File

@ -557,7 +557,6 @@ nsCSSCompressedDataBlock::CreateEmptyBlock()
nsCSSExpandedDataBlock::nsCSSExpandedDataBlock()
{
ClearSets();
AssertInitialState();
}
@ -685,14 +684,13 @@ nsCSSExpandedDataBlock::ComputeSizeResult
nsCSSExpandedDataBlock::ComputeSize()
{
ComputeSizeResult result = {0, 0};
for (PRUint32 iHigh = 0; iHigh < NS_ARRAY_LENGTH(mPropertiesSet); ++iHigh) {
if (mPropertiesSet[iHigh] == 0)
for (PRUint32 iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) {
if (!mPropertiesSet.HasPropertyInChunk(iHigh))
continue;
for (PRInt32 iLow = 0; iLow < kPropertiesSetChunkSize; ++iLow) {
if ((mPropertiesSet[iHigh] & (1 << iLow)) == 0)
for (PRInt32 iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) {
if (!mPropertiesSet.HasPropertyAt(iHigh, iLow))
continue;
nsCSSProperty iProp =
nsCSSProperty(iHigh * kPropertiesSetChunkSize + iLow);
nsCSSProperty iProp = nsCSSPropertySet::CSSPropertyAt(iHigh, iLow);
NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
"out of range");
#ifdef DEBUG
@ -737,10 +735,10 @@ nsCSSExpandedDataBlock::ComputeSize()
increment = CDBPointerStorage_advance;
} break;
}
if ((mPropertiesImportant[iHigh] & (1 << iLow)) == 0)
result.normal += increment;
else
if (mPropertiesImportant.HasPropertyAt(iHigh, iLow))
result.important += increment;
else
result.normal += increment;
}
}
return result;
@ -781,19 +779,18 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock,
* corresponding to the stored data in the expanded block, and then
* clearing the data in the expanded block.
*/
for (PRUint32 iHigh = 0; iHigh < NS_ARRAY_LENGTH(mPropertiesSet); ++iHigh) {
if (mPropertiesSet[iHigh] == 0)
for (PRUint32 iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) {
if (!mPropertiesSet.HasPropertyInChunk(iHigh))
continue;
for (PRInt32 iLow = 0; iLow < kPropertiesSetChunkSize; ++iLow) {
if ((mPropertiesSet[iHigh] & (1 << iLow)) == 0)
for (PRInt32 iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) {
if (!mPropertiesSet.HasPropertyAt(iHigh, iLow))
continue;
nsCSSProperty iProp =
nsCSSProperty(iHigh * kPropertiesSetChunkSize + iLow);
nsCSSProperty iProp = nsCSSPropertySet::CSSPropertyAt(iHigh, iLow);
NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
"out of range");
void *prop = PropertyAt(iProp);
PRBool important =
(mPropertiesImportant[iHigh] & (1 << iLow)) != 0;
mPropertiesImportant.HasPropertyAt(iHigh, iLow);
char *&cursor = important ? cursor_important : cursor_normal;
nsCSSCompressedDataBlock *result =
important ? result_important : result_normal;
@ -870,14 +867,13 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock,
void
nsCSSExpandedDataBlock::Clear()
{
for (PRUint32 iHigh = 0; iHigh < NS_ARRAY_LENGTH(mPropertiesSet); ++iHigh) {
if (mPropertiesSet[iHigh] == 0)
for (PRUint32 iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) {
if (!mPropertiesSet.HasPropertyInChunk(iHigh))
continue;
for (PRInt32 iLow = 0; iLow < kPropertiesSetChunkSize; ++iLow) {
if ((mPropertiesSet[iHigh] & (1 << iLow)) == 0)
for (PRInt32 iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) {
if (!mPropertiesSet.HasPropertyAt(iHigh, iLow))
continue;
nsCSSProperty iProp =
nsCSSProperty(iHigh * kPropertiesSetChunkSize + iLow);
nsCSSProperty iProp = nsCSSPropertySet::CSSPropertyAt(iHigh, iLow);
ClearProperty(iProp);
}
}
@ -935,15 +931,10 @@ nsCSSExpandedDataBlock::ClearProperty(nsCSSProperty aPropID)
void
nsCSSExpandedDataBlock::DoAssertInitialState()
{
PRUint32 i;
for (i = 0; i < NS_ARRAY_LENGTH(mPropertiesSet); ++i) {
NS_ASSERTION(mPropertiesSet[i] == 0, "not initial state");
}
for (i = 0; i < NS_ARRAY_LENGTH(mPropertiesImportant); ++i) {
NS_ASSERTION(mPropertiesImportant[i] == 0, "not initial state");
}
mPropertiesSet.AssertIsEmpty("not initial state");
mPropertiesImportant.AssertIsEmpty("not initial state");
for (i = 0; i < eCSSProperty_COUNT_no_shorthands; ++i) {
for (PRUint32 i = 0; i < eCSSProperty_COUNT_no_shorthands; ++i) {
void *prop = PropertyAt(nsCSSProperty(i));
switch (nsCSSProps::kTypeTable[i]) {
case eCSSType_Value: {

View File

@ -44,6 +44,7 @@
#include "nsCSSStruct.h"
#include "nsCSSProps.h"
#include "nsCSSPropertySet.h"
struct nsRuleData;
@ -257,24 +258,17 @@ private:
static const PropertyOffsetInfo kOffsetTable[];
typedef PRUint8 property_set_type;
enum { kPropertiesSetChunkSize = 8 }; // number of bits in
// |property_set_type|.
// number of |property_set_type|s in the set
enum { kPropertiesSetChunkCount =
(eCSSProperty_COUNT_no_shorthands + (kPropertiesSetChunkSize-1)) /
kPropertiesSetChunkSize };
/*
* mPropertiesSet stores a bit for every property that is present,
* to optimize compression of blocks with small numbers of
* properties (the norm) and to allow quickly checking whether a
* property is set in this block.
*/
property_set_type mPropertiesSet[kPropertiesSetChunkCount];
nsCSSPropertySet mPropertiesSet;
/*
* mPropertiesImportant indicates which properties are '!important'.
*/
property_set_type mPropertiesImportant[kPropertiesSetChunkCount];
nsCSSPropertySet mPropertiesImportant;
public:
/*
@ -307,51 +301,33 @@ public:
(cssstruct + offsets.ruledata_member_offset);
}
void AssertInSetRange(nsCSSProperty aProperty) {
NS_ASSERTION(0 <= aProperty &&
aProperty < eCSSProperty_COUNT_no_shorthands,
"out of bounds");
}
void SetPropertyBit(nsCSSProperty aProperty) {
AssertInSetRange(aProperty);
mPropertiesSet[aProperty / kPropertiesSetChunkSize] |=
property_set_type(1 << (aProperty % kPropertiesSetChunkSize));
mPropertiesSet.AddProperty(aProperty);
}
void ClearPropertyBit(nsCSSProperty aProperty) {
AssertInSetRange(aProperty);
mPropertiesSet[aProperty / kPropertiesSetChunkSize] &=
~property_set_type(1 << (aProperty % kPropertiesSetChunkSize));
mPropertiesSet.RemoveProperty(aProperty);
}
PRBool HasPropertyBit(nsCSSProperty aProperty) {
AssertInSetRange(aProperty);
return (mPropertiesSet[aProperty / kPropertiesSetChunkSize] &
(1 << (aProperty % kPropertiesSetChunkSize))) != 0;
return mPropertiesSet.HasProperty(aProperty);
}
void SetImportantBit(nsCSSProperty aProperty) {
AssertInSetRange(aProperty);
mPropertiesImportant[aProperty / kPropertiesSetChunkSize] |=
property_set_type(1 << (aProperty % kPropertiesSetChunkSize));
mPropertiesImportant.AddProperty(aProperty);
}
void ClearImportantBit(nsCSSProperty aProperty) {
AssertInSetRange(aProperty);
mPropertiesImportant[aProperty / kPropertiesSetChunkSize] &=
~property_set_type(1 << (aProperty % kPropertiesSetChunkSize));
mPropertiesImportant.RemoveProperty(aProperty);
}
PRBool HasImportantBit(nsCSSProperty aProperty) {
AssertInSetRange(aProperty);
return (mPropertiesImportant[aProperty / kPropertiesSetChunkSize] &
(1 << (aProperty % kPropertiesSetChunkSize))) != 0;
return mPropertiesImportant.HasProperty(aProperty);
}
void ClearSets() {
memset(mPropertiesSet, 0, sizeof(mPropertiesSet));
memset(mPropertiesImportant, 0, sizeof(mPropertiesImportant));
mPropertiesSet.Empty();
mPropertiesImportant.Empty();
}
};

View File

@ -0,0 +1,117 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is nsCSSDataBlock.h.
*
* The Initial Developer of the Original Code is L. David Baron.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* L. David Baron <dbaron@dbaron.org> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* bit vectors for sets of CSS properties */
#ifndef nsCSSPropertySet_h__
#define nsCSSPropertySet_h__
#include "nsCSSProperty.h"
/**
* nsCSSPropertySet maintains a set of non-shorthand CSS properties. In
* other words, for each longhand CSS property we support, it has a bit
* for whether that property is in the set.
*/
class nsCSSPropertySet {
public:
nsCSSPropertySet() { Empty(); }
// auto-generated copy-constructor OK
void AssertInSetRange(nsCSSProperty aProperty) const {
NS_ASSERTION(0 <= aProperty &&
aProperty < eCSSProperty_COUNT_no_shorthands,
"out of bounds");
}
void AddProperty(nsCSSProperty aProperty) {
AssertInSetRange(aProperty);
mProperties[aProperty / kBitsInChunk] |=
property_set_type(1 << (aProperty % kBitsInChunk));
}
void RemoveProperty(nsCSSProperty aProperty) {
AssertInSetRange(aProperty);
mProperties[aProperty / kBitsInChunk] &=
~property_set_type(1 << (aProperty % kBitsInChunk));
}
PRBool HasProperty(nsCSSProperty aProperty) const {
AssertInSetRange(aProperty);
return (mProperties[aProperty / kBitsInChunk] &
(1 << (aProperty % kBitsInChunk))) != 0;
}
void Empty() {
memset(mProperties, 0, sizeof(mProperties));
}
void AssertIsEmpty(const char* aText) const {
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mProperties); ++i) {
NS_ASSERTION(mProperties[i] == 0, aText);
}
}
private:
typedef PRUint8 property_set_type;
public:
enum { kBitsInChunk = 8 }; // number of bits in
// |property_set_type|.
// number of |property_set_type|s in the set
enum { kChunkCount =
(eCSSProperty_COUNT_no_shorthands + (kBitsInChunk-1)) /
kBitsInChunk };
/*
* For fast enumeration of all the bits that are set, callers can
* check each chunk against zero (since in normal cases few bits are
* likely to be set).
*/
PRBool HasPropertyInChunk(PRUint32 aChunk) const {
return mProperties[aChunk] != 0;
}
PRBool HasPropertyAt(PRUint32 aChunk, PRInt32 aBit) const {
return (mProperties[aChunk] & (1 << aBit)) != 0;
}
static nsCSSProperty CSSPropertyAt(PRUint32 aChunk, PRInt32 aBit) {
return nsCSSProperty(aChunk * kBitsInChunk + aBit);
}
private:
property_set_type mProperties[kChunkCount];
};
#endif /* !defined(nsCSSPropertySet_h__) */