forked from mirrors/gecko-dev
Bug 1897361 - Share counter-style / list-style-type representation between Servo and Gecko. r=jwatt
It's not clear to me what is going on there or what caused it. I suspect it might be: https://searchfox.org/mozilla-central/rev/1f46481d6c16f27c989e72b898fd1fddce9f445f/servo/components/style/gecko/values.rs#69 Which is the only potential from_raw_parts caller there. But hard to say without a regression range. However I've been wanting to get rid of that code for a while, and this is a good opportunity for that. The WithCounterStyleNameOrSymbols stuff isn't super pretty, but it has only two callers, and something more complicated might require further refactoring. Differential Revision: https://phabricator.services.mozilla.com/D210814
This commit is contained in:
parent
be925b90bf
commit
f3519ac0d9
25 changed files with 426 additions and 679 deletions
|
|
@ -99,7 +99,6 @@ function checkOverridableVirtualCall(entry, location, callee)
|
|||
"Gecko_AddRefAtom",
|
||||
"Gecko_ReleaseAtom",
|
||||
/nsPrincipal::Get/,
|
||||
/CounterStylePtr::Reset/,
|
||||
];
|
||||
if (entry.matches(whitelist))
|
||||
return;
|
||||
|
|
@ -149,11 +148,6 @@ function treatAsSafeArgument(entry, varName, csuName)
|
|||
// Various Servo binding out parameters. This is a mess and there needs
|
||||
// to be a way to indicate which params are out parameters, either using
|
||||
// an attribute or a naming convention.
|
||||
["Gecko_SetCounterStyleToName", "aPtr", null],
|
||||
["Gecko_SetCounterStyleToSymbols", "aPtr", null],
|
||||
["Gecko_SetCounterStyleToString", "aPtr", null],
|
||||
["Gecko_CopyCounterStyle", "aDst", null],
|
||||
["Gecko_SetMozBinding", "aDisplay", null],
|
||||
[/ClassOrClassList/, /aClass/, null],
|
||||
["Gecko_GetAtomAsUTF16", "aLength", null],
|
||||
["Gecko_CopyMozBindingFrom", "aDest", null],
|
||||
|
|
@ -223,8 +217,6 @@ function treatAsSafeArgument(entry, varName, csuName)
|
|||
["Gecko_ClearAlternateValues", "aFont", null],
|
||||
["Gecko_AppendAlternateValues", "aFont", null],
|
||||
["Gecko_CopyAlternateValuesFrom", "aDest", null],
|
||||
["Gecko_CounterStyle_GetName", "aResult", null],
|
||||
["Gecko_CounterStyle_GetSingleString", "aResult", null],
|
||||
["Gecko_nsTArray_FontFamilyName_AppendNamed", "aNames", null],
|
||||
["Gecko_nsTArray_FontFamilyName_AppendGeneric", "aNames", null],
|
||||
];
|
||||
|
|
@ -345,12 +337,6 @@ function ignoreCallEdge(entry, callee)
|
|||
return true;
|
||||
}
|
||||
|
||||
// This function has an explicit test for being on the main thread if the
|
||||
// style has non-threadsafe refcounts, but the analysis isn't smart enough
|
||||
// to understand what the actual styles that can be involved are.
|
||||
if (/nsStyleList::SetCounterStyle/.test(callee))
|
||||
return true;
|
||||
|
||||
// CachedBorderImageData is exclusively owned by nsStyleImage, but the
|
||||
// analysis is not smart enough to know this.
|
||||
if (/CachedBorderImageData::PurgeCachedImages/.test(callee) &&
|
||||
|
|
|
|||
|
|
@ -190,28 +190,39 @@ static bool GetFirstCounterValueForScopeAndFrame(ContainStyleScope* aScope,
|
|||
|
||||
void ContainStyleScopeManager::GetSpokenCounterText(nsIFrame* aFrame,
|
||||
nsAString& aText) {
|
||||
using Tag = StyleCounterStyle::Tag;
|
||||
const auto& listStyleType = aFrame->StyleList()->mListStyleType;
|
||||
switch (listStyleType.tag) {
|
||||
case Tag::None:
|
||||
return;
|
||||
case Tag::String:
|
||||
listStyleType.AsString().AsAtom()->ToString(aText);
|
||||
return;
|
||||
case Tag::Symbols:
|
||||
case Tag::Name:
|
||||
break;
|
||||
}
|
||||
|
||||
CounterValue ordinal = 1;
|
||||
GetFirstCounterValueForScopeAndFrame(&GetRootScope(), aFrame, ordinal);
|
||||
|
||||
CounterStyle* counterStyle =
|
||||
aFrame->PresContext()->CounterStyleManager()->ResolveCounterStyle(
|
||||
aFrame->StyleList()->mCounterStyle);
|
||||
aFrame->PresContext()->CounterStyleManager()->WithCounterStyleNameOrSymbols(
|
||||
listStyleType, [&](CounterStyle* aStyle) {
|
||||
nsAutoString text;
|
||||
bool isBullet;
|
||||
counterStyle->GetSpokenCounterText(ordinal, aFrame->GetWritingMode(), text,
|
||||
aStyle->GetSpokenCounterText(ordinal, aFrame->GetWritingMode(), text,
|
||||
isBullet);
|
||||
if (isBullet) {
|
||||
aText = text;
|
||||
if (!counterStyle->IsNone()) {
|
||||
aText.Append(' ');
|
||||
}
|
||||
} else {
|
||||
counterStyle->GetPrefix(aText);
|
||||
aStyle->GetPrefix(aText);
|
||||
aText += text;
|
||||
nsAutoString suffix;
|
||||
counterStyle->GetSuffix(suffix);
|
||||
aStyle->GetSuffix(suffix);
|
||||
aText += suffix;
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1584,23 +1584,23 @@ void nsCSSFrameConstructor::CreateGeneratedContent(
|
|||
case Type::Counter:
|
||||
case Type::Counters: {
|
||||
RefPtr<nsAtom> name;
|
||||
CounterStylePtr ptr;
|
||||
const StyleCounterStyle* style;
|
||||
nsString separator;
|
||||
if (type == Type::Counter) {
|
||||
auto& counter = aItem.AsCounter();
|
||||
const auto& counter = aItem.AsCounter();
|
||||
name = counter._0.AsAtom();
|
||||
ptr = CounterStylePtr::FromStyle(counter._1);
|
||||
style = &counter._1;
|
||||
} else {
|
||||
auto& counters = aItem.AsCounters();
|
||||
const auto& counters = aItem.AsCounters();
|
||||
name = counters._0.AsAtom();
|
||||
CopyUTF8toUTF16(counters._1.AsString(), separator);
|
||||
ptr = CounterStylePtr::FromStyle(counters._2);
|
||||
style = &counters._2;
|
||||
}
|
||||
|
||||
auto* counterList = mContainStyleScopeManager.GetOrCreateCounterList(
|
||||
aOriginatingElement, name);
|
||||
auto node = MakeUnique<nsCounterUseNode>(
|
||||
std::move(ptr), std::move(separator), aContentIndex,
|
||||
*style, std::move(separator), aContentIndex,
|
||||
/* aAllCounters = */ type == Type::Counters);
|
||||
|
||||
auto initializer = MakeUnique<nsGenConInitializer>(
|
||||
|
|
@ -1747,8 +1747,6 @@ void nsCSSFrameConstructor::CreateGeneratedContent(
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void nsCSSFrameConstructor::CreateGeneratedContentFromListStyle(
|
||||
|
|
@ -1772,30 +1770,33 @@ void nsCSSFrameConstructor::CreateGeneratedContentFromListStyleType(
|
|||
nsFrameConstructorState& aState, Element& aOriginatingElement,
|
||||
const ComputedStyle& aPseudoStyle,
|
||||
const FunctionRef<void(nsIContent*)> aAddChild) {
|
||||
const nsStyleList* styleList = aPseudoStyle.StyleList();
|
||||
CounterStyle* counterStyle =
|
||||
mPresShell->GetPresContext()->CounterStyleManager()->ResolveCounterStyle(
|
||||
styleList->mCounterStyle);
|
||||
bool needUseNode = false;
|
||||
switch (counterStyle->GetStyle()) {
|
||||
case ListStyle::None:
|
||||
using Tag = StyleCounterStyle::Tag;
|
||||
const auto& styleType = aPseudoStyle.StyleList()->mListStyleType;
|
||||
switch (styleType.tag) {
|
||||
case Tag::None:
|
||||
return;
|
||||
case Tag::String: {
|
||||
nsDependentAtomString string(styleType.AsString().AsAtom());
|
||||
RefPtr<nsIContent> child = CreateGenConTextNode(aState, string, nullptr);
|
||||
aAddChild(child);
|
||||
return;
|
||||
case ListStyle::Disc:
|
||||
case ListStyle::Circle:
|
||||
case ListStyle::Square:
|
||||
case ListStyle::DisclosureClosed:
|
||||
case ListStyle::DisclosureOpen:
|
||||
break;
|
||||
default:
|
||||
const auto* anonStyle = counterStyle->AsAnonymous();
|
||||
if (!anonStyle || !anonStyle->IsSingleString()) {
|
||||
needUseNode = true;
|
||||
}
|
||||
case Tag::Name:
|
||||
case Tag::Symbols:
|
||||
break;
|
||||
}
|
||||
|
||||
auto node = MakeUnique<nsCounterUseNode>(nsCounterUseNode::ForLegacyBullet,
|
||||
styleList->mCounterStyle);
|
||||
if (!needUseNode) {
|
||||
styleType);
|
||||
if (styleType.IsName()) {
|
||||
nsAtom* name = styleType.AsName().AsAtom();
|
||||
if (name == nsGkAtoms::disc || name == nsGkAtoms::circle ||
|
||||
name == nsGkAtoms::square || name == nsGkAtoms::disclosure_closed ||
|
||||
name == nsGkAtoms::disclosure_open) {
|
||||
// We don't need a use node inserted for these.
|
||||
CounterStyle* counterStyle = mPresShell->GetPresContext()
|
||||
->CounterStyleManager()
|
||||
->ResolveCounterStyle(name);
|
||||
nsAutoString text;
|
||||
node->GetText(WritingMode(&aPseudoStyle), counterStyle, text);
|
||||
// Note that we're done with 'node' in this case. It's not inserted into
|
||||
|
|
@ -1804,6 +1805,7 @@ void nsCSSFrameConstructor::CreateGeneratedContentFromListStyleType(
|
|||
aAddChild(child);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto* counterList = mContainStyleScopeManager.GetOrCreateCounterList(
|
||||
aOriginatingElement, nsGkAtoms::list_item);
|
||||
|
|
|
|||
|
|
@ -80,10 +80,11 @@ void nsCounterChangeNode::Calc(nsCounterList* aList) {
|
|||
}
|
||||
|
||||
void nsCounterUseNode::GetText(nsString& aResult) {
|
||||
CounterStyle* style =
|
||||
mPseudoFrame->PresContext()->CounterStyleManager()->ResolveCounterStyle(
|
||||
mCounterStyle);
|
||||
GetText(mPseudoFrame->GetWritingMode(), style, aResult);
|
||||
mPseudoFrame->PresContext()
|
||||
->CounterStyleManager()
|
||||
->WithCounterStyleNameOrSymbols(mCounterStyle, [&](CounterStyle* aStyle) {
|
||||
GetText(mPseudoFrame->GetWritingMode(), aStyle, aResult);
|
||||
});
|
||||
}
|
||||
|
||||
void nsCounterUseNode::GetText(WritingMode aWM, CounterStyle* aStyle,
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ struct nsCounterNode : public nsGenConNode {
|
|||
};
|
||||
|
||||
struct nsCounterUseNode : public nsCounterNode {
|
||||
mozilla::CounterStylePtr mCounterStyle;
|
||||
mozilla::StyleCounterStyle mCounterStyle;
|
||||
nsString mSeparator;
|
||||
|
||||
// false for counter(), true for counters()
|
||||
|
|
@ -103,16 +103,18 @@ struct nsCounterUseNode : public nsCounterNode {
|
|||
bool mForLegacyBullet = false;
|
||||
|
||||
enum ForLegacyBullet { ForLegacyBullet };
|
||||
nsCounterUseNode(enum ForLegacyBullet, mozilla::CounterStylePtr aCounterStyle)
|
||||
nsCounterUseNode(enum ForLegacyBullet,
|
||||
const mozilla::StyleCounterStyle& aCounterStyle)
|
||||
: nsCounterNode(0, USE),
|
||||
mCounterStyle(std::move(aCounterStyle)),
|
||||
mCounterStyle(aCounterStyle),
|
||||
mForLegacyBullet(true) {}
|
||||
|
||||
// args go directly to member variables here and of nsGenConNode
|
||||
nsCounterUseNode(mozilla::CounterStylePtr aCounterStyle, nsString aSeparator,
|
||||
uint32_t aContentIndex, bool aAllCounters)
|
||||
nsCounterUseNode(const mozilla::StyleCounterStyle& aCounterStyle,
|
||||
nsString aSeparator, uint32_t aContentIndex,
|
||||
bool aAllCounters)
|
||||
: nsCounterNode(aContentIndex, USE),
|
||||
mCounterStyle(std::move(aCounterStyle)),
|
||||
mCounterStyle(aCounterStyle),
|
||||
mSeparator(std::move(aSeparator)),
|
||||
mAllCounters(aAllCounters) {
|
||||
NS_ASSERTION(aContentIndex <= INT32_MAX, "out of range");
|
||||
|
|
|
|||
|
|
@ -70,22 +70,24 @@ static nscoord FontSizeInflationListMarginAdjustment(const nsIFrame* aFrame) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
const auto* list = aFrame->StyleList();
|
||||
if (!list->mListStyleType.IsNone()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The HTML spec states that the default padding for ordered lists
|
||||
// begins at 40px, indicating that we have 40px of space to place a
|
||||
// bullet. When performing font inflation calculations, we add space
|
||||
// equivalent to this, but simply inflated at the same amount as the
|
||||
// text, in app units.
|
||||
auto margin = nsPresContext::CSSPixelsToAppUnits(40) * (inflation - 1);
|
||||
|
||||
auto* list = aFrame->StyleList();
|
||||
if (!list->mCounterStyle.IsAtom()) {
|
||||
if (!list->mListStyleType.IsName()) {
|
||||
return margin;
|
||||
}
|
||||
|
||||
nsAtom* type = list->mCounterStyle.AsAtom();
|
||||
if (type != nsGkAtoms::none && type != nsGkAtoms::disc &&
|
||||
type != nsGkAtoms::circle && type != nsGkAtoms::square &&
|
||||
type != nsGkAtoms::disclosure_closed &&
|
||||
nsAtom* type = list->mListStyleType.AsName().AsAtom();
|
||||
if (type != nsGkAtoms::disc && type != nsGkAtoms::circle &&
|
||||
type != nsGkAtoms::square && type != nsGkAtoms::disclosure_closed &&
|
||||
type != nsGkAtoms::disclosure_open) {
|
||||
return margin;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7980,7 +7980,7 @@ bool nsBlockFrame::MarkerIsEmpty() const {
|
|||
nsIFrame* marker = GetMarker();
|
||||
const nsStyleList* list = marker->StyleList();
|
||||
return marker->StyleContent()->mContent.IsNone() ||
|
||||
(list->mCounterStyle.IsNone() && list->mListStyleImage.IsNone() &&
|
||||
(list->mListStyleType.IsNone() && list->mListStyleImage.IsNone() &&
|
||||
marker->StyleContent()->NonAltContentItems().IsEmpty());
|
||||
}
|
||||
|
||||
|
|
@ -8657,13 +8657,11 @@ void nsBlockFrame::VerifyOverflowSituation() {
|
|||
}
|
||||
LineIterator line = flow->LinesBegin();
|
||||
LineIterator line_end = flow->LinesEnd();
|
||||
for (; line != line_end && line != cursor; ++line)
|
||||
;
|
||||
for (; line != line_end && line != cursor; ++line);
|
||||
if (line == line_end && overflowLines) {
|
||||
line = overflowLines->mLines.begin();
|
||||
line_end = overflowLines->mLines.end();
|
||||
for (; line != line_end && line != cursor; ++line)
|
||||
;
|
||||
for (; line != line_end && line != cursor; ++line);
|
||||
}
|
||||
return line != line_end;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -47,29 +47,44 @@ struct PadType {
|
|||
// points outside the BMP will need 2 16-bit units.
|
||||
#define LENGTH_LIMIT 150
|
||||
|
||||
static void SymbolToString(const StyleSymbol& aSymbol, nsAString& aResult) {
|
||||
if (aSymbol.IsIdent()) {
|
||||
return aSymbol.AsIdent().AsAtom()->ToString(aResult);
|
||||
}
|
||||
MOZ_ASSERT(aSymbol.IsString());
|
||||
return CopyUTF8toUTF16(aSymbol.AsString().AsString(), aResult);
|
||||
}
|
||||
|
||||
static size_t SymbolLength(const StyleSymbol& aSymbol) {
|
||||
if (aSymbol.IsIdent()) {
|
||||
return aSymbol.AsIdent().AsAtom()->GetLength();
|
||||
}
|
||||
MOZ_ASSERT(aSymbol.IsString());
|
||||
return aSymbol.AsString().AsString().Length();
|
||||
}
|
||||
|
||||
static bool GetCyclicCounterText(CounterValue aOrdinal, nsAString& aResult,
|
||||
Span<const nsString> aSymbols) {
|
||||
Span<const StyleSymbol> aSymbols) {
|
||||
MOZ_ASSERT(aSymbols.Length() >= 1, "No symbol available for cyclic counter.");
|
||||
auto n = CounterValue(aSymbols.Length());
|
||||
CounterValue index = (aOrdinal - 1) % n;
|
||||
aResult = aSymbols[index >= 0 ? index : index + n];
|
||||
SymbolToString(aSymbols[index >= 0 ? index : index + n], aResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetFixedCounterText(CounterValue aOrdinal, nsAString& aResult,
|
||||
CounterValue aStart,
|
||||
Span<const nsString> aSymbols) {
|
||||
Span<const StyleSymbol> aSymbols) {
|
||||
CounterValue index = aOrdinal - aStart;
|
||||
if (index >= 0 && index < CounterValue(aSymbols.Length())) {
|
||||
aResult = aSymbols[index];
|
||||
SymbolToString(aSymbols[index], aResult);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool GetSymbolicCounterText(CounterValue aOrdinal, nsAString& aResult,
|
||||
Span<const nsString> aSymbols) {
|
||||
Span<const StyleSymbol> aSymbols) {
|
||||
MOZ_ASSERT(aSymbols.Length() >= 1,
|
||||
"No symbol available for symbolic counter.");
|
||||
MOZ_ASSERT(aOrdinal >= 0, "Invalid ordinal.");
|
||||
|
|
@ -79,23 +94,25 @@ static bool GetSymbolicCounterText(CounterValue aOrdinal, nsAString& aResult,
|
|||
|
||||
aResult.Truncate();
|
||||
auto n = aSymbols.Length();
|
||||
const nsString& symbol = aSymbols[(aOrdinal - 1) % n];
|
||||
const StyleSymbol& symbol = aSymbols[(aOrdinal - 1) % n];
|
||||
size_t len = (aOrdinal + n - 1) / n;
|
||||
auto symbolLength = symbol.Length();
|
||||
auto symbolLength = SymbolLength(symbol);
|
||||
if (symbolLength > 0) {
|
||||
if (len > LENGTH_LIMIT || symbolLength > LENGTH_LIMIT ||
|
||||
len * symbolLength > LENGTH_LIMIT) {
|
||||
return false;
|
||||
}
|
||||
nsAutoString str;
|
||||
SymbolToString(symbol, str);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
aResult.Append(symbol);
|
||||
aResult.Append(str);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetAlphabeticCounterText(CounterValue aOrdinal, nsAString& aResult,
|
||||
Span<const nsString> aSymbols) {
|
||||
Span<const StyleSymbol> aSymbols) {
|
||||
MOZ_ASSERT(aSymbols.Length() >= 2, "Too few symbols for alphabetic counter.");
|
||||
MOZ_ASSERT(aOrdinal >= 0, "Invalid ordinal.");
|
||||
if (aOrdinal == 0) {
|
||||
|
|
@ -115,18 +132,23 @@ static bool GetAlphabeticCounterText(CounterValue aOrdinal, nsAString& aResult,
|
|||
|
||||
aResult.Truncate();
|
||||
for (auto i = indexes.Length(); i > 0; --i) {
|
||||
aResult.Append(aSymbols[indexes[i - 1]]);
|
||||
const auto& symbol = aSymbols[indexes[i - 1]];
|
||||
if (symbol.IsIdent()) {
|
||||
aResult.Append(nsDependentAtomString(symbol.AsIdent().AsAtom()));
|
||||
} else {
|
||||
AppendUTF8toUTF16(symbol.AsString().AsString(), aResult);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetNumericCounterText(CounterValue aOrdinal, nsAString& aResult,
|
||||
Span<const nsString> aSymbols) {
|
||||
Span<const StyleSymbol> aSymbols) {
|
||||
MOZ_ASSERT(aSymbols.Length() >= 2, "Too few symbols for numeric counter.");
|
||||
MOZ_ASSERT(aOrdinal >= 0, "Invalid ordinal.");
|
||||
|
||||
if (aOrdinal == 0) {
|
||||
aResult = aSymbols[0];
|
||||
SymbolToString(aSymbols[0], aResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +161,12 @@ static bool GetNumericCounterText(CounterValue aOrdinal, nsAString& aResult,
|
|||
|
||||
aResult.Truncate();
|
||||
for (auto i = indexes.Length(); i > 0; --i) {
|
||||
aResult.Append(aSymbols[indexes[i - 1]]);
|
||||
const auto& symbol = aSymbols[indexes[i - 1]];
|
||||
if (symbol.IsIdent()) {
|
||||
aResult.Append(nsDependentAtomString(symbol.AsIdent().AsAtom()));
|
||||
} else {
|
||||
AppendUTF8toUTF16(symbol.AsString().AsString(), aResult);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -515,24 +542,21 @@ class BuiltinCounterStyle : public CounterStyle {
|
|||
|
||||
nsStaticAtom* GetStyleName() const { return mName; }
|
||||
|
||||
virtual void GetPrefix(nsAString& aResult) override;
|
||||
virtual void GetSuffix(nsAString& aResult) override;
|
||||
virtual void GetSpokenCounterText(CounterValue aOrdinal,
|
||||
WritingMode aWritingMode,
|
||||
nsAString& aResult,
|
||||
bool& aIsBullet) override;
|
||||
virtual bool IsBullet() override;
|
||||
void GetPrefix(nsAString& aResult) override;
|
||||
void GetSuffix(nsAString& aResult) override;
|
||||
void GetSpokenCounterText(CounterValue aOrdinal, WritingMode aWritingMode,
|
||||
nsAString& aResult, bool& aIsBullet) override;
|
||||
bool IsBullet() override;
|
||||
|
||||
virtual void GetNegative(NegativeType& aResult) override;
|
||||
virtual bool IsOrdinalInRange(CounterValue aOrdinal) override;
|
||||
virtual bool IsOrdinalInAutoRange(CounterValue aOrdinal) override;
|
||||
virtual void GetPad(PadType& aResult) override;
|
||||
virtual CounterStyle* GetFallback() override;
|
||||
virtual SpeakAs GetSpeakAs() override;
|
||||
virtual bool UseNegativeSign() override;
|
||||
void GetNegative(NegativeType& aResult) override;
|
||||
bool IsOrdinalInRange(CounterValue aOrdinal) override;
|
||||
bool IsOrdinalInAutoRange(CounterValue aOrdinal) override;
|
||||
void GetPad(PadType& aResult) override;
|
||||
CounterStyle* GetFallback() override;
|
||||
SpeakAs GetSpeakAs() override;
|
||||
bool UseNegativeSign() override;
|
||||
|
||||
virtual bool GetInitialCounterText(CounterValue aOrdinal,
|
||||
WritingMode aWritingMode,
|
||||
bool GetInitialCounterText(CounterValue aOrdinal, WritingMode aWritingMode,
|
||||
nsAString& aResult, bool& aIsRTL) override;
|
||||
|
||||
protected:
|
||||
|
|
@ -953,27 +977,23 @@ class CustomCounterStyle final : public CounterStyle {
|
|||
const StyleLockedCounterStyleRule* GetRule() const { return mRule; }
|
||||
uint32_t GetRuleGeneration() const { return mRuleGeneration; }
|
||||
|
||||
virtual void GetPrefix(nsAString& aResult) override;
|
||||
virtual void GetSuffix(nsAString& aResult) override;
|
||||
virtual void GetSpokenCounterText(CounterValue aOrdinal,
|
||||
WritingMode aWritingMode,
|
||||
nsAString& aResult,
|
||||
bool& aIsBullet) override;
|
||||
virtual bool IsBullet() override;
|
||||
void GetPrefix(nsAString& aResult) override;
|
||||
void GetSuffix(nsAString& aResult) override;
|
||||
void GetSpokenCounterText(CounterValue aOrdinal, WritingMode aWritingMode,
|
||||
nsAString& aResult, bool& aIsBullet) override;
|
||||
bool IsBullet() override;
|
||||
|
||||
virtual void GetNegative(NegativeType& aResult) override;
|
||||
virtual bool IsOrdinalInRange(CounterValue aOrdinal) override;
|
||||
virtual bool IsOrdinalInAutoRange(CounterValue aOrdinal) override;
|
||||
virtual void GetPad(PadType& aResult) override;
|
||||
virtual CounterStyle* GetFallback() override;
|
||||
virtual SpeakAs GetSpeakAs() override;
|
||||
virtual bool UseNegativeSign() override;
|
||||
void GetNegative(NegativeType& aResult) override;
|
||||
bool IsOrdinalInRange(CounterValue aOrdinal) override;
|
||||
bool IsOrdinalInAutoRange(CounterValue aOrdinal) override;
|
||||
void GetPad(PadType& aResult) override;
|
||||
CounterStyle* GetFallback() override;
|
||||
SpeakAs GetSpeakAs() override;
|
||||
bool UseNegativeSign() override;
|
||||
|
||||
virtual void CallFallbackStyle(CounterValue aOrdinal,
|
||||
WritingMode aWritingMode, nsAString& aResult,
|
||||
bool& aIsRTL) override;
|
||||
virtual bool GetInitialCounterText(CounterValue aOrdinal,
|
||||
WritingMode aWritingMode,
|
||||
void CallFallbackStyle(CounterValue aOrdinal, WritingMode aWritingMode,
|
||||
nsAString& aResult, bool& aIsRTL) override;
|
||||
bool GetInitialCounterText(CounterValue aOrdinal, WritingMode aWritingMode,
|
||||
nsAString& aResult, bool& aIsRTL) override;
|
||||
|
||||
bool IsExtendsSystem() { return mSystem == StyleCounterSystem::Extends; }
|
||||
|
|
@ -992,7 +1012,7 @@ class CustomCounterStyle final : public CounterStyle {
|
|||
private:
|
||||
~CustomCounterStyle() = default;
|
||||
|
||||
Span<const nsString> GetSymbols();
|
||||
Span<const StyleSymbol> GetSymbols();
|
||||
Span<const AdditiveSymbol> GetAdditiveSymbols();
|
||||
|
||||
// The speak-as values of counter styles may form a loop, and the
|
||||
|
|
@ -1039,7 +1059,6 @@ class CustomCounterStyle final : public CounterStyle {
|
|||
uint16_t mFlags;
|
||||
|
||||
// Fields below will be initialized when necessary.
|
||||
StyleOwnedSlice<nsString> mSymbols;
|
||||
StyleOwnedSlice<AdditiveSymbol> mAdditiveSymbols;
|
||||
NegativeType mNegative;
|
||||
nsString mPrefix, mSuffix;
|
||||
|
|
@ -1068,7 +1087,6 @@ class CustomCounterStyle final : public CounterStyle {
|
|||
};
|
||||
|
||||
void CustomCounterStyle::ResetCachedData() {
|
||||
mSymbols.Clear();
|
||||
mAdditiveSymbols.Clear();
|
||||
mFlags &= ~(FLAG_NEGATIVE_INITED | FLAG_PREFIX_INITED | FLAG_SUFFIX_INITED |
|
||||
FLAG_PAD_INITED | FLAG_SPEAKAS_INITED);
|
||||
|
|
@ -1296,11 +1314,10 @@ bool CustomCounterStyle::GetInitialCounterText(CounterValue aOrdinal,
|
|||
}
|
||||
}
|
||||
|
||||
Span<const nsString> CustomCounterStyle::GetSymbols() {
|
||||
if (mSymbols.IsEmpty()) {
|
||||
Servo_CounterStyleRule_GetSymbols(mRule, &mSymbols);
|
||||
}
|
||||
return mSymbols.AsSpan();
|
||||
Span<const StyleSymbol> CustomCounterStyle::GetSymbols() {
|
||||
size_t count = 0;
|
||||
const StyleSymbol* ptr = Servo_CounterStyleRule_GetSymbols(mRule, &count);
|
||||
return Span(ptr, count);
|
||||
}
|
||||
|
||||
Span<const AdditiveSymbol> CustomCounterStyle::GetAdditiveSymbols() {
|
||||
|
|
@ -1504,20 +1521,11 @@ CounterStyle* CustomCounterStyle::GetExtendsRoot() {
|
|||
return mExtendsRoot;
|
||||
}
|
||||
|
||||
AnonymousCounterStyle::AnonymousCounterStyle(const nsAString& aContent)
|
||||
: CounterStyle(ListStyle::Custom),
|
||||
mSingleString(true),
|
||||
mSymbolsType(StyleSymbolsType::Cyclic) {
|
||||
mSymbols.SetCapacity(1);
|
||||
mSymbols.AppendElement(aContent);
|
||||
}
|
||||
|
||||
AnonymousCounterStyle::AnonymousCounterStyle(StyleSymbolsType aType,
|
||||
nsTArray<nsString> aSymbols)
|
||||
Span<const StyleSymbol> aSymbols)
|
||||
: CounterStyle(ListStyle::Custom),
|
||||
mSingleString(false),
|
||||
mSymbolsType(aType),
|
||||
mSymbols(std::move(aSymbols)) {}
|
||||
mSymbols(aSymbols) {}
|
||||
|
||||
/* virtual */
|
||||
void AnonymousCounterStyle::GetPrefix(nsAString& aResult) {
|
||||
|
|
@ -1525,13 +1533,7 @@ void AnonymousCounterStyle::GetPrefix(nsAString& aResult) {
|
|||
}
|
||||
|
||||
/* virtual */
|
||||
void AnonymousCounterStyle::GetSuffix(nsAString& aResult) {
|
||||
if (IsSingleString()) {
|
||||
aResult.Truncate();
|
||||
} else {
|
||||
aResult = ' ';
|
||||
}
|
||||
}
|
||||
void AnonymousCounterStyle::GetSuffix(nsAString& aResult) { aResult = ' '; }
|
||||
|
||||
/* virtual */
|
||||
bool AnonymousCounterStyle::IsBullet() {
|
||||
|
|
|
|||
|
|
@ -97,195 +97,36 @@ class CounterStyle {
|
|||
const ListStyle mStyle;
|
||||
};
|
||||
|
||||
class AnonymousCounterStyle final : public CounterStyle {
|
||||
class MOZ_STACK_CLASS AnonymousCounterStyle final : public CounterStyle {
|
||||
public:
|
||||
explicit AnonymousCounterStyle(const nsAString& aContent);
|
||||
AnonymousCounterStyle(StyleSymbolsType, nsTArray<nsString> aSymbols);
|
||||
AnonymousCounterStyle(StyleSymbolsType, Span<const StyleSymbol> aSymbols);
|
||||
|
||||
virtual void GetPrefix(nsAString& aResult) override;
|
||||
virtual void GetSuffix(nsAString& aResult) override;
|
||||
virtual bool IsBullet() override;
|
||||
void GetPrefix(nsAString& aResult) override;
|
||||
void GetSuffix(nsAString& aResult) override;
|
||||
bool IsBullet() override;
|
||||
|
||||
virtual void GetNegative(NegativeType& aResult) override;
|
||||
virtual bool IsOrdinalInRange(CounterValue aOrdinal) override;
|
||||
virtual bool IsOrdinalInAutoRange(CounterValue aOrdinal) override;
|
||||
virtual void GetPad(PadType& aResult) override;
|
||||
virtual CounterStyle* GetFallback() override;
|
||||
virtual SpeakAs GetSpeakAs() override;
|
||||
virtual bool UseNegativeSign() override;
|
||||
void GetNegative(NegativeType& aResult) override;
|
||||
bool IsOrdinalInRange(CounterValue aOrdinal) override;
|
||||
bool IsOrdinalInAutoRange(CounterValue aOrdinal) override;
|
||||
void GetPad(PadType& aResult) override;
|
||||
CounterStyle* GetFallback() override;
|
||||
SpeakAs GetSpeakAs() override;
|
||||
bool UseNegativeSign() override;
|
||||
|
||||
virtual bool GetInitialCounterText(CounterValue aOrdinal,
|
||||
WritingMode aWritingMode,
|
||||
bool GetInitialCounterText(CounterValue aOrdinal, WritingMode aWritingMode,
|
||||
nsAString& aResult, bool& aIsRTL) override;
|
||||
|
||||
virtual AnonymousCounterStyle* AsAnonymous() override { return this; }
|
||||
AnonymousCounterStyle* AsAnonymous() override { return this; }
|
||||
|
||||
bool IsSingleString() const { return mSingleString; }
|
||||
auto GetSymbols() const { return Span<const nsString>{mSymbols}; }
|
||||
auto GetSymbols() const { return mSymbols; }
|
||||
|
||||
StyleCounterSystem GetSystem() const;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnonymousCounterStyle)
|
||||
|
||||
private:
|
||||
~AnonymousCounterStyle() = default;
|
||||
|
||||
bool mSingleString;
|
||||
StyleSymbolsType mSymbolsType;
|
||||
nsTArray<nsString> mSymbols;
|
||||
};
|
||||
|
||||
// A smart pointer to CounterStyle. It either owns a reference to an
|
||||
// anonymous counter style, or weakly refers to a named counter style
|
||||
// managed by counter style manager.
|
||||
class CounterStylePtr {
|
||||
public:
|
||||
CounterStylePtr() : mRaw(0) {}
|
||||
CounterStylePtr(const CounterStylePtr& aOther) : mRaw(aOther.mRaw) {
|
||||
if (!mRaw) {
|
||||
return;
|
||||
}
|
||||
switch (GetType()) {
|
||||
case eAnonymousCounterStyle:
|
||||
AsAnonymous()->AddRef();
|
||||
break;
|
||||
case eAtom:
|
||||
AsAtom()->AddRef();
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
CounterStylePtr(CounterStylePtr&& aOther) : mRaw(aOther.mRaw) {
|
||||
aOther.mRaw = 0;
|
||||
}
|
||||
~CounterStylePtr() { Reset(); }
|
||||
|
||||
CounterStylePtr& operator=(const CounterStylePtr& aOther) {
|
||||
if (this != &aOther) {
|
||||
Reset();
|
||||
new (this) CounterStylePtr(aOther);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
CounterStylePtr& operator=(CounterStylePtr&& aOther) {
|
||||
if (this != &aOther) {
|
||||
Reset();
|
||||
mRaw = aOther.mRaw;
|
||||
aOther.mRaw = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
CounterStylePtr& operator=(decltype(nullptr)) {
|
||||
Reset();
|
||||
return *this;
|
||||
}
|
||||
CounterStylePtr& operator=(nsStaticAtom* aStaticAtom) {
|
||||
Reset();
|
||||
mRaw = reinterpret_cast<uintptr_t>(aStaticAtom) | eAtom;
|
||||
return *this;
|
||||
}
|
||||
CounterStylePtr& operator=(already_AddRefed<nsAtom> aAtom) {
|
||||
Reset();
|
||||
mRaw = reinterpret_cast<uintptr_t>(aAtom.take()) | eAtom;
|
||||
return *this;
|
||||
}
|
||||
CounterStylePtr& operator=(AnonymousCounterStyle* aCounterStyle) {
|
||||
Reset();
|
||||
if (aCounterStyle) {
|
||||
CounterStyle* raw = do_AddRef(aCounterStyle).take();
|
||||
mRaw = reinterpret_cast<uintptr_t>(raw) | eAnonymousCounterStyle;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO(emilio): Make CounterStyle have a single representation, either by
|
||||
// removing CounterStylePtr or by moving this representation to Rust.
|
||||
static CounterStylePtr FromStyle(const StyleCounterStyle& aStyle) {
|
||||
CounterStylePtr ret;
|
||||
if (aStyle.IsName()) {
|
||||
ret = do_AddRef(aStyle.AsName().AsAtom());
|
||||
} else {
|
||||
StyleSymbolsType type = aStyle.AsSymbols()._0;
|
||||
Span<const StyleSymbol> symbols = aStyle.AsSymbols()._1._0.AsSpan();
|
||||
nsTArray<nsString> transcoded(symbols.Length());
|
||||
for (const auto& symbol : symbols) {
|
||||
MOZ_ASSERT(symbol.IsString(), "Should not have <ident> in symbols()");
|
||||
transcoded.AppendElement(
|
||||
NS_ConvertUTF8toUTF16(symbol.AsString().AsString()));
|
||||
}
|
||||
ret = new AnonymousCounterStyle(type, std::move(transcoded));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return !!mRaw; }
|
||||
bool operator!() const { return !mRaw; }
|
||||
bool operator==(const CounterStylePtr& aOther) const {
|
||||
// FIXME(emilio): For atoms this is all right, but for symbols doesn't this
|
||||
// cause us to compare as unequal all the time, even if the specified
|
||||
// symbols didn't change?
|
||||
return mRaw == aOther.mRaw;
|
||||
}
|
||||
bool operator!=(const CounterStylePtr& aOther) const {
|
||||
return mRaw != aOther.mRaw;
|
||||
}
|
||||
|
||||
nsAtom* AsAtom() const {
|
||||
MOZ_ASSERT(IsAtom());
|
||||
return reinterpret_cast<nsAtom*>(mRaw & ~eMask);
|
||||
}
|
||||
AnonymousCounterStyle* AsAnonymous() const {
|
||||
MOZ_ASSERT(IsAnonymous());
|
||||
return static_cast<AnonymousCounterStyle*>(
|
||||
reinterpret_cast<CounterStyle*>(mRaw & ~eMask));
|
||||
}
|
||||
|
||||
bool IsAtom() const { return GetType() == eAtom; }
|
||||
bool IsAnonymous() const { return GetType() == eAnonymousCounterStyle; }
|
||||
|
||||
bool IsNone() const { return IsAtom() && AsAtom() == nsGkAtoms::none; }
|
||||
|
||||
private:
|
||||
enum Type : uintptr_t {
|
||||
eAnonymousCounterStyle = 0,
|
||||
eAtom = 1,
|
||||
eMask = 1,
|
||||
};
|
||||
|
||||
static_assert(alignof(CounterStyle) >= 1 << eMask,
|
||||
"We're gonna tag the pointer, so it better fit");
|
||||
static_assert(alignof(nsAtom) >= 1 << eMask,
|
||||
"We're gonna tag the pointer, so it better fit");
|
||||
|
||||
Type GetType() const { return static_cast<Type>(mRaw & eMask); }
|
||||
|
||||
void Reset() {
|
||||
if (!mRaw) {
|
||||
return;
|
||||
}
|
||||
switch (GetType()) {
|
||||
case eAnonymousCounterStyle:
|
||||
AsAnonymous()->Release();
|
||||
break;
|
||||
case eAtom:
|
||||
AsAtom()->Release();
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown type");
|
||||
break;
|
||||
}
|
||||
mRaw = 0;
|
||||
}
|
||||
|
||||
// mRaw contains the pointer, and its last bit is used to store the type of
|
||||
// the pointer.
|
||||
// If the type is eAtom, the pointer owns a reference to an nsAtom
|
||||
// (potentially null).
|
||||
// If the type is eAnonymousCounterStyle, it owns a reference to an
|
||||
// anonymous counter style (never null).
|
||||
uintptr_t mRaw;
|
||||
Span<const StyleSymbol> mSymbols;
|
||||
};
|
||||
|
||||
class CounterStyleManager final {
|
||||
|
|
@ -310,11 +151,23 @@ class CounterStyleManager final {
|
|||
// Same as GetCounterStyle but try to build the counter style object
|
||||
// rather than returning nullptr if that hasn't been built.
|
||||
CounterStyle* ResolveCounterStyle(nsAtom* aName);
|
||||
CounterStyle* ResolveCounterStyle(const CounterStylePtr& aPtr) {
|
||||
if (aPtr.IsAtom()) {
|
||||
return ResolveCounterStyle(aPtr.AsAtom());
|
||||
template <typename F>
|
||||
void WithCounterStyleNameOrSymbols(const StyleCounterStyle& aStyle,
|
||||
F&& aCallback) {
|
||||
using Tag = StyleCounterStyle::Tag;
|
||||
switch (aStyle.tag) {
|
||||
case Tag::None:
|
||||
case Tag::String:
|
||||
MOZ_CRASH("Unexpected counter style");
|
||||
case Tag::Symbols: {
|
||||
AnonymousCounterStyle s(aStyle.AsSymbols().ty,
|
||||
aStyle.AsSymbols().symbols._0.AsSpan());
|
||||
return aCallback(&s);
|
||||
}
|
||||
case Tag::Name: {
|
||||
return aCallback(ResolveCounterStyle(aStyle.AsName().AsAtom()));
|
||||
}
|
||||
}
|
||||
return aPtr.AsAnonymous();
|
||||
}
|
||||
|
||||
static CounterStyle* GetBuiltinStyle(ListStyle aStyle);
|
||||
|
|
|
|||
|
|
@ -960,34 +960,6 @@ void Gecko_SetFontPaletteOverride(
|
|||
uint32_t(aIndex), gfx::sRGBColor::FromABGR(aColor->ToColor())});
|
||||
}
|
||||
|
||||
void Gecko_CounterStyle_ToPtr(const StyleCounterStyle* aStyle,
|
||||
CounterStylePtr* aPtr) {
|
||||
*aPtr = CounterStylePtr::FromStyle(*aStyle);
|
||||
}
|
||||
|
||||
void Gecko_SetCounterStyleToNone(CounterStylePtr* aPtr) {
|
||||
*aPtr = nsGkAtoms::none;
|
||||
}
|
||||
|
||||
void Gecko_SetCounterStyleToString(CounterStylePtr* aPtr,
|
||||
const nsACString* aSymbol) {
|
||||
*aPtr = new AnonymousCounterStyle(NS_ConvertUTF8toUTF16(*aSymbol));
|
||||
}
|
||||
|
||||
void Gecko_CopyCounterStyle(CounterStylePtr* aDst,
|
||||
const CounterStylePtr* aSrc) {
|
||||
*aDst = *aSrc;
|
||||
}
|
||||
|
||||
nsAtom* Gecko_CounterStyle_GetName(const CounterStylePtr* aPtr) {
|
||||
return aPtr->IsAtom() ? aPtr->AsAtom() : nullptr;
|
||||
}
|
||||
|
||||
const AnonymousCounterStyle* Gecko_CounterStyle_GetAnonymous(
|
||||
const CounterStylePtr* aPtr) {
|
||||
return aPtr->AsAnonymous();
|
||||
}
|
||||
|
||||
void Gecko_EnsureImageLayersLength(nsStyleImageLayers* aLayers, size_t aLen,
|
||||
nsStyleImageLayers::LayerType aLayerType) {
|
||||
size_t oldLength = aLayers->mLayers.Length();
|
||||
|
|
|
|||
|
|
@ -315,23 +315,6 @@ void Gecko_SetImageOrientationAsFromImage(nsStyleVisibility* aVisibility);
|
|||
void Gecko_CopyImageOrientationFrom(nsStyleVisibility* aDst,
|
||||
const nsStyleVisibility* aSrc);
|
||||
|
||||
// Counter style.
|
||||
void Gecko_CounterStyle_ToPtr(const mozilla::StyleCounterStyle*,
|
||||
mozilla::CounterStylePtr*);
|
||||
|
||||
void Gecko_SetCounterStyleToNone(mozilla::CounterStylePtr*);
|
||||
|
||||
void Gecko_SetCounterStyleToString(mozilla::CounterStylePtr* ptr,
|
||||
const nsACString* symbol);
|
||||
|
||||
void Gecko_CopyCounterStyle(mozilla::CounterStylePtr* dst,
|
||||
const mozilla::CounterStylePtr* src);
|
||||
|
||||
nsAtom* Gecko_CounterStyle_GetName(const mozilla::CounterStylePtr* ptr);
|
||||
|
||||
const mozilla::AnonymousCounterStyle* Gecko_CounterStyle_GetAnonymous(
|
||||
const mozilla::CounterStylePtr* ptr);
|
||||
|
||||
// list-style-image style.
|
||||
void Gecko_SetListStyleImageNone(nsStyleList* style_struct);
|
||||
|
||||
|
|
|
|||
|
|
@ -206,7 +206,6 @@ allowlist-types = [
|
|||
"mozilla::DeclarationBlockMutationClosure",
|
||||
"mozilla::AnimatedPropertyID",
|
||||
"mozilla::AnimationPropertySegment",
|
||||
"mozilla::AnonymousCounterStyle",
|
||||
"mozilla::AtomArray",
|
||||
"mozilla::ComputedTiming",
|
||||
"mozilla::Matrix4x4Components",
|
||||
|
|
@ -566,8 +565,8 @@ cbindgen-types = [
|
|||
{ gecko = "StyleCounterSet", servo = "crate::values::computed::CounterSet" },
|
||||
{ gecko = "StyleCounterIncrement", servo = "crate::values::computed::CounterIncrement" },
|
||||
{ gecko = "StyleContent", servo = "crate::values::computed::counters::Content" },
|
||||
{ gecko = "StyleSymbolsType", servo = "crate::values::generics::SymbolsType" },
|
||||
{ gecko = "StyleCounterStyle", servo = "crate::values::generics::CounterStyle" },
|
||||
{ gecko = "StyleSymbolsType", servo = "crate::counter_style::SymbolsType" },
|
||||
{ gecko = "StyleCounterStyle", servo = "crate::counter_style::CounterStyle" },
|
||||
{ gecko = "StyleComputedJustifyItems", servo = "crate::values::computed::align::ComputedJustifyItems" },
|
||||
{ gecko = "StyleAlignItems", servo = "crate::values::computed::AlignItems" },
|
||||
{ gecko = "StyleJustifySelf", servo = "crate::values::computed::JustifySelf" },
|
||||
|
|
@ -619,6 +618,7 @@ cbindgen-types = [
|
|||
{ gecko = "StyleLockedImportRule", servo = "crate::gecko::arc_types::LockedImportRule" },
|
||||
{ gecko = "StyleLockedFontFaceRule", servo = "crate::gecko::arc_types::LockedFontFaceRule" },
|
||||
{ gecko = "StyleBaselineSource", servo = "crate::values::computed::BaselineSource" },
|
||||
{ gecko = "StyleListStyleType", servo = "crate::values::computed::ListStyleType" },
|
||||
{ gecko = "StyleAu", servo = "app_units::Au" },
|
||||
{ gecko = "StyleAnchorName", servo = "crate::values::computed::position::AnchorName" },
|
||||
{ gecko = "StyleAnchorScope", servo = "crate::values::computed::position::AnchorScope" },
|
||||
|
|
|
|||
|
|
@ -750,7 +750,7 @@ bool ServoStyleSet::GeneratedContentPseudoExists(
|
|||
}
|
||||
// ::marker only exist if we have 'content' or at least one of
|
||||
// 'list-style-type' or 'list-style-image'.
|
||||
if (aPseudoStyle.StyleList()->mCounterStyle.IsNone() &&
|
||||
if (aPseudoStyle.StyleList()->mListStyleType.IsNone() &&
|
||||
aPseudoStyle.StyleList()->mListStyleImage.IsNone() &&
|
||||
content.IsNormal()) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -605,17 +605,16 @@ nsSize nsStyleOutline::EffectiveOffsetFor(const nsRect& aRect) const {
|
|||
//
|
||||
nsStyleList::nsStyleList()
|
||||
: mListStylePosition(StyleListStylePosition::Outside),
|
||||
mListStyleType(StyleCounterStyle::Name({StyleAtom(nsGkAtoms::disc)})),
|
||||
mQuotes(StyleQuotes::Auto()),
|
||||
mListStyleImage(StyleImage::None()) {
|
||||
MOZ_COUNT_CTOR(nsStyleList);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mCounterStyle = nsGkAtoms::disc;
|
||||
}
|
||||
|
||||
nsStyleList::nsStyleList(const nsStyleList& aSource)
|
||||
: mListStylePosition(aSource.mListStylePosition),
|
||||
mCounterStyle(aSource.mCounterStyle),
|
||||
mListStyleType(aSource.mListStyleType),
|
||||
mQuotes(aSource.mQuotes),
|
||||
mListStyleImage(aSource.mListStyleImage) {
|
||||
MOZ_COUNT_CTOR(nsStyleList);
|
||||
|
|
@ -641,7 +640,7 @@ nsChangeHint nsStyleList::CalcDifference(const nsStyleList& aNewData,
|
|||
// value changes from something else to list-item, that change itself would
|
||||
// cause ReconstructFrame.
|
||||
if (mListStylePosition != aNewData.mListStylePosition ||
|
||||
mCounterStyle != aNewData.mCounterStyle ||
|
||||
mListStyleType != aNewData.mListStyleType ||
|
||||
mListStyleImage != aNewData.mListStyleImage) {
|
||||
if (aOldStyle.StyleDisplay()->IsListItem()) {
|
||||
return nsChangeHint_ReconstructFrame;
|
||||
|
|
|
|||
|
|
@ -642,7 +642,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList {
|
|||
|
||||
mozilla::StyleListStylePosition mListStylePosition;
|
||||
|
||||
mozilla::CounterStylePtr mCounterStyle;
|
||||
mozilla::StyleListStyleType mListStyleType;
|
||||
mozilla::StyleQuotes mQuotes;
|
||||
mozilla::StyleImage mListStyleImage;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::parser::{Parse, ParserContext};
|
|||
use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use crate::str::CssStringWriter;
|
||||
use crate::values::specified::Integer;
|
||||
use crate::values::CustomIdent;
|
||||
use crate::values::{AtomString, CustomIdent};
|
||||
use crate::Atom;
|
||||
use cssparser::{
|
||||
AtRuleParser, DeclarationParser, QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser,
|
||||
|
|
@ -21,14 +21,174 @@ use selectors::parser::SelectorParseErrorKind;
|
|||
use std::fmt::{self, Write};
|
||||
use std::mem;
|
||||
use std::num::Wrapping;
|
||||
use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError};
|
||||
use style_traits::{StyleParseErrorKind, ToCss};
|
||||
use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError,
|
||||
StyleParseErrorKind, ToCss,
|
||||
KeywordsCollectFn, SpecifiedValueInfo};
|
||||
|
||||
/// Parse a counter style name reference.
|
||||
/// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(u8)]
|
||||
pub enum SymbolsType {
|
||||
Cyclic,
|
||||
Numeric,
|
||||
Alphabetic,
|
||||
Symbolic,
|
||||
Fixed,
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css-counter-styles/#typedef-counter-style>
|
||||
///
|
||||
/// This allows the reserved counter style names "decimal" and "disc".
|
||||
pub fn parse_counter_style_name<'i, 't>(
|
||||
/// Note that 'none' is not a valid name, but we include this (along with String) for space
|
||||
/// efficiency when storing list-style-type.
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
|
||||
#[repr(u8)]
|
||||
pub enum CounterStyle {
|
||||
/// The 'none' value.
|
||||
None,
|
||||
/// `<counter-style-name>`
|
||||
Name(CustomIdent),
|
||||
/// `symbols()`
|
||||
#[css(function)]
|
||||
Symbols {
|
||||
/// The <symbols-type>, or symbolic if not specified.
|
||||
#[css(skip_if = "is_symbolic")]
|
||||
ty: SymbolsType,
|
||||
/// The actual symbols.
|
||||
symbols: Symbols,
|
||||
},
|
||||
/// A single string value, useful for `<list-style-type>`.
|
||||
String(AtomString),
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_symbolic(symbols_type: &SymbolsType) -> bool {
|
||||
*symbols_type == SymbolsType::Symbolic
|
||||
}
|
||||
|
||||
impl CounterStyle {
|
||||
/// disc value
|
||||
pub fn disc() -> Self {
|
||||
CounterStyle::Name(CustomIdent(atom!("disc")))
|
||||
}
|
||||
|
||||
/// decimal value
|
||||
pub fn decimal() -> Self {
|
||||
CounterStyle::Name(CustomIdent(atom!("decimal")))
|
||||
}
|
||||
|
||||
/// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`)
|
||||
#[inline]
|
||||
pub fn is_bullet(&self) -> bool {
|
||||
match self {
|
||||
CounterStyle::Name(CustomIdent(ref name)) => {
|
||||
name == &atom!("disc") ||
|
||||
name == &atom!("circle") ||
|
||||
name == &atom!("square") ||
|
||||
name == &atom!("disclosure-closed") ||
|
||||
name == &atom!("disclosure-open")
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Clone, Copy)]
|
||||
/// Flags to control parsing of counter styles.
|
||||
pub struct CounterStyleParsingFlags: u8 {
|
||||
/// Whether `none` is allowed.
|
||||
const ALLOW_NONE = 1 << 0;
|
||||
/// Whether a bare string is allowed.
|
||||
const ALLOW_STRING = 1 << 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl CounterStyle {
|
||||
/// Parse a counter style, and optionally none|string (for list-style-type).
|
||||
pub fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
flags: CounterStyleParsingFlags,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
use self::CounterStyleParsingFlags as Flags;
|
||||
let location = input.current_source_location();
|
||||
match input.next()? {
|
||||
Token::QuotedString(ref string) if flags.intersects(Flags::ALLOW_STRING) => {
|
||||
Ok(Self::String(AtomString::from(string.as_ref())))
|
||||
},
|
||||
Token::Ident(ref ident) => {
|
||||
if flags.intersects(Flags::ALLOW_NONE) && ident.eq_ignore_ascii_case("none") {
|
||||
return Ok(Self::None);
|
||||
}
|
||||
Ok(Self::Name(counter_style_name_from_ident(ident, location)?))
|
||||
},
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("symbols") => {
|
||||
input.parse_nested_block(|input| {
|
||||
let symbols_type = input
|
||||
.try_parse(SymbolsType::parse)
|
||||
.unwrap_or(SymbolsType::Symbolic);
|
||||
let symbols = Symbols::parse(context, input)?;
|
||||
// There must be at least two symbols for alphabetic or
|
||||
// numeric system.
|
||||
if (symbols_type == SymbolsType::Alphabetic || symbols_type == SymbolsType::Numeric) &&
|
||||
symbols.0.len() < 2
|
||||
{
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
// Identifier is not allowed in symbols() function.
|
||||
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
Ok(Self::Symbols { ty: symbols_type, symbols })
|
||||
})
|
||||
},
|
||||
t => Err(location.new_unexpected_token_error(t.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecifiedValueInfo for CounterStyle {
|
||||
fn collect_completion_keywords(f: KeywordsCollectFn) {
|
||||
// XXX The best approach for implementing this is probably
|
||||
// having a CounterStyleName type wrapping CustomIdent, and
|
||||
// put the predefined list for that type in counter_style mod.
|
||||
// But that's a non-trivial change itself, so we use a simpler
|
||||
// approach here.
|
||||
macro_rules! predefined {
|
||||
($($name:expr,)+) => {
|
||||
f(&["symbols", "none", $($name,)+])
|
||||
}
|
||||
}
|
||||
include!("predefined.rs");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn parse_counter_style_name<'i>(input: &mut Parser<'i, '_>) -> Result<CustomIdent, ParseError<'i>> {
|
||||
let location = input.current_source_location();
|
||||
let ident = input.expect_ident()?;
|
||||
counter_style_name_from_ident(ident, location)
|
||||
}
|
||||
|
||||
|
||||
/// This allows the reserved counter style names "decimal" and "disc".
|
||||
fn counter_style_name_from_ident<'i>(
|
||||
ident: &CowRcStr<'i>,
|
||||
location: SourceLocation,
|
||||
) -> Result<CustomIdent, ParseError<'i>> {
|
||||
macro_rules! predefined {
|
||||
($($name: tt,)+) => {{
|
||||
|
|
@ -40,8 +200,6 @@ pub fn parse_counter_style_name<'i, 't>(
|
|||
}
|
||||
}
|
||||
|
||||
let location = input.current_source_location();
|
||||
let ident = input.expect_ident()?;
|
||||
// This effectively performs case normalization only on predefined names.
|
||||
if let Some(lower_case) = predefined::get(&ident) {
|
||||
Ok(CustomIdent(lower_case.clone()))
|
||||
|
|
@ -583,21 +741,21 @@ impl Parse for Fallback {
|
|||
Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToCss, ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub struct Symbols(#[css(iterable)] pub crate::OwnedSlice<Symbol>);
|
||||
pub struct Symbols(#[css(iterable)] #[ignore_malloc_size_of = "Arc"] pub crate::ArcSlice<Symbol>);
|
||||
|
||||
impl Parse for Symbols {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let mut symbols = Vec::new();
|
||||
let mut symbols = smallvec::SmallVec::<[_; 5]>::new();
|
||||
while let Ok(s) = input.try_parse(|input| Symbol::parse(context, input)) {
|
||||
symbols.push(s);
|
||||
}
|
||||
if symbols.is_empty() {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
Ok(Symbols(symbols.into()))
|
||||
Ok(Symbols(crate::ArcSlice::from_iter(symbols.drain(..))))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,6 @@
|
|||
//! Different kind of helpers to interact with Gecko values.
|
||||
|
||||
use crate::color::{AbsoluteColor, ColorSpace};
|
||||
use crate::counter_style::{Symbol, Symbols};
|
||||
use crate::gecko_bindings::bindings;
|
||||
use crate::gecko_bindings::structs::CounterStylePtr;
|
||||
use crate::values::generics::CounterStyle;
|
||||
use crate::values::Either;
|
||||
use crate::Atom;
|
||||
|
||||
/// Convert a color value to `nscolor`.
|
||||
pub fn convert_absolute_color_to_nscolor(color: &AbsoluteColor) -> u32 {
|
||||
|
|
@ -40,38 +34,3 @@ fn convert_ns_color_to_absolute_color_should_be_in_legacy_syntax() {
|
|||
|
||||
assert!(result.is_legacy_syntax());
|
||||
}
|
||||
|
||||
impl CounterStyle {
|
||||
/// Convert this counter style to a Gecko CounterStylePtr.
|
||||
#[inline]
|
||||
pub fn to_gecko_value(&self, gecko_value: &mut CounterStylePtr) {
|
||||
unsafe { bindings::Gecko_CounterStyle_ToPtr(self, gecko_value) }
|
||||
}
|
||||
|
||||
/// Convert Gecko CounterStylePtr to CounterStyle or String.
|
||||
pub fn from_gecko_value(gecko_value: &CounterStylePtr) -> Either<Self, String> {
|
||||
use crate::values::CustomIdent;
|
||||
|
||||
let name = unsafe { bindings::Gecko_CounterStyle_GetName(gecko_value) };
|
||||
if !name.is_null() {
|
||||
let name = unsafe { Atom::from_raw(name) };
|
||||
debug_assert_ne!(name, atom!("none"));
|
||||
Either::First(CounterStyle::Name(CustomIdent(name)))
|
||||
} else {
|
||||
let anonymous =
|
||||
unsafe { bindings::Gecko_CounterStyle_GetAnonymous(gecko_value).as_ref() }.unwrap();
|
||||
let symbols = &anonymous.mSymbols;
|
||||
if anonymous.mSingleString {
|
||||
debug_assert_eq!(symbols.len(), 1);
|
||||
Either::Second(symbols[0].to_string())
|
||||
} else {
|
||||
let symbol_type = anonymous.mSymbolsType;
|
||||
let symbols = symbols
|
||||
.iter()
|
||||
.map(|gecko_symbol| Symbol::String(gecko_symbol.to_string().into()))
|
||||
.collect();
|
||||
Either::First(CounterStyle::Symbols(symbol_type, Symbols(symbols)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use crate::gecko_bindings::bindings::Gecko_Construct_Default_${style_struct.geck
|
|||
use crate::gecko_bindings::bindings::Gecko_CopyConstruct_${style_struct.gecko_ffi_name};
|
||||
use crate::gecko_bindings::bindings::Gecko_Destroy_${style_struct.gecko_ffi_name};
|
||||
% endfor
|
||||
use crate::gecko_bindings::bindings::Gecko_CopyCounterStyle;
|
||||
use crate::gecko_bindings::bindings::Gecko_EnsureImageLayersLength;
|
||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_SetLang;
|
||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom;
|
||||
|
|
@ -1453,55 +1452,7 @@ fn static_assert() {
|
|||
<% impl_simple_image_array_property("blend_mode", "background", "mImage", "mBlendMode", "Background") %>
|
||||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="List" skip_longhands="list-style-type">
|
||||
pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) {
|
||||
use nsstring::{nsACString, nsCStr};
|
||||
use self::longhands::list_style_type::computed_value::T;
|
||||
match v {
|
||||
T::None => unsafe {
|
||||
bindings::Gecko_SetCounterStyleToNone(&mut self.mCounterStyle)
|
||||
}
|
||||
T::CounterStyle(s) => s.to_gecko_value(&mut self.mCounterStyle),
|
||||
T::String(s) => unsafe {
|
||||
bindings::Gecko_SetCounterStyleToString(
|
||||
&mut self.mCounterStyle,
|
||||
&nsCStr::from(&s) as &nsACString,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_list_style_type_from(&mut self, other: &Self) {
|
||||
unsafe {
|
||||
Gecko_CopyCounterStyle(&mut self.mCounterStyle, &other.mCounterStyle);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_list_style_type(&mut self, other: &Self) {
|
||||
self.copy_list_style_type_from(other)
|
||||
}
|
||||
|
||||
pub fn clone_list_style_type(&self) -> longhands::list_style_type::computed_value::T {
|
||||
use self::longhands::list_style_type::computed_value::T;
|
||||
use crate::values::Either;
|
||||
use crate::values::generics::CounterStyle;
|
||||
use crate::gecko_bindings::bindings;
|
||||
|
||||
let name = unsafe {
|
||||
bindings::Gecko_CounterStyle_GetName(&self.mCounterStyle)
|
||||
};
|
||||
if !name.is_null() {
|
||||
let name = unsafe { Atom::from_raw(name) };
|
||||
if name == atom!("none") {
|
||||
return T::None;
|
||||
}
|
||||
}
|
||||
let result = CounterStyle::from_gecko_value(&self.mCounterStyle);
|
||||
match result {
|
||||
Either::First(counter_style) => T::CounterStyle(counter_style),
|
||||
Either::Second(string) => T::String(string),
|
||||
}
|
||||
}
|
||||
<%self:impl_trait style_struct_name="List">
|
||||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="Table">
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ ${helpers.single_keyword(
|
|||
engines="gecko",
|
||||
initial_specified_value="specified::ListStyleType::disc()",
|
||||
animation_value_type="discrete",
|
||||
boxed=True,
|
||||
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
affects="layout",
|
||||
|
|
|
|||
|
|
@ -69,14 +69,14 @@
|
|||
Ok(expanded! {
|
||||
list_style_position: position,
|
||||
list_style_image: Image::None,
|
||||
list_style_type: ListStyleType::None,
|
||||
list_style_type: ListStyleType::none(),
|
||||
})
|
||||
}
|
||||
(true, 1, None, Some(image)) => {
|
||||
Ok(expanded! {
|
||||
list_style_position: position,
|
||||
list_style_image: image,
|
||||
list_style_type: ListStyleType::None,
|
||||
list_style_type: ListStyleType::none(),
|
||||
})
|
||||
}
|
||||
(true, 1, Some(list_style_type), None) => {
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
Ok(expanded! {
|
||||
list_style_position: position,
|
||||
list_style_image: Image::None,
|
||||
list_style_type: ListStyleType::None,
|
||||
list_style_type: ListStyleType::none(),
|
||||
})
|
||||
}
|
||||
(true, 0, list_style_type, image) => {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#[cfg(feature = "servo")]
|
||||
use crate::computed_values::list_style_type::T as ListStyleType;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::generics::CounterStyle;
|
||||
use crate::counter_style::CounterStyle;
|
||||
use crate::values::specified::Attr;
|
||||
use crate::values::CustomIdent;
|
||||
use std::fmt::{self, Write};
|
||||
|
|
|
|||
|
|
@ -5,13 +5,8 @@
|
|||
//! Generic types that share their serialization implementations
|
||||
//! for both specified and computed values.
|
||||
|
||||
use super::CustomIdent;
|
||||
use crate::counter_style::{parse_counter_style_name, Symbols};
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::Zero;
|
||||
use cssparser::Parser;
|
||||
use std::ops::Add;
|
||||
use style_traits::{KeywordsCollectFn, ParseError, SpecifiedValueInfo, StyleParseErrorKind};
|
||||
|
||||
pub mod animation;
|
||||
pub mod background;
|
||||
|
|
@ -42,123 +37,6 @@ pub mod transform;
|
|||
pub mod ui;
|
||||
pub mod url;
|
||||
|
||||
/// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(u8)]
|
||||
pub enum SymbolsType {
|
||||
Cyclic,
|
||||
Numeric,
|
||||
Alphabetic,
|
||||
Symbolic,
|
||||
Fixed,
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css-counter-styles/#typedef-counter-style>
|
||||
///
|
||||
/// Note that 'none' is not a valid name.
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
|
||||
#[repr(u8)]
|
||||
pub enum CounterStyle {
|
||||
/// `<counter-style-name>`
|
||||
Name(CustomIdent),
|
||||
/// `symbols()`
|
||||
#[css(function)]
|
||||
Symbols(#[css(skip_if = "is_symbolic")] SymbolsType, Symbols),
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_symbolic(symbols_type: &SymbolsType) -> bool {
|
||||
*symbols_type == SymbolsType::Symbolic
|
||||
}
|
||||
|
||||
impl CounterStyle {
|
||||
/// disc value
|
||||
pub fn disc() -> Self {
|
||||
CounterStyle::Name(CustomIdent(atom!("disc")))
|
||||
}
|
||||
|
||||
/// decimal value
|
||||
pub fn decimal() -> Self {
|
||||
CounterStyle::Name(CustomIdent(atom!("decimal")))
|
||||
}
|
||||
|
||||
/// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`)
|
||||
#[inline]
|
||||
pub fn is_bullet(&self) -> bool {
|
||||
match self {
|
||||
CounterStyle::Name(CustomIdent(ref name)) => {
|
||||
name == &atom!("disc") ||
|
||||
name == &atom!("circle") ||
|
||||
name == &atom!("square") ||
|
||||
name == &atom!("disclosure-closed") ||
|
||||
name == &atom!("disclosure-open")
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for CounterStyle {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(name) = input.try_parse(|i| parse_counter_style_name(i)) {
|
||||
return Ok(CounterStyle::Name(name));
|
||||
}
|
||||
input.expect_function_matching("symbols")?;
|
||||
input.parse_nested_block(|input| {
|
||||
let symbols_type = input
|
||||
.try_parse(SymbolsType::parse)
|
||||
.unwrap_or(SymbolsType::Symbolic);
|
||||
let symbols = Symbols::parse(context, input)?;
|
||||
// There must be at least two symbols for alphabetic or
|
||||
// numeric system.
|
||||
if (symbols_type == SymbolsType::Alphabetic || symbols_type == SymbolsType::Numeric) &&
|
||||
symbols.0.len() < 2
|
||||
{
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
// Identifier is not allowed in symbols() function.
|
||||
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
Ok(CounterStyle::Symbols(symbols_type, symbols))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecifiedValueInfo for CounterStyle {
|
||||
fn collect_completion_keywords(f: KeywordsCollectFn) {
|
||||
// XXX The best approach for implementing this is probably
|
||||
// having a CounterStyleName type wrapping CustomIdent, and
|
||||
// put the predefined list for that type in counter_style mod.
|
||||
// But that's a non-trivial change itself, so we use a simpler
|
||||
// approach here.
|
||||
macro_rules! predefined {
|
||||
($($name:expr,)+) => {
|
||||
f(&["symbols", $($name,)+])
|
||||
}
|
||||
}
|
||||
include!("../../counter_style/predefined.rs");
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper of Non-negative values.
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::parser::{Parse, ParserContext};
|
|||
use crate::values::generics::counters as generics;
|
||||
use crate::values::generics::counters::CounterPair;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::generics::CounterStyle;
|
||||
use crate::counter_style::CounterStyle;
|
||||
use crate::values::specified::image::Image;
|
||||
use crate::values::specified::Attr;
|
||||
use crate::values::specified::Integer;
|
||||
|
|
@ -161,12 +161,13 @@ impl Content {
|
|||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyle {
|
||||
use crate::counter_style::CounterStyleParsingFlags;
|
||||
input
|
||||
.try_parse(|input| {
|
||||
input.expect_comma()?;
|
||||
CounterStyle::parse(context, input)
|
||||
CounterStyle::parse(context, input, CounterStyleParsingFlags::empty())
|
||||
})
|
||||
.unwrap_or(CounterStyle::decimal())
|
||||
.unwrap_or_else(|_| CounterStyle::decimal())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@
|
|||
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::generics::CounterStyle;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::CustomIdent;
|
||||
use crate::counter_style::{CounterStyle, CounterStyleParsingFlags};
|
||||
use cssparser::{Parser, Token};
|
||||
use style_traits::{ParseError, StyleParseErrorKind};
|
||||
|
||||
|
|
@ -26,37 +24,36 @@ use style_traits::{ParseError, StyleParseErrorKind};
|
|||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
pub enum ListStyleType {
|
||||
/// `none`
|
||||
None,
|
||||
/// <counter-style>
|
||||
CounterStyle(CounterStyle),
|
||||
/// <string>
|
||||
String(String),
|
||||
}
|
||||
#[repr(transparent)]
|
||||
pub struct ListStyleType(pub CounterStyle);
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl ListStyleType {
|
||||
/// Initial specified value for `list-style-type`.
|
||||
#[inline]
|
||||
pub fn disc() -> Self {
|
||||
ListStyleType::CounterStyle(CounterStyle::disc())
|
||||
Self(CounterStyle::disc())
|
||||
}
|
||||
|
||||
/// none value.
|
||||
#[inline]
|
||||
pub fn none() -> Self {
|
||||
Self(CounterStyle::None)
|
||||
}
|
||||
|
||||
/// Convert from gecko keyword to list-style-type.
|
||||
///
|
||||
/// This should only be used for mapping type attribute to
|
||||
/// list-style-type, and thus only values possible in that
|
||||
/// attribute is considered here.
|
||||
/// This should only be used for mapping type attribute to list-style-type, and thus only
|
||||
/// values possible in that attribute is considered here.
|
||||
pub fn from_gecko_keyword(value: u32) -> Self {
|
||||
use crate::gecko_bindings::structs;
|
||||
use crate::values::CustomIdent;
|
||||
let v8 = value as u8;
|
||||
|
||||
if v8 == structs::ListStyle_None {
|
||||
return ListStyleType::None;
|
||||
return Self::none();
|
||||
}
|
||||
|
||||
ListStyleType::CounterStyle(CounterStyle::Name(CustomIdent(match v8 {
|
||||
Self(CounterStyle::Name(CustomIdent(match v8 {
|
||||
structs::ListStyle_Disc => atom!("disc"),
|
||||
structs::ListStyle_Circle => atom!("circle"),
|
||||
structs::ListStyle_Square => atom!("square"),
|
||||
|
|
@ -69,13 +66,11 @@ impl ListStyleType {
|
|||
})))
|
||||
}
|
||||
|
||||
|
||||
/// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`)
|
||||
#[inline]
|
||||
pub fn is_bullet(&self) -> bool {
|
||||
match self {
|
||||
ListStyleType::CounterStyle(ref style) => style.is_bullet(),
|
||||
_ => false,
|
||||
}
|
||||
self.0.is_bullet()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,15 +80,8 @@ impl Parse for ListStyleType {
|
|||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(style) = input.try_parse(|i| CounterStyle::parse(context, i)) {
|
||||
return Ok(ListStyleType::CounterStyle(style));
|
||||
}
|
||||
if input.try_parse(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(ListStyleType::None);
|
||||
}
|
||||
Ok(ListStyleType::String(
|
||||
input.expect_string()?.as_ref().to_owned(),
|
||||
))
|
||||
let flags = CounterStyleParsingFlags::ALLOW_NONE | CounterStyleParsingFlags::ALLOW_STRING;
|
||||
Ok(Self(CounterStyle::parse(context, input, flags)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3750,13 +3750,15 @@ pub unsafe extern "C" fn Servo_CounterStyleRule_IsInRange(
|
|||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_CounterStyleRule_GetSymbols(
|
||||
rule: &LockedCounterStyleRule,
|
||||
symbols: &mut style::OwnedSlice<nsString>,
|
||||
) {
|
||||
count: &mut usize,
|
||||
) -> *const counter_style::Symbol {
|
||||
read_locked_arc(rule, |rule: &CounterStyleRule| {
|
||||
*symbols = match rule.symbols() {
|
||||
Some(s) => s.0.iter().map(symbol_to_string).collect(),
|
||||
None => style::OwnedSlice::default(),
|
||||
let symbols = match rule.symbols() {
|
||||
Some(s) => &*s.0,
|
||||
None => &[],
|
||||
};
|
||||
*count = symbols.len();
|
||||
symbols.as_ptr()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -5351,7 +5353,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(
|
|||
})
|
||||
},
|
||||
FontWeight => longhands::font_weight::SpecifiedValue::from_gecko_keyword(value),
|
||||
ListStyleType => Box::new(longhands::list_style_type::SpecifiedValue::from_gecko_keyword(value)),
|
||||
ListStyleType => longhands::list_style_type::SpecifiedValue::from_gecko_keyword(value),
|
||||
MathStyle => longhands::math_style::SpecifiedValue::from_gecko_keyword(value),
|
||||
MozMathVariant => longhands::_moz_math_variant::SpecifiedValue::from_gecko_keyword(value),
|
||||
WhiteSpaceCollapse => get_from_computed::<longhands::white_space_collapse::SpecifiedValue>(value),
|
||||
|
|
|
|||
Loading…
Reference in a new issue