Bug 507067: Fix GetAnimVal and GetBaseVal's handling of em/ex/etc. units inside display:none elements by using nsComputedDOMStyle's method for resolving style contexts for such elements. r=dbaron

This commit is contained in:
Brian Birtles 2009-08-20 14:52:47 -07:00
Родитель 36c0b9d09f
Коммит 4e96b6eb1b
6 изменённых файлов: 217 добавлений и 12 удалений

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

@ -45,6 +45,7 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
test_animLengthUnits.xhtml \
test_bbox.xhtml \
bbox-helper.svg \
bounds-helper.svg \

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

@ -0,0 +1,124 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=507067
-->
<head>
<title>Test for units of SVG animated lengths</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=507067">Mozilla Bug 507067</a>
<p id="display"></p>
<div id="content" style="display: none">
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px">
<g font-size="10px">
<circle cx="-100" cy="20" r="15" fill="blue" id="circle">
<animate attributeName="cx" from="0em" to="10em" dur="8s" begin="1s"
fill="freeze"/>
</circle>
</g>
</svg>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
/** Test units of animated lengths **/
/* Global Variables */
const svgns="http://www.w3.org/2000/svg";
var svg = document.getElementById("svg");
var circle = document.getElementById('circle');
var animate = document.getElementById('animate');
SimpleTest.waitForExplicitFinish();
// Interop comments are based on:
//
// Opera -- 10 beta 2
// WebKit -- July 09 trunk build
// Batik -- 1.7
// Firefox -- July 09 trunk build
//
function main() {
// Sanity check: check initial values
is(circle.cx.baseVal.valueInSpecifiedUnits, -100,
"Unexpected initial baseVal");
is(circle.cx.baseVal.unitType, SVGLength.SVG_LENGTHTYPE_NUMBER,
"Unexpected initial baseVal units");
is(circle.cx.animVal.valueInSpecifiedUnits, -100,
"Unexpected initial animVal");
is(circle.cx.animVal.unitType, SVGLength.SVG_LENGTHTYPE_NUMBER,
"Unexpected initial animVal units");
// Sample mid-way through the animation
svg.pauseAnimations();
svg.setCurrentTime(5);
// (1) Check the absolute value is right
//
// We're not too worried about the units. Based on our testing we get:
// Opera: Will use user units for the animVal
// Safari: Doesn't work
// Batik: Will use the units specified on the animation function provided they
// are the same
// FF: Will use the units of the baseVal for the animVal
//
is(circle.cx.baseVal.value, -100,
"(1) Unexpected value for baseVal during animation");
is(circle.cx.animVal.value, 50,
"(1) Unexpected value for animVal during animation");
// Change font-size and check
circle.parentNode.setAttribute('font-size', '5px');
// Currently, changing the font-size on a parent doesn't force a resample (see
// bug 508206) so we have to give the animation a chance to run
setTimeout("checkAfterChangeFontSize()",100);
}
function checkAfterChangeFontSize() {
// (2) Check that changing the font-size of the parent element is reflected in
// the anim val
is(circle.cx.baseVal.value, -100,
"(2) Unexpected value for baseVal after changing font-size during " +
"animation");
is(circle.cx.animVal.value, 25,
"(2) Unexpected value for animVal after changing font-size during " +
"animation");
// Do the same again, when the animation is frozen
svg.setCurrentTime(10);
circle.parentNode.setAttribute('font-size', '7px');
// Again, due to bug 508206 we need to give the animation a chance to resample
setTimeout("checkWhilstFrozen()",100);
}
function checkWhilstFrozen() {
// (3) Check that changing the font-size of the parent element is reflected in
// the anim val
is(circle.cx.baseVal.value, -100,
"(3) Unexpected value for baseVal after changing font-size whilst " +
"frozen");
is(circle.cx.animVal.value, 70,
"(3) Unexpected value for animVal after changing font-size whilst " +
"frozen");
SimpleTest.finish();
}
netscape.security.PrivilegeManager.enablePrivilege("UniversalPreferencesRead");
if (navigator.preference('svg.smil.enabled')) {
window.addEventListener("load", main, false);
} else {
ok(true); // Skip tests but don't report 'todo' either
SimpleTest.finish();
}
]]>
</script>
</pre>
</body>
</html>

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

@ -354,7 +354,35 @@ nsComputedDOMStyle::GetStyleContextForContent(nsIContent* aContent,
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eELEMENT),
"aContent must be an element");
if (!aPseudo) {
// If there's no pres shell, get it from the content
if (!aPresShell) {
aPresShell = GetPresShellForContent(aContent);
if (!aPresShell)
return nsnull;
}
aPresShell->FlushPendingNotifications(Flush_Style);
}
return GetStyleContextForContentNoFlush(aContent, aPseudo, aPresShell);
}
/* static */
already_AddRefed<nsStyleContext>
nsComputedDOMStyle::GetStyleContextForContentNoFlush(nsIContent* aContent,
nsIAtom* aPseudo,
nsIPresShell* aPresShell)
{
NS_ABORT_IF_FALSE(aContent, "NULL content node");
// If there's no pres shell, get it from the content
if (!aPresShell) {
aPresShell = GetPresShellForContent(aContent);
if (!aPresShell)
return nsnull;
}
if (!aPseudo) {
nsIFrame* frame = aPresShell->GetPrimaryFrameFor(aContent);
if (frame) {
nsStyleContext* result = GetStyleContextForFrame(frame);
@ -390,6 +418,17 @@ nsComputedDOMStyle::GetStyleContextForContent(nsIContent* aContent,
return styleSet->ResolveStyleFor(aContent, parentContext);
}
/* static */
nsIPresShell*
nsComputedDOMStyle::GetPresShellForContent(nsIContent* aContent)
{
nsIDocument* currentDoc = aContent->GetCurrentDoc();
if (!currentDoc)
return nsnull;
return currentDoc->GetPrimaryShell();
}
NS_IMETHODIMP
nsComputedDOMStyle::GetPropertyCSSValue(const nsAString& aPropertyName,
nsIDOMCSSValue** aReturn)

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

@ -86,6 +86,13 @@ public:
GetStyleContextForContent(nsIContent* aContent, nsIAtom* aPseudo,
nsIPresShell* aPresShell);
static already_AddRefed<nsStyleContext>
GetStyleContextForContentNoFlush(nsIContent* aContent, nsIAtom* aPseudo,
nsIPresShell* aPresShell);
static nsIPresShell*
GetPresShellForContent(nsIContent* aContent);
private:
void AssertFlushedPendingReflows() {
NS_ASSERTION(mFlushedPendingReflows,

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

@ -85,6 +85,7 @@
#include "nsSVGIntegrationUtils.h"
#include "nsSVGFilterPaintCallback.h"
#include "nsSVGGeometryFrame.h"
#include "nsComputedDOMStyle.h"
gfxASurface *nsSVGUtils::mThebesComputationalSurface = nsnull;
@ -267,39 +268,69 @@ nsSVGUtils::GetParentElement(nsIContent *aContent)
float
nsSVGUtils::GetFontSize(nsIContent *aContent)
{
nsIFrame* frame = GetFrameForContent(aContent);
if (!frame) {
NS_WARNING("no frame in GetFontSize()");
nsRefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForContentNoFlush(aContent, nsnull,
nsnull);
if (!styleContext) {
NS_WARNING("Couldn't get style context for content in GetFontStyle");
return 1.0f;
}
return GetFontSize(frame);
return GetFontSize(styleContext);
}
float
nsSVGUtils::GetFontSize(nsIFrame *aFrame)
{
return nsPresContext::AppUnitsToFloatCSSPixels(aFrame->GetStyleFont()->mSize) /
aFrame->PresContext()->TextZoom();
NS_ABORT_IF_FALSE(aFrame, "NULL frame in GetFontSize");
return GetFontSize(aFrame->GetStyleContext());
}
float
nsSVGUtils::GetFontSize(nsStyleContext *aStyleContext)
{
NS_ABORT_IF_FALSE(aStyleContext, "NULL style context in GetFontSize");
nsPresContext *presContext = aStyleContext->PresContext();
NS_ABORT_IF_FALSE(presContext, "NULL pres context in GetFontSize");
nscoord fontSize = aStyleContext->GetStyleFont()->mSize;
return nsPresContext::AppUnitsToFloatCSSPixels(fontSize) /
presContext->TextZoom();
}
float
nsSVGUtils::GetFontXHeight(nsIContent *aContent)
{
nsIFrame* frame = GetFrameForContent(aContent);
if (!frame) {
NS_WARNING("no frame in GetFontXHeight()");
nsRefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForContentNoFlush(aContent, nsnull,
nsnull);
if (!styleContext) {
NS_WARNING("Couldn't get style context for content in GetFontStyle");
return 1.0f;
}
return GetFontXHeight(frame);
return GetFontXHeight(styleContext);
}
float
nsSVGUtils::GetFontXHeight(nsIFrame *aFrame)
{
NS_ABORT_IF_FALSE(aFrame, "NULL frame in GetFontXHeight");
return GetFontXHeight(aFrame->GetStyleContext());
}
float
nsSVGUtils::GetFontXHeight(nsStyleContext *aStyleContext)
{
NS_ABORT_IF_FALSE(aStyleContext, "NULL style context in GetFontXHeight");
nsPresContext *presContext = aStyleContext->PresContext();
NS_ABORT_IF_FALSE(presContext, "NULL pres context in GetFontXHeight");
nsCOMPtr<nsIFontMetrics> fontMetrics;
nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fontMetrics));
nsLayoutUtils::GetFontMetricsForStyleContext(aStyleContext,
getter_AddRefs(fontMetrics));
if (!fontMetrics) {
NS_WARNING("no FontMetrics in GetFontXHeight()");
@ -309,7 +340,7 @@ nsSVGUtils::GetFontXHeight(nsIFrame *aFrame)
nscoord xHeight;
fontMetrics->GetXHeight(xHeight);
return nsPresContext::AppUnitsToFloatCSSPixels(xHeight) /
aFrame->PresContext()->TextZoom();
presContext->TextZoom();
}
void

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

@ -53,6 +53,7 @@
class nsIDocument;
class nsPresContext;
class nsIContent;
class nsStyleContext;
class nsStyleCoord;
class nsFrameList;
class nsIFrame;
@ -203,11 +204,13 @@ public:
*/
static float GetFontSize(nsIContent *aContent);
static float GetFontSize(nsIFrame *aFrame);
static float GetFontSize(nsStyleContext *aStyleContext);
/*
* Get an x-height of of an nsIContent
*/
static float GetFontXHeight(nsIContent *aContent);
static float GetFontXHeight(nsIFrame *aFrame);
static float GetFontXHeight(nsStyleContext *aStyleContext);
/*
* Converts image data from premultipled to unpremultiplied alpha