From b31121a2a1a8f4b9069e3b829735c64b259e887f Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 30 May 2013 16:00:20 +0800 Subject: [PATCH] Bug 234485: Map xml:lang attribute into style so that it's used for font selection and hyphenation. r=bzbarsky The code in nsHTMLStyleSheet implements LangRule to map xml:lang into style and the code to manage its uniqueness. The change to nsGenericHTMLElement fixes the mapping of the HTML lang attribute to do cascading the way all other rule mapping does so that the cascading works correctly. The tests test that the correct style language is used for hyphenation by copying over a set of hyphenation reftests that check its basic response to languages. There are no specific tests for font selection, but font selection is known to use the same language data from style. I verified manually (see other attachments to bug) that the rule uniqueness is being managed correctly. --HG-- rename : layout/reftests/text/auto-hyphenation-1.html => layout/reftests/text/auto-hyphenation-xmllang-1.xhtml rename : layout/reftests/text/auto-hyphenation-10.html => layout/reftests/text/auto-hyphenation-xmllang-10.xhtml rename : layout/reftests/text/auto-hyphenation-1.html => layout/reftests/text/auto-hyphenation-xmllang-11a.xhtml rename : layout/reftests/text/auto-hyphenation-1.html => layout/reftests/text/auto-hyphenation-xmllang-11b.xhtml rename : layout/reftests/text/auto-hyphenation-4.html => layout/reftests/text/auto-hyphenation-xmllang-12a.xhtml rename : layout/reftests/text/auto-hyphenation-4.html => layout/reftests/text/auto-hyphenation-xmllang-12b.xhtml rename : layout/reftests/text/auto-hyphenation-1.html => layout/reftests/text/auto-hyphenation-xmllang-13a.xhtml rename : layout/reftests/text/auto-hyphenation-1.html => layout/reftests/text/auto-hyphenation-xmllang-13b.xhtml rename : layout/reftests/text/auto-hyphenation-4.html => layout/reftests/text/auto-hyphenation-xmllang-14a.xhtml rename : layout/reftests/text/auto-hyphenation-4.html => layout/reftests/text/auto-hyphenation-xmllang-14b.xhtml rename : layout/reftests/text/auto-hyphenation-1a.html => layout/reftests/text/auto-hyphenation-xmllang-1a.xhtml rename : layout/reftests/text/auto-hyphenation-2.html => layout/reftests/text/auto-hyphenation-xmllang-2.xhtml rename : layout/reftests/text/auto-hyphenation-3.html => layout/reftests/text/auto-hyphenation-xmllang-3.xhtml rename : layout/reftests/text/auto-hyphenation-4.html => layout/reftests/text/auto-hyphenation-xmllang-4.xhtml rename : layout/reftests/text/auto-hyphenation-5.html => layout/reftests/text/auto-hyphenation-xmllang-5.xhtml rename : layout/reftests/text/auto-hyphenation-6.html => layout/reftests/text/auto-hyphenation-xmllang-6.xhtml rename : layout/reftests/text/auto-hyphenation-7.html => layout/reftests/text/auto-hyphenation-xmllang-7.xhtml rename : layout/reftests/text/auto-hyphenation-8.html => layout/reftests/text/auto-hyphenation-xmllang-8.xhtml rename : layout/reftests/text/auto-hyphenation-9.html => layout/reftests/text/auto-hyphenation-xmllang-9.xhtml --- .../html/content/src/nsGenericHTMLElement.cpp | 10 +- .../text/auto-hyphenation-xmllang-1.xhtml | 11 ++ .../text/auto-hyphenation-xmllang-10.xhtml | 12 ++ .../text/auto-hyphenation-xmllang-11a.xhtml | 11 ++ .../text/auto-hyphenation-xmllang-11b.xhtml | 11 ++ .../text/auto-hyphenation-xmllang-12a.xhtml | 12 ++ .../text/auto-hyphenation-xmllang-12b.xhtml | 12 ++ .../text/auto-hyphenation-xmllang-13a.xhtml | 13 ++ .../text/auto-hyphenation-xmllang-13b.xhtml | 13 ++ .../text/auto-hyphenation-xmllang-14a.xhtml | 14 ++ .../text/auto-hyphenation-xmllang-14b.xhtml | 14 ++ .../text/auto-hyphenation-xmllang-1a.xhtml | 11 ++ .../text/auto-hyphenation-xmllang-2.xhtml | 13 ++ .../text/auto-hyphenation-xmllang-3.xhtml | 11 ++ .../text/auto-hyphenation-xmllang-4.xhtml | 11 ++ .../text/auto-hyphenation-xmllang-5.xhtml | 28 ++++ .../text/auto-hyphenation-xmllang-6.xhtml | 11 ++ .../text/auto-hyphenation-xmllang-7.xhtml | 11 ++ .../text/auto-hyphenation-xmllang-8.xhtml | 11 ++ .../text/auto-hyphenation-xmllang-9.xhtml | 12 ++ layout/reftests/text/reftest.list | 20 +++ layout/style/nsHTMLStyleSheet.cpp | 123 +++++++++++++++++- layout/style/nsHTMLStyleSheet.h | 24 ++++ 23 files changed, 414 insertions(+), 5 deletions(-) create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-1.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-10.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-11a.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-11b.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-12a.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-12b.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-13a.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-13b.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-14a.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-14b.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-1a.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-2.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-3.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-4.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-5.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-6.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-7.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-8.xhtml create mode 100644 layout/reftests/text/auto-hyphenation-xmllang-9.xhtml diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 373c64641d8..a209b28bf13 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -1461,10 +1461,12 @@ nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttribu } if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) { - const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::lang); - if (value && value->Type() == nsAttrValue::eString) { - aData->ValueForLang()->SetStringValue(value->GetStringValue(), - eCSSUnit_Ident); + nsCSSValue* lang = aData->ValueForLang(); + if (lang->GetUnit() == eCSSUnit_Null) { + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::lang); + if (value && value->Type() == nsAttrValue::eString) { + lang->SetStringValue(value->GetStringValue(), eCSSUnit_Ident); + } } } diff --git a/layout/reftests/text/auto-hyphenation-xmllang-1.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-1.xhtml new file mode 100644 index 00000000000..e075a015096 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-1.xhtml @@ -0,0 +1,11 @@ + + +Hyphenation test + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-10.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-10.xhtml new file mode 100644 index 00000000000..456d894739f --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-10.xhtml @@ -0,0 +1,12 @@ + + + +Hyphenation test + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-11a.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-11a.xhtml new file mode 100644 index 00000000000..01c3e1ca828 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-11a.xhtml @@ -0,0 +1,11 @@ + + +Hyphenation test + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-11b.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-11b.xhtml new file mode 100644 index 00000000000..97c6ff9b0bb --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-11b.xhtml @@ -0,0 +1,11 @@ + + +Hyphenation test + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-12a.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-12a.xhtml new file mode 100644 index 00000000000..2751dd93f2e --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-12a.xhtml @@ -0,0 +1,12 @@ + + +Hyphenation test + + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-12b.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-12b.xhtml new file mode 100644 index 00000000000..c6b62249fc1 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-12b.xhtml @@ -0,0 +1,12 @@ + + +Hyphenation test + + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-13a.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-13a.xhtml new file mode 100644 index 00000000000..ee75d43158d --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-13a.xhtml @@ -0,0 +1,13 @@ + + +Hyphenation test + + +
+
+supercalifragilisticexpialidocious +
+
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-13b.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-13b.xhtml new file mode 100644 index 00000000000..b90cfae8db9 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-13b.xhtml @@ -0,0 +1,13 @@ + + +Hyphenation test + + +
+
+supercalifragilisticexpialidocious +
+
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-14a.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-14a.xhtml new file mode 100644 index 00000000000..e6aa85573fd --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-14a.xhtml @@ -0,0 +1,14 @@ + + +Hyphenation test + + + +
+
+supercalifragilisticexpialidocious +
+
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-14b.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-14b.xhtml new file mode 100644 index 00000000000..4811a34f9d0 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-14b.xhtml @@ -0,0 +1,14 @@ + + +Hyphenation test + + + +
+
+supercalifragilisticexpialidocious +
+
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-1a.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-1a.xhtml new file mode 100644 index 00000000000..a5761a11c0b --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-1a.xhtml @@ -0,0 +1,11 @@ + + +Hyphenation test + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-2.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-2.xhtml new file mode 100644 index 00000000000..47fe750ed53 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-2.xhtml @@ -0,0 +1,13 @@ + + +Hyphenation test + + +
+supercalifragilisticexpialidocious +supercalifragilisticexpialidocious +supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-3.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-3.xhtml new file mode 100644 index 00000000000..ff4b3667df7 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-3.xhtml @@ -0,0 +1,11 @@ + + +Hyphenation test + + +
+su­per­cal­ifrag­ilis­tic­ex­pi­ali­do­cious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-4.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-4.xhtml new file mode 100644 index 00000000000..cde29e6e655 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-4.xhtml @@ -0,0 +1,11 @@ + + +Hyphenation test + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-5.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-5.xhtml new file mode 100644 index 00000000000..ec0495b891e --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-5.xhtml @@ -0,0 +1,28 @@ + + + + + + + +
+photo +
+
+photograph +
+
+photographer +
+
+photographical +
+ + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-6.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-6.xhtml new file mode 100644 index 00000000000..f5637ea7689 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-6.xhtml @@ -0,0 +1,11 @@ + + +Hyphenation test + + +
+hyphenation +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-7.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-7.xhtml new file mode 100644 index 00000000000..c621c7984e0 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-7.xhtml @@ -0,0 +1,11 @@ + + +Hyphenation test + + +
+hyphenation +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-8.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-8.xhtml new file mode 100644 index 00000000000..17b26c5b5cf --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-8.xhtml @@ -0,0 +1,11 @@ + + +Hyphenation test + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/auto-hyphenation-xmllang-9.xhtml b/layout/reftests/text/auto-hyphenation-xmllang-9.xhtml new file mode 100644 index 00000000000..c0367bea366 --- /dev/null +++ b/layout/reftests/text/auto-hyphenation-xmllang-9.xhtml @@ -0,0 +1,12 @@ + + + +Hyphenation test + + +
+supercalifragilisticexpialidocious +
+ + + diff --git a/layout/reftests/text/reftest.list b/layout/reftests/text/reftest.list index cca53a6e015..cdc52ed8da8 100644 --- a/layout/reftests/text/reftest.list +++ b/layout/reftests/text/reftest.list @@ -219,6 +219,26 @@ pref(gfx.font_rendering.graphite.enabled,true) HTTP(..) == glyph-decomposition-g == auto-hyphenation-8.html auto-hyphenation-8-ref.html == auto-hyphenation-9.html auto-hyphenation-9-ref.html == auto-hyphenation-10.html auto-hyphenation-10-ref.html +== auto-hyphenation-xmllang-1.xhtml auto-hyphenation-1-ref.html +!= auto-hyphenation-xmllang-1.xhtml auto-hyphenation-1-notref.html +== auto-hyphenation-xmllang-1a.xhtml auto-hyphenation-1-ref.html +== auto-hyphenation-xmllang-2.xhtml auto-hyphenation-2-ref.html +== auto-hyphenation-xmllang-3.xhtml auto-hyphenation-3-ref.html +== auto-hyphenation-xmllang-4.xhtml auto-hyphenation-4-ref.html +== auto-hyphenation-xmllang-5.xhtml auto-hyphenation-5-ref.html +== auto-hyphenation-xmllang-6.xhtml auto-hyphenation-6-ref.html +== auto-hyphenation-xmllang-7.xhtml auto-hyphenation-7-ref.html +== auto-hyphenation-xmllang-8.xhtml auto-hyphenation-8-ref.html +== auto-hyphenation-xmllang-9.xhtml auto-hyphenation-9-ref.html +== auto-hyphenation-xmllang-10.xhtml auto-hyphenation-10-ref.html +== auto-hyphenation-xmllang-11a.xhtml auto-hyphenation-1-ref.html +== auto-hyphenation-xmllang-11b.xhtml auto-hyphenation-1-ref.html +== auto-hyphenation-xmllang-12a.xhtml auto-hyphenation-4-ref.html +== auto-hyphenation-xmllang-12b.xhtml auto-hyphenation-4-ref.html +== auto-hyphenation-xmllang-13a.xhtml auto-hyphenation-1-ref.html +== auto-hyphenation-xmllang-13b.xhtml auto-hyphenation-1-ref.html +== auto-hyphenation-xmllang-14a.xhtml auto-hyphenation-4-ref.html +== auto-hyphenation-xmllang-14b.xhtml auto-hyphenation-4-ref.html == auto-hyphenation-af-1.html auto-hyphenation-af-1-ref.html == auto-hyphenation-bg-1.html auto-hyphenation-bg-1-ref.html == auto-hyphenation-ca-1.html auto-hyphenation-ca-1-ref.html diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index de610795b56..d1ef8c23347 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -32,7 +32,9 @@ #include "nsCSSRuleProcessor.h" #include "mozilla/dom/Element.h" #include "nsCSSFrameConstructor.h" +#include "nsHashKeys.h" +using namespace mozilla; using namespace mozilla::dom; NS_IMPL_ISUPPORTS1(nsHTMLStyleSheet::HTMLColorRule, nsIStyleRule) @@ -94,6 +96,31 @@ nsHTMLStyleSheet::TableQuirkColorRule::MapRuleInfoInto(nsRuleData* aRuleData) } } + +NS_IMPL_ISUPPORTS1(nsHTMLStyleSheet::LangRule, nsIStyleRule) + +/* virtual */ void +nsHTMLStyleSheet::LangRule::MapRuleInfoInto(nsRuleData* aRuleData) +{ + if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) { + nsCSSValue* lang = aRuleData->ValueForLang(); + if (lang->GetUnit() == eCSSUnit_Null) { + lang->SetStringValue(mLang, eCSSUnit_Ident); + } + } +} + +#ifdef DEBUG +/* virtual */ void +nsHTMLStyleSheet::LangRule::List(FILE* out, int32_t aIndent) const +{ + for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); + fputs("[lang rule] { language: \"", out); + fputs(NS_ConvertUTF16toUTF8(mLang).get(), out); + fputs("\" }\n", out); +} +#endif + // ----------------------------------------------------------- struct MappedAttrTableEntry : public PLDHashEntryHdr { @@ -138,7 +165,64 @@ static PLDHashTableOps MappedAttrTable_Ops = { PL_DHashMoveEntryStub, MappedAttrTable_ClearEntry, PL_DHashFinalizeStub, - NULL + nullptr +}; + +// ----------------------------------------------------------- + +struct LangRuleTableEntry : public PLDHashEntryHdr { + nsRefPtr mRule; +}; + +static PLDHashNumber +LangRuleTable_HashKey(PLDHashTable *table, const void *key) +{ + const nsString *lang = static_cast(key); + return HashString(*lang); +} + +static void +LangRuleTable_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr) +{ + LangRuleTableEntry *entry = static_cast(hdr); + + entry->~LangRuleTableEntry(); + memset(entry, 0, sizeof(LangRuleTableEntry)); +} + +static bool +LangRuleTable_MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr, + const void *key) +{ + const nsString *lang = static_cast(key); + const LangRuleTableEntry *entry = static_cast(hdr); + + return entry->mRule->mLang == *lang; +} + +static bool +LangRuleTable_InitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr, + const void *key) +{ + const nsString *lang = static_cast(key); + + LangRuleTableEntry *entry = new (hdr) LangRuleTableEntry(); + + // Create the unique rule for this language + entry->mRule = new nsHTMLStyleSheet::LangRule(*lang); + + return true; +} + +static PLDHashTableOps LangRuleTable_Ops = { + PL_DHashAllocTable, + PL_DHashFreeTable, + LangRuleTable_HashKey, + LangRuleTable_MatchEntry, + PL_DHashMoveEntryStub, + LangRuleTable_ClearEntry, + PL_DHashFinalizeStub, + LangRuleTable_InitEntry }; // ----------------------------------------------------------- @@ -152,10 +236,13 @@ nsHTMLStyleSheet::nsHTMLStyleSheet(nsIURI* aURL, nsIDocument* aDocument) MOZ_ASSERT(aURL); MOZ_ASSERT(aDocument); mMappedAttrTable.ops = nullptr; + mLangRuleTable.ops = nullptr; } nsHTMLStyleSheet::~nsHTMLStyleSheet() { + if (mLangRuleTable.ops) + PL_DHashTableFinish(&mLangRuleTable); if (mMappedAttrTable.ops) PL_DHashTableFinish(&mMappedAttrTable); } @@ -212,6 +299,14 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData) if (!ruleWalker->AuthorStyleDisabled() || aData->mElement->IsSVG()) { aData->mElement->WalkContentStyleRules(ruleWalker); } + + // http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#language + // says that the xml:lang attribute overrides HTML's lang attribute, + // so we need to do this after WalkContentStyleRules. + nsString lang; + if (aData->mElement->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang, lang)) { + ruleWalker->Forward(LangRuleFor(lang)); + } } // Test if style is dependent on content state @@ -387,6 +482,10 @@ nsHTMLStyleSheet::Reset(nsIURI* aURL) mVisitedRule = nullptr; mActiveRule = nullptr; + if (mLangRuleTable.ops) { + PL_DHashTableFinish(&mLangRuleTable); + mLangRuleTable.ops = nullptr; + } if (mMappedAttrTable.ops) { PL_DHashTableFinish(&mMappedAttrTable); mMappedAttrTable.ops = nullptr; @@ -474,6 +573,27 @@ nsHTMLStyleSheet::DropMappedAttributes(nsMappedAttributes* aMapped) NS_ASSERTION(entryCount == mMappedAttrTable.entryCount, "not removed"); } +nsIStyleRule* +nsHTMLStyleSheet::LangRuleFor(const nsString& aLanguage) +{ + if (!mLangRuleTable.ops) { + bool res = PL_DHashTableInit(&mLangRuleTable, &LangRuleTable_Ops, + nullptr, sizeof(LangRuleTableEntry), 16); + if (!res) { + NS_ASSERTION(false, "out of memory"); + mLangRuleTable.ops = nullptr; + return nullptr; + } + } + LangRuleTableEntry *entry = static_cast + (PL_DHashTableOperate(&mLangRuleTable, &aLanguage, PL_DHASH_ADD)); + if (!entry) { + NS_ASSERTION(false, "out of memory"); + return nullptr; + } + return entry->mRule; +} + #ifdef DEBUG /* virtual */ void nsHTMLStyleSheet::List(FILE* out, int32_t aIndent) const @@ -522,6 +642,7 @@ nsHTMLStyleSheet::DOMSizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const // - mActiveRule // - mTableQuirkColorRule // - mTableTHRule + // - mLangRuleTable // // The following members are not measured: // - mDocument, because it's non-owning diff --git a/layout/style/nsHTMLStyleSheet.h b/layout/style/nsHTMLStyleSheet.h index 6b6dfa29950..c56b4bfa4cf 100644 --- a/layout/style/nsHTMLStyleSheet.h +++ b/layout/style/nsHTMLStyleSheet.h @@ -20,6 +20,7 @@ #include "nsIStyleSheet.h" #include "pldhash.h" #include "mozilla/Attributes.h" +#include "nsString.h" class nsMappedAttributes; @@ -76,6 +77,8 @@ public: UniqueMappedAttributes(nsMappedAttributes* aMapped); void DropMappedAttributes(nsMappedAttributes* aMapped); + nsIStyleRule* LangRuleFor(const nsString& aLanguage); + private: nsHTMLStyleSheet(const nsHTMLStyleSheet& aCopy) MOZ_DELETE; nsHTMLStyleSheet& operator=(const nsHTMLStyleSheet& aCopy) MOZ_DELETE; @@ -136,6 +139,26 @@ private: virtual void MapRuleInfoInto(nsRuleData* aRuleData) MOZ_OVERRIDE; }; +public: // for mLangRuleTable structures only + + // Rule to handle xml:lang attributes, of which we have exactly one + // per language string, maintained in mLangRuleTable. + class LangRule MOZ_FINAL : public nsIStyleRule { + public: + LangRule(const nsSubstring& aLang) : mLang(aLang) {} + + NS_DECL_ISUPPORTS + + // nsIStyleRule interface + virtual void MapRuleInfoInto(nsRuleData* aRuleData) MOZ_OVERRIDE; + #ifdef DEBUG + virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE; + #endif + + nsString mLang; + }; + +private: nsCOMPtr mURL; nsIDocument* mDocument; nsRefPtr mLinkRule; @@ -145,6 +168,7 @@ private: nsRefPtr mTableTHRule; PLDHashTable mMappedAttrTable; + PLDHashTable mLangRuleTable; }; #endif /* !defined(nsHTMLStyleSheet_h_) */