Bug 721920 - Honor the 'lang' and 'xml:lang' attributes in SVG as we do in HTML. r=bz.

This commit is contained in:
Jonathan Watt 2012-02-19 20:49:34 +00:00
parent fe1bfcb339
commit 3864018bdb
10 changed files with 184 additions and 5 deletions

View File

@ -920,7 +920,7 @@ public:
/**
* Determing language. Look at the nearest ancestor element that has a lang
* attribute in the XML namespace or is an HTML element and has a lang in
* attribute in the XML namespace or is an HTML/SVG element and has a lang in
* no namespace attribute.
*/
void GetLang(nsAString& aResult) const {
@ -930,7 +930,7 @@ public:
// XHTML1 section C.7).
bool hasAttr = content->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang,
aResult);
if (!hasAttr && content->IsHTML()) {
if (!hasAttr && (content->IsHTML() || content->IsSVG())) {
hasAttr = content->GetAttr(kNameSpaceID_None, nsGkAtoms::lang,
aResult);
}

View File

@ -908,6 +908,15 @@ nsSVGElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
return NS_OK;
}
NS_IMETHODIMP_(bool)
nsSVGElement::IsAttributeMapped(const nsIAtom* name) const
{
if (name == nsGkAtoms::lang) {
return true;
}
return nsSVGElementBase::IsAttributeMapped(name);
}
// PresentationAttributes-FillStroke
/* static */ const nsGenericElement::MappedAttributeEntry
nsSVGElement::sFillStrokeMap[] = {
@ -1155,9 +1164,24 @@ MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName,
// Get the nsCSSProperty ID for our mapped attribute.
nsCSSProperty propertyID =
nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName));
bool changed; // outparam for ParseProperty. (ignored)
mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
mNodePrincipal, mDecl, &changed, false);
if (propertyID != eCSSProperty_UNKNOWN) {
bool changed; // outparam for ParseProperty. (ignored)
mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
mNodePrincipal, mDecl, &changed, false);
return;
}
NS_ABORT_IF_FALSE(aMappedAttrName == nsGkAtoms::lang,
"Only 'lang' should be unrecognized!");
// nsCSSParser doesn't know about 'lang', so we need to handle it specially.
if (aMappedAttrName == nsGkAtoms::lang) {
propertyID = eCSSProperty__x_lang;
nsCSSExpandedDataBlock block;
mDecl->ExpandTo(&block);
nsCSSValue cssValue(PromiseFlatString(aMappedAttrValue), eCSSUnit_Ident);
block.AddLonghandProperty(propertyID, cssValue);
mDecl->ValueAppended(propertyID);
mDecl->CompressFrom(&block);
}
}
already_AddRefed<css::StyleRule>
@ -1203,6 +1227,16 @@ nsSVGElement::UpdateContentStyleRule()
if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom()))
continue;
if (attrName->NamespaceID() != kNameSpaceID_None &&
!attrName->Equals(nsGkAtoms::lang, kNameSpaceID_XML)) {
continue;
}
if (attrName->Equals(nsGkAtoms::lang, kNameSpaceID_None) &&
HasAttr(kNameSpaceID_XML, nsGkAtoms::lang)) {
continue; // xml:lang has precedence
}
if (Tag() == nsGkAtoms::svg) {
// Special case: we don't want <svg> 'width'/'height' mapped into style
// if the attribute value isn't a valid <length> according to SVG (which

View File

@ -124,6 +124,8 @@ public:
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
static const MappedAttributeEntry sFillStrokeMap[];
static const MappedAttributeEntry sGraphicsMap[];
static const MappedAttributeEntry sTextContentElementsMap[];

View File

@ -74,6 +74,7 @@ _TEST_FILES = \
test_getSubStringLength.xhtml \
getSubStringLength-helper.svg \
test_isSupported.xhtml \
test_lang.xhtml \
test_nonAnimStrings.xhtml \
test_pathAnimInterpolation.xhtml \
test_pathSeg.xhtml \

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=721920
-->
<head>
<title>Test for Bug 721920</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style type="text/css">
svg text { word-spacing: 1em; }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=721920">Mozilla Bug 721920</a>
<p id="display">
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300">
<g lang="zh-Hans">
<text id="s0" y="40" style="font-size: 0">汉字</text>
<text id="s4" y="80" style="font-size: 4px">汉字</text>
<text id="s12" y="120" style="font-size: 12px">汉字</text>
<text id="s28" y="160" style="font-size: 28px">汉字</text>
</g>
</svg>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
//<![CDATA[
/** Test for Bug 721920 **/
SimpleTest.waitForExplicitFinish();
var elts = [
document.getElementById("s0"),
document.getElementById("s4"),
document.getElementById("s12"),
document.getElementById("s28")
];
function fs(idx) {
// The computed font size actually *doesn't* currently reflect the
// minimum font size preference, but things in em units do. Hence
// why we use word-spacing here.
// test_bug401046.html uses margin-bottom instead, but there's an
// SVG bug that prevents that working in SVG (bug 728723).
return getComputedStyle(elts[idx], "").wordSpacing;
}
SpecialPowers.pushPrefEnv({'clear': [['font.minimum-size.zh-CN']]}, step1);
function step1() {
is(fs(0), "0px", "at min font size 0, 0px should compute to 0px");
is(fs(1), "4px", "at min font size 0, 4px should compute to 4px");
is(fs(2), "12px", "at min font size 0, 12px should compute to 12px");
is(fs(3), "28px", "at min font size 0, 28px should compute to 28px");
SpecialPowers.pushPrefEnv({'set': [['font.minimum-size.zh-CN', 7]]}, step2);
}
function step2() {
is(fs(0), "0px", "at min font size 7, 0px should compute to 0px");
is(fs(1), "7px", "at min font size 7, 4px should compute to 7px");
is(fs(2), "12px", "at min font size 7, 12px should compute to 12px");
is(fs(3), "28px", "at min font size 7, 28px should compute to 28px");
SpecialPowers.pushPrefEnv({'set': [['font.minimum-size.zh-CN', 18]]}, step3);
}
function step3() {
is(fs(0), "0px", "at min font size 18, 0px should compute to 0px");
is(fs(1), "18px", "at min font size 18, 4px should compute to 18px");
is(fs(2), "18px", "at min font size 18, 12px should compute to 18px");
is(fs(3), "28px", "at min font size 18, 28px should compute to 28px");
SpecialPowers.pushPrefEnv({'clear': [['font.minimum-size.zh-CN']]}, SimpleTest.finish);
}
//]]>
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,16 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" lang="foo">
<title>Test the 'lang' attribute in SVG</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=368840 -->
<style type="text/css">
rect:lang(foo) {
fill: lime;
}
</style>
<rect width="100%" height="100%" fill="red"/>
</svg>

After

Width:  |  Height:  |  Size: 415 B

View File

@ -0,0 +1,16 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="foo">
<title>Test the 'xml:lang' attribute in SVG</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=368840 -->
<style type="text/css">
rect:lang(foo) {
fill: lime;
}
</style>
<rect width="100%" height="100%" fill="red"/>
</svg>

After

Width:  |  Height:  |  Size: 423 B

View File

@ -0,0 +1,16 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="foo" lang="bar">
<title>Test the 'xml:lang' attribute in SVG</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=368840 -->
<style type="text/css">
rect:lang(foo) {
fill: lime;
}
</style>
<rect width="100%" height="100%" fill="red"/>
</svg>

After

Width:  |  Height:  |  Size: 434 B

View File

@ -153,6 +153,9 @@ fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated) == gr
fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated) == gradient-live-01d.svg gradient-live-01-ref.svg # bug 696674
fails == inline-in-xul-basic-01.xul pass.svg
== invalid-text-01.svg pass.svg
== lang-attribute-01.svg pass.svg
== lang-attribute-02.svg pass.svg
== lang-attribute-03.svg pass.svg
== linearGradient-basic-01.svg pass.svg
== linearGradient-basic-02.svg pass.svg
== markers-and-group-opacity-01.svg markers-and-group-opacity-01-ref.svg

View File

@ -118,6 +118,7 @@ public:
/**
* Transfer all of the state from |aExpandedData| into this declaration.
* After calling, |aExpandedData| should be in its initial state.
* Callers must make sure mOrder is updated as necessary.
*/
void CompressFrom(nsCSSExpandedDataBlock *aExpandedData) {
NS_ABORT_IF_FALSE(!mData, "oops");