Bug 1261754 - Part 2: Make quotes computed values shareable between different structs. r=dholbert

This commit is contained in:
Cameron McCormack 2016-04-12 15:52:40 +10:00
Родитель cde55115b7
Коммит d340c36d57
6 изменённых файлов: 119 добавлений и 116 удалений

Просмотреть файл

@ -7661,6 +7661,9 @@ nsLayoutUtils::Shutdown()
Preferences::UnregisterCallback(WebkitPrefixEnabledPrefChangeCallback,
WEBKIT_PREFIXES_ENABLED_PREF_NAME);
nsComputedDOMStyle::UnregisterPrefChangeCallbacks();
// so the cached initial quotes array doesn't appear to be a leak
nsStyleQuotes::Shutdown();
}
/* static */

Просмотреть файл

@ -37,8 +37,9 @@ nsQuoteNode::Text()
NS_ASSERTION(mType == eStyleContentType_OpenQuote ||
mType == eStyleContentType_CloseQuote,
"should only be called when mText should be non-null");
const nsStyleQuotes* styleQuotes = mPseudoFrame->StyleQuotes();
int32_t quotesCount = styleQuotes->QuotesCount(); // 0 if 'quotes:none'
const nsStyleQuoteValues::QuotePairArray& quotePairs =
mPseudoFrame->StyleQuotes()->GetQuotePairs();
int32_t quotesCount = quotePairs.Length(); // 0 if 'quotes:none'
int32_t quoteDepth = Depth();
// Reuse the last pair when the depth is greater than the number of
@ -47,15 +48,15 @@ nsQuoteNode::Text()
if (quoteDepth >= quotesCount)
quoteDepth = quotesCount - 1;
const nsString *result;
const nsString* result;
if (quoteDepth == -1) {
// close-quote from a depth of 0 or 'quotes: none' (we want a node
// with the empty string so dynamic changes are easier to handle)
result = & EmptyString();
result = &EmptyString();
} else {
result = eStyleContentType_OpenQuote == mType
? styleQuotes->OpenQuoteAt(quoteDepth)
: styleQuotes->CloseQuoteAt(quoteDepth);
? &quotePairs[quoteDepth].first
: &quotePairs[quoteDepth].second;
}
return result;
}

Просмотреть файл

@ -1471,9 +1471,9 @@ nsComputedDOMStyle::DoGetCounterReset()
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetQuotes()
{
const nsStyleQuotes *quotes = StyleQuotes();
const auto& quotePairs = StyleQuotes()->GetQuotePairs();
if (quotes->QuotesCount() == 0) {
if (quotePairs.IsEmpty()) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(eCSSKeyword_none);
return val.forget();
@ -1481,15 +1481,15 @@ nsComputedDOMStyle::DoGetQuotes()
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
for (uint32_t i = 0, i_end = quotes->QuotesCount(); i < i_end; ++i) {
for (const auto& quotePair : quotePairs) {
RefPtr<nsROCSSPrimitiveValue> openVal = new nsROCSSPrimitiveValue;
RefPtr<nsROCSSPrimitiveValue> closeVal = new nsROCSSPrimitiveValue;
nsString s;
nsStyleUtil::AppendEscapedCSSString(*quotes->OpenQuoteAt(i), s);
nsStyleUtil::AppendEscapedCSSString(quotePair.first, s);
openVal->SetString(s);
s.Truncate();
nsStyleUtil::AppendEscapedCSSString(*quotes->CloseQuoteAt(i), s);
nsStyleUtil::AppendEscapedCSSString(quotePair.second, s);
closeVal->SetString(s);
valueList->AppendCSSValue(openVal.forget());

Просмотреть файл

@ -8854,34 +8854,33 @@ nsRuleNode::ComputeQuotesData(void* aStartStruct,
case eCSSUnit_Inherit:
case eCSSUnit_Unset:
conditions.SetUncacheable();
quotes->CopyFrom(*parentQuotes);
quotes->SetQuotesInherit(parentQuotes);
break;
case eCSSUnit_Initial:
quotes->SetInitial();
quotes->SetQuotesInitial();
break;
case eCSSUnit_None:
quotes->AllocateQuotes(0);
quotes->SetQuotesNone();
break;
case eCSSUnit_PairList:
case eCSSUnit_PairListDep: {
const nsCSSValuePairList* ourQuotes
= quotesValue->GetPairListValue();
const nsCSSValuePairList* ourQuotes = quotesValue->GetPairListValue();
nsStyleQuoteValues::QuotePairArray quotePairs;
quotePairs.SetLength(ListLength(ourQuotes));
size_t index = 0;
nsAutoString buffer;
nsAutoString closeBuffer;
uint32_t count = ListLength(ourQuotes);
if (NS_FAILED(quotes->AllocateQuotes(count))) {
break;
}
count = 0;
while (ourQuotes) {
MOZ_ASSERT(ourQuotes->mXValue.GetUnit() == eCSSUnit_String &&
ourQuotes->mYValue.GetUnit() == eCSSUnit_String,
"improper list contents for quotes");
ourQuotes->mXValue.GetStringValue(buffer);
ourQuotes->mYValue.GetStringValue(closeBuffer);
quotes->SetQuotesAt(count++, buffer, closeBuffer);
quotePairs[index].first = ourQuotes->mXValue.GetStringValue(buffer);
quotePairs[index].second = ourQuotes->mYValue.GetStringValue(buffer);
++index;
ourQuotes = ourQuotes->mNext;
}
quotes->SetQuotes(Move(quotePairs));
break;
}
default:

Просмотреть файл

@ -3497,75 +3497,93 @@ nsresult nsStyleContent::AllocateContents(uint32_t aCount)
//
nsStyleQuotes::nsStyleQuotes(StyleStructContext aContext)
: mQuotesCount(0),
mQuotes(nullptr)
{
MOZ_COUNT_CTOR(nsStyleQuotes);
SetInitial();
SetQuotesInitial();
}
nsStyleQuotes::~nsStyleQuotes(void)
nsStyleQuotes::~nsStyleQuotes()
{
MOZ_COUNT_DTOR(nsStyleQuotes);
DELETE_ARRAY_IF(mQuotes);
}
nsStyleQuotes::nsStyleQuotes(const nsStyleQuotes& aSource)
: mQuotesCount(0),
mQuotes(nullptr)
: mQuotes(aSource.mQuotes)
{
MOZ_COUNT_CTOR(nsStyleQuotes);
CopyFrom(aSource);
}
void
nsStyleQuotes::SetInitial()
nsStyleQuotes::SetQuotesInherit(const nsStyleQuotes* aOther)
{
// The initial value for quotes is the en-US typographic convention:
// outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
// with LEFT and RIGHT SINGLE QUOTATION MARK.
static const char16_t initialQuotes[8] = {
0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
};
if (NS_SUCCEEDED(AllocateQuotes(2))) {
SetQuotesAt(0,
nsDependentString(&initialQuotes[0], 1),
nsDependentString(&initialQuotes[2], 1));
SetQuotesAt(1,
nsDependentString(&initialQuotes[4], 1),
nsDependentString(&initialQuotes[6], 1));
}
mQuotes = aOther->mQuotes;
}
void
nsStyleQuotes::CopyFrom(const nsStyleQuotes& aSource)
nsStyleQuotes::SetQuotesInitial()
{
if (NS_SUCCEEDED(AllocateQuotes(aSource.QuotesCount()))) {
uint32_t count = (mQuotesCount * 2);
for (uint32_t index = 0; index < count; index += 2) {
aSource.GetQuotesAt(index, mQuotes[index], mQuotes[index + 1]);
}
if (!sInitialQuotes) {
// The initial value for quotes is the en-US typographic convention:
// outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
// with LEFT and RIGHT SINGLE QUOTATION MARK.
static const char16_t initialQuotes[8] = {
0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
};
sInitialQuotes = new nsStyleQuoteValues;
sInitialQuotes->mQuotePairs.AppendElement(
std::make_pair(nsDependentString(&initialQuotes[0], 1),
nsDependentString(&initialQuotes[2], 1)));
sInitialQuotes->mQuotePairs.AppendElement(
std::make_pair(nsDependentString(&initialQuotes[4], 1),
nsDependentString(&initialQuotes[6], 1)));
}
mQuotes = sInitialQuotes;
}
nsChangeHint nsStyleQuotes::CalcDifference(const nsStyleQuotes& aOther) const
void
nsStyleQuotes::SetQuotesNone()
{
if (!sNoneQuotes) {
sNoneQuotes = new nsStyleQuoteValues;
}
mQuotes = sNoneQuotes;
}
void
nsStyleQuotes::SetQuotes(nsStyleQuoteValues::QuotePairArray&& aValues)
{
mQuotes = new nsStyleQuoteValues;
mQuotes->mQuotePairs = Move(aValues);
}
const nsStyleQuoteValues::QuotePairArray&
nsStyleQuotes::GetQuotePairs() const
{
return mQuotes->mQuotePairs;
}
nsChangeHint
nsStyleQuotes::CalcDifference(const nsStyleQuotes& aOther) const
{
// If the quotes implementation is ever going to change we might not need
// a framechange here and a reflow should be sufficient. See bug 35768.
if (mQuotesCount == aOther.mQuotesCount) {
uint32_t ix = (mQuotesCount * 2);
while (0 < ix--) {
if (mQuotes[ix] != aOther.mQuotes[ix]) {
return NS_STYLE_HINT_FRAMECHANGE;
}
}
return NS_STYLE_HINT_NONE;
if (mQuotes != aOther.mQuotes &&
mQuotes->mQuotePairs != aOther.mQuotes->mQuotePairs) {
return NS_STYLE_HINT_FRAMECHANGE;
}
return NS_STYLE_HINT_FRAMECHANGE;
return NS_STYLE_HINT_NONE;
}
StaticRefPtr<nsStyleQuoteValues>
nsStyleQuotes::sInitialQuotes;
StaticRefPtr<nsStyleQuoteValues>
nsStyleQuotes::sNoneQuotes;
// --------------------
// nsStyleTextReset
//

Просмотреть файл

@ -16,6 +16,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/CSSVariableValues.h"
#include "mozilla/SheetType.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/StyleStructContext.h"
#include "nsColor.h"
#include "nsCoord.h"
@ -33,6 +34,7 @@
#include "Orientation.h"
#include "CounterStyleManager.h"
#include <cstddef> // offsetof()
#include <utility>
class nsIFrame;
class nsIURI;
@ -2796,6 +2798,22 @@ struct nsStyleCounterData
#define DELETE_ARRAY_IF(array) if (array) { delete[] array; array = nullptr; }
/**
* An object that allows sharing of arrays that store 'quotes' property
* values. This is particularly important for inheritance, where we want
* to share the same 'quotes' value with a parent style context.
*/
class nsStyleQuoteValues
{
public:
typedef nsTArray<std::pair<nsString, nsString>> QuotePairArray;
NS_INLINE_DECL_REFCOUNTING(nsStyleQuoteValues);
QuotePairArray mQuotePairs;
private:
~nsStyleQuoteValues() {}
};
struct nsStyleQuotes
{
explicit nsStyleQuotes(StyleStructContext aContext);
@ -2812,10 +2830,6 @@ struct nsStyleQuotes
aContext->PresShell()->
FreeByObjectID(mozilla::eArenaObjectID_nsStyleQuotes, this);
}
void SetInitial();
void CopyFrom(const nsStyleQuotes& aSource);
nsChangeHint CalcDifference(const nsStyleQuotes& aOther) const;
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
@ -2828,56 +2842,24 @@ struct nsStyleQuotes
nsChangeHint_ClearAncestorIntrinsics;
}
uint32_t QuotesCount(void) const { return mQuotesCount; } // [inherited]
const nsString* OpenQuoteAt(uint32_t aIndex) const
{
NS_ASSERTION(aIndex < mQuotesCount, "out of range");
return mQuotes + (aIndex * 2);
}
const nsString* CloseQuoteAt(uint32_t aIndex) const
{
NS_ASSERTION(aIndex < mQuotesCount, "out of range");
return mQuotes + (aIndex * 2 + 1);
}
nsresult GetQuotesAt(uint32_t aIndex, nsString& aOpen, nsString& aClose) const {
if (aIndex < mQuotesCount) {
aIndex *= 2;
aOpen = mQuotes[aIndex];
aClose = mQuotes[++aIndex];
return NS_OK;
}
return NS_ERROR_ILLEGAL_VALUE;
static void Shutdown() {
sInitialQuotes = nullptr;
sNoneQuotes = nullptr;
}
nsresult AllocateQuotes(uint32_t aCount) {
if (aCount != mQuotesCount) {
DELETE_ARRAY_IF(mQuotes);
if (aCount) {
mQuotes = new nsString[aCount * 2];
if (! mQuotes) {
mQuotesCount = 0;
return NS_ERROR_OUT_OF_MEMORY;
}
}
mQuotesCount = aCount;
}
return NS_OK;
}
const nsStyleQuoteValues::QuotePairArray& GetQuotePairs() const;
nsresult SetQuotesAt(uint32_t aIndex, const nsString& aOpen, const nsString& aClose) {
if (aIndex < mQuotesCount) {
aIndex *= 2;
mQuotes[aIndex] = aOpen;
mQuotes[++aIndex] = aClose;
return NS_OK;
}
return NS_ERROR_ILLEGAL_VALUE;
}
void SetQuotesInherit(const nsStyleQuotes* aOther);
void SetQuotesInitial();
void SetQuotesNone();
void SetQuotes(nsStyleQuoteValues::QuotePairArray&& aValues);
protected:
uint32_t mQuotesCount;
nsString* mQuotes;
private:
RefPtr<nsStyleQuoteValues> mQuotes; // [inherited]
// nsStyleQuoteValues objects representing two common values, for sharing.
static mozilla::StaticRefPtr<nsStyleQuoteValues> sInitialQuotes;
static mozilla::StaticRefPtr<nsStyleQuoteValues> sNoneQuotes;
};
struct nsStyleContent