diff --git a/content/Makefile.in b/content/Makefile.in index 3189294ae6c..6e44e446f74 100644 --- a/content/Makefile.in +++ b/content/Makefile.in @@ -53,6 +53,10 @@ ifdef MOZ_XTF DIRS += xtf endif +ifdef MOZ_MATHML +DIRS += mathml +endif + DIRS += events ifdef ENABLE_TESTS diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 981c1049ece..9056a617fc4 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -275,7 +275,7 @@ public: CopyASCIItoUTF16(mContentLanguage, aContentLanguage); } - // The state BidiEnabled should persist across multiple views + // The states BidiEnabled and MathMLEnabled should persist across multiple views // (screen, print) of the same document. /** @@ -297,6 +297,19 @@ public: { mBidiEnabled = aBidiEnabled; } + + /** + * Check if the document contains (or has contained) any MathML elements. + */ + PRBool GetMathMLEnabled() const + { + return mMathMLEnabled; + } + + void SetMathMLEnabled() + { + mMathMLEnabled = PR_TRUE; + } /** * Ask this document whether it's the initial document in its window. @@ -965,6 +978,8 @@ protected: // True if BIDI is enabled. PRPackedBool mBidiEnabled; + // True if a MathML element has ever been owned by this document. + PRPackedBool mMathMLEnabled; // True if this document is the initial document for a window. This should // basically be true only for documents that exist in newly-opened windows or diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index 692a68684c6..9c1fd5640ee 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -180,7 +180,9 @@ public: eDOCUMENT_FRAGMENT = 1 << 11, /** data nodes (comments, PIs, text). Nodes of this type always returns a non-null value for nsIContent::GetText() */ - eDATA_NODE = 1 << 12 + eDATA_NODE = 1 << 12, + /** nsMathMLElement */ + eMATHML = 1 << 13, }; /** diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index c4779856dd0..85013822430 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -136,6 +136,7 @@ CPPSRCS = \ nsImageLoadingContent.cpp \ nsLineBreaker.cpp \ nsLoadListenerProxy.cpp \ + nsMappedAttributeElement.cpp \ nsMappedAttributes.cpp \ nsNameSpaceManager.cpp \ nsNoDataProtocolContentPolicy.cpp \ diff --git a/content/base/src/nsAttrAndChildArray.cpp b/content/base/src/nsAttrAndChildArray.cpp index eec36581a61..9d1d7e27306 100644 --- a/content/base/src/nsAttrAndChildArray.cpp +++ b/content/base/src/nsAttrAndChildArray.cpp @@ -42,7 +42,7 @@ */ #include "nsAttrAndChildArray.h" -#include "nsGenericHTMLElement.h" +#include "nsMappedAttributeElement.h" #include "prmem.h" #include "prbit.h" #include "nsString.h" @@ -561,7 +561,7 @@ nsAttrAndChildArray::IndexOfAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID) cons nsresult nsAttrAndChildArray::SetAndTakeMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue, - nsGenericHTMLElement* aContent, + nsMappedAttributeElement* aContent, nsHTMLStyleSheet* aSheet) { nsRefPtr mapped; @@ -651,7 +651,7 @@ nsAttrAndChildArray::MappedAttrCount() const } nsresult -nsAttrAndChildArray::GetModifiableMapped(nsGenericHTMLElement* aContent, +nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent, nsHTMLStyleSheet* aSheet, PRBool aWillAddAttr, nsMappedAttributes** aModifiable) diff --git a/content/base/src/nsAttrAndChildArray.h b/content/base/src/nsAttrAndChildArray.h index 5d0c1cee8ac..31fe69c049b 100644 --- a/content/base/src/nsAttrAndChildArray.h +++ b/content/base/src/nsAttrAndChildArray.h @@ -53,7 +53,7 @@ class nsIContent; class nsMappedAttributes; class nsHTMLStyleSheet; class nsRuleWalker; -class nsGenericHTMLElement; +class nsMappedAttributeElement; #define ATTRCHILD_ARRAY_GROWSIZE 8 #define ATTRCHILD_ARRAY_LINEAR_THRESHOLD 32 @@ -120,7 +120,7 @@ public: PRInt32 IndexOfAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID = kNameSpaceID_None) const; nsresult SetAndTakeMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue, - nsGenericHTMLElement* aContent, + nsMappedAttributeElement* aContent, nsHTMLStyleSheet* aSheet); nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet); void WalkMappedAttributeStyleRules(nsRuleWalker* aRuleWalker); @@ -134,7 +134,7 @@ private: PRUint32 NonMappedAttrCount() const; PRUint32 MappedAttrCount() const; - nsresult GetModifiableMapped(nsGenericHTMLElement* aContent, + nsresult GetModifiableMapped(nsMappedAttributeElement* aContent, nsHTMLStyleSheet* aSheet, PRBool aWillAddAttr, nsMappedAttributes** aModifiable); diff --git a/content/base/src/nsMappedAttributeElement.cpp b/content/base/src/nsMappedAttributeElement.cpp new file mode 100644 index 00000000000..93bc0622a24 --- /dev/null +++ b/content/base/src/nsMappedAttributeElement.cpp @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mats Palmgren + * Daniel Kraft + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsMappedAttributeElement.h" +#include "nsIDocument.h" + +nsresult +nsMappedAttributeElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + PRBool aCompileEventHandlers) +{ + nsresult rv = nsMappedAttributeElementBase::BindToTree(aDocument, aParent, + aBindingParent, + aCompileEventHandlers); + NS_ENSURE_SUCCESS(rv, rv); + + if (aDocument) { + // If we're in a document now, let our mapped attrs know what their new + // sheet is. + nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet(); + if (sheet) { + mAttrsAndChildren.SetMappedAttrStyleSheet(sheet); + } + } + + return rv; +} + +nsresult +nsMappedAttributeElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker) +{ + mAttrsAndChildren.WalkMappedAttributeStyleRules(aRuleWalker); + return NS_OK; +} + +PRBool +nsMappedAttributeElement::SetMappedAttribute(nsIDocument* aDocument, + nsIAtom* aName, + nsAttrValue& aValue, + nsresult* aRetval) +{ + NS_PRECONDITION(aDocument == GetCurrentDoc(), "Unexpected document"); + nsHTMLStyleSheet* sheet = aDocument ? + aDocument->GetAttributeStyleSheet() : nsnull; + + *aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue, + this, sheet); + return PR_TRUE; +} + +nsMapRuleToAttributesFunc +nsMappedAttributeElement::GetAttributeMappingFunction() const +{ + return &MapNoAttributesInto; +} + +void +nsMappedAttributeElement::MapNoAttributesInto(const nsMappedAttributes* aAttributes, + nsRuleData* aData) +{ +} diff --git a/content/base/src/nsMappedAttributeElement.h b/content/base/src/nsMappedAttributeElement.h new file mode 100644 index 00000000000..be3612680bd --- /dev/null +++ b/content/base/src/nsMappedAttributeElement.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Daniel Kraft + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/** + * nsMappedAttributeElement is the base for elements supporting style mapped + * attributes via nsMappedAttributes (HTML and MathML). + */ + +#ifndef NS_MAPPEDATTRIBUTEELEMENT_H_ +#define NS_MAPPEDATTRIBUTEELEMENT_H_ + +#include "nsStyledElement.h" + +class nsMappedAttributes; +class nsRuleData; + +typedef void (*nsMapRuleToAttributesFunc)(const nsMappedAttributes* aAttributes, + nsRuleData* aData); + +typedef nsStyledElement nsMappedAttributeElementBase; + +class nsMappedAttributeElement : public nsMappedAttributeElementBase +{ + +protected: + + nsMappedAttributeElement(nsINodeInfo *aNodeInfo) + : nsMappedAttributeElementBase(aNodeInfo) + {} + +public: + virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + PRBool aCompileEventHandlers); + + virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; + + static void MapNoAttributesInto(const nsMappedAttributes* aAttributes, + nsRuleData* aRuleData); + + NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker); + virtual PRBool SetMappedAttribute(nsIDocument* aDocument, + nsIAtom* aName, + nsAttrValue& aValue, + nsresult* aRetval); +}; + +#endif // NS_MAPPEDATTRIBUTEELEMENT_H_ diff --git a/content/base/src/nsMappedAttributes.h b/content/base/src/nsMappedAttributes.h index 9f00c6853b0..5c86e3be38b 100644 --- a/content/base/src/nsMappedAttributes.h +++ b/content/base/src/nsMappedAttributes.h @@ -45,7 +45,7 @@ #define nsMappedAttributes_h___ #include "nsAttrAndChildArray.h" -#include "nsGenericHTMLElement.h" +#include "nsMappedAttributeElement.h" #include "nsIStyleRule.h" class nsIAtom; diff --git a/content/events/public/nsIEventStateManager.h b/content/events/public/nsIEventStateManager.h index 24afac8bf9a..e1986e5a9e6 100644 --- a/content/events/public/nsIEventStateManager.h +++ b/content/events/public/nsIEventStateManager.h @@ -215,5 +215,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIEventStateManager, NS_IEVENTSTATEMANAGER_IID) // Content is of a type that gecko can't handle #define NS_EVENT_STATE_TYPE_UNSUPPORTED \ 0x00400000 +#ifdef MOZ_MATHML +#define NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL 0x00800000 +#endif #endif // nsIEventStateManager_h__ diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 696b69ba752..e2bacb4d0c2 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -1146,13 +1146,6 @@ nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, htmlDocument->ChangeContentEditableCount(this, +1); } } - - // If we're in a document now, let our mapped attrs know what their new - // sheet is. - nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet(); - if (sheet) { - mAttrsAndChildren.SetMappedAttrStyleSheet(sheet); - } } return rv; @@ -1435,13 +1428,6 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, aNotify); } -nsresult -nsGenericHTMLElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker) -{ - mAttrsAndChildren.WalkMappedAttributeStyleRules(aRuleWalker); - return NS_OK; -} - already_AddRefed nsGenericHTMLElement::GetBaseURI() const { @@ -1540,22 +1526,6 @@ nsGenericHTMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map)); } -PRBool -nsGenericHTMLElement::SetMappedAttribute(nsIDocument* aDocument, - nsIAtom* aName, - nsAttrValue& aValue, - nsresult* aRetval) -{ - NS_PRECONDITION(aDocument == GetCurrentDoc(), "Unexpected document"); - nsHTMLStyleSheet* sheet = aDocument ? - aDocument->GetAttributeStyleSheet() : nsnull; - - *aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue, - this, sheet); - return PR_TRUE; -} - - nsMapRuleToAttributesFunc nsGenericHTMLElement::GetAttributeMappingFunction() const { diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 8d0cad61016..15befa464f6 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -38,7 +38,7 @@ #ifndef nsGenericHTMLElement_h___ #define nsGenericHTMLElement_h___ -#include "nsStyledElement.h" +#include "nsMappedAttributeElement.h" #include "nsIDOMHTMLElement.h" #include "nsINameSpaceManager.h" // for kNameSpaceID_None #include "nsIFormControl.h" @@ -50,7 +50,6 @@ class nsIDOMAttr; class nsIDOMEventListener; class nsIDOMNodeList; class nsIFrame; -class nsMappedAttributes; class nsIStyleRule; class nsChildContentList; class nsDOMCSSDeclaration; @@ -64,12 +63,8 @@ class nsILayoutHistoryState; class nsIEditor; struct nsRect; struct nsSize; -struct nsRuleData; -typedef void (*nsMapRuleToAttributesFunc)(const nsMappedAttributes* aAttributes, - nsRuleData* aData); - -typedef nsStyledElement nsGenericHTMLElementBase; +typedef nsMappedAttributeElement nsGenericHTMLElementBase; /** * A common superclass for HTML elements @@ -239,11 +234,9 @@ public: { return mAttrsAndChildren.GetAttr(aAttr); } - virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; virtual void UpdateEditableState(); - NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker); already_AddRefed GetBaseURI() const; virtual PRBool ParseAttribute(PRInt32 aNamespaceID, @@ -252,10 +245,7 @@ public: nsAttrValue& aResult); NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; - virtual PRBool SetMappedAttribute(nsIDocument* aDocument, - nsIAtom* aName, - nsAttrValue& aValue, - nsresult* aRetval); + virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; /** * Get the base target for any links within this piece diff --git a/content/html/document/src/nsImageDocument.cpp b/content/html/document/src/nsImageDocument.cpp index daccdaee417..212195bba24 100644 --- a/content/html/document/src/nsImageDocument.cpp +++ b/content/html/document/src/nsImageDocument.cpp @@ -608,7 +608,7 @@ nsresult nsImageDocument::CheckOverflowing(PRBool changeState) { /* Create a scope so that the style context gets destroyed before we might - * call ClearStyleDataAndReflow. Also, holding onto pointers to the + * call RebuildStyleData. Also, holding onto pointers to the * presentatation through style resolution is potentially dangerous. */ { diff --git a/content/mathml/Makefile.in b/content/mathml/Makefile.in new file mode 100644 index 00000000000..71838f2e688 --- /dev/null +++ b/content/mathml/Makefile.in @@ -0,0 +1,47 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = content + +include $(topsrcdir)/config/rules.mk diff --git a/content/mathml/content/Makefile.in b/content/mathml/content/Makefile.in new file mode 100644 index 00000000000..ac483e08e95 --- /dev/null +++ b/content/mathml/content/Makefile.in @@ -0,0 +1,48 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = src + +include $(topsrcdir)/config/rules.mk + diff --git a/content/mathml/content/src/Makefile.in b/content/mathml/content/src/Makefile.in new file mode 100644 index 00000000000..9d62c66d299 --- /dev/null +++ b/content/mathml/content/src/Makefile.in @@ -0,0 +1,87 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Mozilla MathML DOM code. +# +# The Initial Developer of the Original Code is +# mozilla.org. +# Portions created by the Initial Developer are Copyright (C) 2007 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Vlad Sukhoy (original developer) +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = content +LIBRARY_NAME = gkcontentmathml_s +LIBXUL_LIBRARY = 1 +REQUIRES = xpcom \ + string \ + layout \ + content \ + widget \ + gfx \ + dom \ + js \ + locale \ + pref \ + webshell \ + unicharutil \ + docshell \ + thebes \ + $(NULL) + +CPPSRCS = \ + nsMathMLElement.cpp \ + nsMathMLElementFactory.cpp \ + $(NULL) + +include $(topsrcdir)/config/config.mk + +# we don't want the shared lib, but we want to force the creation of a static +# lib. +FORCE_STATIC_LIB = 1 + +EXPORTS = \ + $(NULL) + + +include $(topsrcdir)/config/rules.mk + +INCLUDES += \ + -I$(srcdir)/../../../shared/public \ + -I$(srcdir)/../../../base/src \ + $(NULL) + +DEFINES += -D_IMPL_NS_LAYOUT diff --git a/content/mathml/content/src/nsMathMLElement.cpp b/content/mathml/content/src/nsMathMLElement.cpp new file mode 100644 index 00000000000..3e957d67248 --- /dev/null +++ b/content/mathml/content/src/nsMathMLElement.cpp @@ -0,0 +1,457 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is MathML DOM code. + * + * The Initial Developer of the Original Code is + * mozilla.org. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vlad Sukhoy (original developer) + * Daniel Kraft (nsMathMLElement patch, attachment 262925) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsMathMLElement.h" +#include "nsDOMClassInfoID.h" // for eDOMClassInfo_MathElement_id. +#include "nsGkAtoms.h" +#include "nsCRT.h" +#include "nsRuleData.h" +#include "nsCSSValue.h" +#include "nsMappedAttributes.h" +#include "nsStyleConsts.h" +#include "nsIDocument.h" +#include "nsIEventStateManager.h" +#include "nsPresShellIterator.h" +#include "nsIPresShell.h" +#include "nsPresContext.h" +#include "nsDOMClassInfoID.h" + +//---------------------------------------------------------------------- +// nsISupports methods: + +NS_IMETHODIMP +nsMathMLElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + NS_PRECONDITION(aInstancePtr, "null out param"); + + nsresult rv = nsMathMLElementBase::QueryInterface(aIID, aInstancePtr); + + if (NS_SUCCEEDED(rv)) + return rv; + + nsISupports *inst = nsnull; + + if (aIID.Equals(NS_GET_IID(nsIDOMNode))) { + inst = static_cast(this); + } else if (aIID.Equals(NS_GET_IID(nsIDOMElement))) { + inst = static_cast(this); + } else if (aIID.Equals(NS_GET_IID(nsIClassInfo))) { + inst = NS_GetDOMClassInfoInstance(eDOMClassInfo_Element_id); + NS_ENSURE_TRUE(inst, NS_ERROR_OUT_OF_MEMORY); + } else { + return PostQueryInterface(aIID, aInstancePtr); + } + + NS_ADDREF(inst); + + *aInstancePtr = inst; + + return NS_OK; +} + +NS_IMPL_ADDREF_INHERITED(nsMathMLElement, nsMathMLElementBase) +NS_IMPL_RELEASE_INHERITED(nsMathMLElement, nsMathMLElementBase) + +nsresult +nsMathMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + PRBool aCompileEventHandlers) +{ + static const char kMathMLStyleSheetURI[] = "resource://gre/res/mathml.css"; + + nsresult rv = nsMathMLElementBase::BindToTree(aDocument, aParent, + aBindingParent, + aCompileEventHandlers); + NS_ENSURE_SUCCESS(rv, rv); + + if (aDocument && !aDocument->GetMathMLEnabled()) { + // Enable MathML and setup the style sheet during binding, not element + // construction, because we could move a MathML element from the document + // that created it to another document. + aDocument->SetMathMLEnabled(); + aDocument->EnsureCatalogStyleSheet(kMathMLStyleSheetURI); + + // Rebuild style data for all the presshells, because style system + // optimizations may have taken place assuming MathML was disabled. + // (See nsRuleNode::CheckSpecifiedProperties.) + // nsPresShellIterator skips hidden presshells, but that's OK because + // if we're changing the document for one of those presshells the whole + // presshell will be torn down. + nsPresShellIterator iter(aDocument); + nsCOMPtr shell; + while ((shell = iter.GetNextShell()) != nsnull) { + shell->GetPresContext()->PostRebuildAllStyleDataEvent(); + } + } + + return rv; +} + +PRBool +nsMathMLElement::ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) +{ + if (aNamespaceID == kNameSpaceID_None) { + if (aAttribute == nsGkAtoms::color || + aAttribute == nsGkAtoms::mathcolor_ || + aAttribute == nsGkAtoms::background || + aAttribute == nsGkAtoms::mathbackground_) { + return aResult.ParseColor(aValue, GetOwnerDoc()); + } + } + + return nsMathMLElementBase::ParseAttribute(aNamespaceID, aAttribute, + aValue, aResult); +} + +static nsGenericElement::MappedAttributeEntry sTokenStyles[] = { + { &nsGkAtoms::mathsize_ }, + { &nsGkAtoms::fontsize_ }, + { &nsGkAtoms::mathcolor_ }, + { &nsGkAtoms::color }, + { &nsGkAtoms::mathbackground_ }, + { &nsGkAtoms::fontfamily_ }, + { nsnull } +}; + +static nsGenericElement::MappedAttributeEntry sEnvironmentStyles[] = { + { &nsGkAtoms::scriptlevel_ }, + { &nsGkAtoms::scriptminsize_ }, + { &nsGkAtoms::scriptsizemultiplier_ }, + { &nsGkAtoms::background }, + { nsnull } +}; + +PRBool +nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const +{ + static const MappedAttributeEntry* const tokenMap[] = { + sTokenStyles + }; + static const MappedAttributeEntry* const mstyleMap[] = { + sTokenStyles, + sEnvironmentStyles + }; + + // We don't support mglyph (yet). + nsIAtom* tag = Tag(); + if (tag == nsGkAtoms::ms_ || tag == nsGkAtoms::mi_ || + tag == nsGkAtoms::mn_ || tag == nsGkAtoms::mo_ || + tag == nsGkAtoms::mtext_) + return FindAttributeDependence(aAttribute, tokenMap, + NS_ARRAY_LENGTH(tokenMap)); + if (tag == nsGkAtoms::mstyle_) + return FindAttributeDependence(aAttribute, mstyleMap, + NS_ARRAY_LENGTH(mstyleMap)); + return PR_FALSE; +} + +nsMapRuleToAttributesFunc +nsMathMLElement::GetAttributeMappingFunction() const +{ + // It doesn't really matter what our tag is here, because only attributes + // that satisfy IsAttributeMapped will be stored in the mapped attributes + // list and available to the mapping function + return &MapMathMLAttributesInto; +} + +// ================ +// Utilities for parsing and retrieving numeric values + +/* +The REC says: + An explicit plus sign ('+') is not allowed as part of a numeric value + except when it is specifically listed in the syntax (as a quoted '+' + or "+"), + + Units allowed + ID Description + em ems (font-relative unit traditionally used for horizontal lengths) + ex exs (font-relative unit traditionally used for vertical lengths) + px pixels, or pixel size of a "typical computer display" + in inches (1 inch = 2.54 centimeters) + cm centimeters + mm millimeters + pt points (1 point = 1/72 inch) + pc picas (1 pica = 12 points) + % percentage of default value + +Implementation here: + The numeric value is valid only if it is of the form [-] nnn.nnn + [h/v-unit] +*/ + +/* static */ PRBool +nsMathMLElement::ParseNumericValue(const nsString& aString, + nsCSSValue& aCSSValue, + PRBool aRequireLengthUnit) +{ + nsAutoString str(aString); + str.CompressWhitespace(); // aString is const in this code... + + PRInt32 stringLength = str.Length(); + if (!stringLength) + return PR_FALSE; + + nsAutoString number, unit; + + // see if the negative sign is there + PRInt32 i = 0; + PRUnichar c = str[0]; + if (c == '-') { + number.Append(c); + i++; + + // skip any space after the negative sign + if (i < stringLength && nsCRT::IsAsciiSpace(str[i])) + i++; + } + + // Gather up characters that make up the number + PRBool gotDot = PR_FALSE; + for ( ; i < stringLength; i++) { + c = str[i]; + if (gotDot && c == '.') + return PR_FALSE; // two dots encountered + else if (c == '.') + gotDot = PR_TRUE; + else if (!nsCRT::IsAsciiDigit(c)) { + str.Right(unit, stringLength - i); + // some authors leave blanks before the unit, but that shouldn't + // be allowed, so don't CompressWhitespace on 'unit'. + break; + } + number.Append(c); + } + + // Convert number to floating point + PRInt32 errorCode; + float floatValue = number.ToFloat(&errorCode); + if (NS_FAILED(errorCode)) + return PR_FALSE; + + nsCSSUnit cssUnit; + if (unit.IsEmpty()) { + if (aRequireLengthUnit) { + // We are supposed to have a length unit, but there isn't one. + // If the value is 0 we can just call it "pixels" otherwise + // this is illegal. + if (floatValue != 0.0) + return PR_FALSE; + cssUnit = eCSSUnit_Pixel; + } else { + // no explicit unit, this is a number that will act as a multiplier + cssUnit = eCSSUnit_Number; + } + } + else if (unit.EqualsLiteral("%")) { + aCSSValue.SetPercentValue(floatValue / 100.0f); + return PR_TRUE; + } + else if (unit.EqualsLiteral("em")) cssUnit = eCSSUnit_EM; + else if (unit.EqualsLiteral("ex")) cssUnit = eCSSUnit_XHeight; + else if (unit.EqualsLiteral("px")) cssUnit = eCSSUnit_Pixel; + else if (unit.EqualsLiteral("in")) cssUnit = eCSSUnit_Inch; + else if (unit.EqualsLiteral("cm")) cssUnit = eCSSUnit_Centimeter; + else if (unit.EqualsLiteral("mm")) cssUnit = eCSSUnit_Millimeter; + else if (unit.EqualsLiteral("pt")) cssUnit = eCSSUnit_Point; + else if (unit.EqualsLiteral("pc")) cssUnit = eCSSUnit_Pica; + else // unexpected unit + return PR_FALSE; + + aCSSValue.SetFloatValue(floatValue, cssUnit); + return PR_TRUE; +} + +void +nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes, + nsRuleData* aData) +{ + if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) { + const nsAttrValue* value = + aAttributes->GetAttr(nsGkAtoms::scriptsizemultiplier_); + if (value && value->Type() == nsAttrValue::eString && + aData->mFontData->mScriptSizeMultiplier.GetUnit() == eCSSUnit_Null) { + nsAutoString str(value->GetStringValue()); + str.CompressWhitespace(); + // MathML numbers can't have leading '+' + if (str.Length() > 0 && str.CharAt(0) != '+') { + PRInt32 errorCode; + float floatValue = str.ToFloat(&errorCode); + // Negative scriptsizemultipliers are not parsed + if (NS_SUCCEEDED(errorCode) && floatValue >= 0.0f) { + aData->mFontData->mScriptSizeMultiplier. + SetFloatValue(floatValue, eCSSUnit_Number); + } + } + } + + value = aAttributes->GetAttr(nsGkAtoms::scriptminsize_); + if (value && value->Type() == nsAttrValue::eString && + aData->mFontData->mScriptMinSize.GetUnit() == eCSSUnit_Null) { + ParseNumericValue(value->GetStringValue(), + aData->mFontData->mScriptMinSize, PR_TRUE); + } + + value = aAttributes->GetAttr(nsGkAtoms::scriptlevel_); + if (value && value->Type() == nsAttrValue::eString && + aData->mFontData->mScriptLevel.GetUnit() == eCSSUnit_Null) { + nsAutoString str(value->GetStringValue()); + str.CompressWhitespace(); + if (str.Length() > 0) { + PRInt32 errorCode; + PRInt32 intValue = str.ToInteger(&errorCode); + if (NS_SUCCEEDED(errorCode)) { + // This is kind of cheesy ... if the scriptlevel has a sign, + // then it's a relative value and we store the nsCSSValue as an + // Integer to indicate that. Otherwise we store it as a Number + // to indicate that the scriptlevel is absolute. + PRUnichar ch = str.CharAt(0); + if (ch == '+' || ch == '-') { + aData->mFontData->mScriptLevel.SetIntValue(intValue, eCSSUnit_Integer); + } else { + aData->mFontData->mScriptLevel.SetFloatValue(intValue, eCSSUnit_Number); + } + } + } + } + + PRBool parseSizeKeywords = PR_TRUE; + value = aAttributes->GetAttr(nsGkAtoms::mathsize_); + if (!value) { + parseSizeKeywords = PR_FALSE; + value = aAttributes->GetAttr(nsGkAtoms::fontsize_); + } + if (value && value->Type() == nsAttrValue::eString && + aData->mFontData->mSize.GetUnit() == eCSSUnit_Null) { + nsAutoString str(value->GetStringValue()); + if (!ParseNumericValue(str, aData->mFontData->mSize, PR_TRUE) && + parseSizeKeywords) { + static const char sizes[3][7] = { "small", "normal", "big" }; + static const PRInt32 values[NS_ARRAY_LENGTH(sizes)] = { + NS_STYLE_FONT_SIZE_SMALL, NS_STYLE_FONT_SIZE_MEDIUM, + NS_STYLE_FONT_SIZE_LARGE + }; + str.CompressWhitespace(); + for (PRInt32 i = 0; i < NS_ARRAY_LENGTH(sizes); ++i) { + if (str.EqualsASCII(sizes[i])) { + aData->mFontData->mSize.SetIntValue(values[i], eCSSUnit_Enumerated); + break; + } + } + } + } + + value = aAttributes->GetAttr(nsGkAtoms::fontfamily_); + if (value && value->Type() == nsAttrValue::eString && + aData->mFontData->mFamily.GetUnit() == eCSSUnit_Null) { + aData->mFontData->mFamily.SetStringValue(value->GetStringValue(), + eCSSUnit_String); + aData->mFontData->mFamilyFromHTML = PR_FALSE; + } + } + + if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)) { + const nsAttrValue* value = + aAttributes->GetAttr(nsGkAtoms::mathbackground_); + if (!value) { + value = aAttributes->GetAttr(nsGkAtoms::background); + } + if (value && aData->mColorData->mBackColor.GetUnit() == eCSSUnit_Null) { + nscolor color; + if (value->GetColorValue(color)) { + aData->mColorData->mBackColor.SetColorValue(color); + } else { + nsAutoString str(value->GetStringValue()); + str.CompressWhitespace(); + if (str.EqualsLiteral("transparent")) { + aData->mColorData->mBackColor.SetColorValue(NS_RGBA(0,0,0,0)); + } + } + } + } + + if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Color)) { + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::mathcolor_); + if (!value) { + value = aAttributes->GetAttr(nsGkAtoms::color); + } + nscolor color; + if (value && value->GetColorValue(color) && + aData->mColorData->mColor.GetUnit() == eCSSUnit_Null) { + aData->mColorData->mColor.SetColorValue(color); + } + } +} + +NS_IMPL_ELEMENT_CLONE(nsMathMLElement) + +PRInt32 +nsMathMLElement::IntrinsicState() const +{ + return nsMathMLElementBase::IntrinsicState() | + (mIncrementScriptLevel ? NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL : 0); +} + +PRBool +nsMathMLElement::IsNodeOfType(PRUint32 aFlags) const +{ + return !(aFlags & ~(eCONTENT | eELEMENT | eMATHML)); +} + +void +nsMathMLElement::SetIncrementScriptLevel(PRBool aIncrementScriptLevel, + PRBool aNotify) +{ + if (aIncrementScriptLevel == mIncrementScriptLevel) + return; + mIncrementScriptLevel = aIncrementScriptLevel; + + NS_ASSERTION(aNotify, "We always notify!"); + + nsIDocument* doc = GetCurrentDoc(); + if (!doc) + return; + + mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE); + doc->ContentStatesChanged(this, nsnull, + NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL); +} diff --git a/content/mathml/content/src/nsMathMLElement.h b/content/mathml/content/src/nsMathMLElement.h new file mode 100644 index 00000000000..15e594be0d4 --- /dev/null +++ b/content/mathml/content/src/nsMathMLElement.h @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is MathML DOM code. + * + * The Initial Developer of the Original Code is + * mozilla.org. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vlad Sukhoy (original developer) + * Daniel Kraft (nsMathMLElement patch, attachment 262925) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsMathMLElement_h +#define nsMathMLElement_h + +#include "nsMappedAttributeElement.h" +#include "nsIDOMElement.h" + +class nsCSSValue; + +typedef nsMappedAttributeElement nsMathMLElementBase; + +/* + * The base class for MathML elements. + */ +class nsMathMLElement : public nsMathMLElementBase + , public nsIDOMElement +{ +public: + nsMathMLElement(nsINodeInfo* aNodeInfo) + : nsMathMLElementBase(aNodeInfo), mIncrementScriptLevel(PR_FALSE) + {} + + // Implementation of nsISupports is inherited from nsMathMLElementBase + NS_DECL_ISUPPORTS_INHERITED + + // Forward implementations of parent interfaces of nsMathMLElement to + // our base class + NS_FORWARD_NSIDOMNODE(nsMathMLElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsMathMLElementBase::) + + nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + PRBool aCompileEventHandlers); + + virtual PRBool ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult); + + NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; + virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; + + static PRBool ParseNumericValue(const nsString& aString, + nsCSSValue& aCSSValue, + PRBool aRequireLengthUnit); + + static void MapMathMLAttributesInto(const nsMappedAttributes* aAttributes, + nsRuleData* aRuleData); + + nsresult Clone(nsINodeInfo*, nsINode**) const; + virtual PRInt32 IntrinsicState() const; + virtual PRBool IsNodeOfType(PRUint32 aFlags) const; + + // Set during reflow as necessary. Does a style change notification, + // aNotify must be true. + void SetIncrementScriptLevel(PRBool aIncrementScriptLevel, PRBool aNotify); + PRBool GetIncrementScriptLevel() const { + return mIncrementScriptLevel; + } + +private: + PRPackedBool mIncrementScriptLevel; +}; + +#endif // nsMathMLElement_h diff --git a/content/mathml/content/src/nsMathMLElementFactory.cpp b/content/mathml/content/src/nsMathMLElementFactory.cpp new file mode 100644 index 00000000000..006546f5af8 --- /dev/null +++ b/content/mathml/content/src/nsMathMLElementFactory.cpp @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is MathML DOM code. + * + * The Initial Developer of the Original Code is + * mozilla.org. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vlad Sukhoy (original developer) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsContentCreatorFunctions.h" +#include "nsGkAtoms.h" +#include "nsIDocument.h" +#include "nsMathMLElement.h" + +// MathML Element Factory (declared in nsContentCreatorFunctions.h) +nsresult +NS_NewMathMLElement(nsIContent** aResult, nsINodeInfo* aNodeInfo) +{ + aNodeInfo->SetIDAttributeAtom(nsGkAtoms::id); + + nsMathMLElement* it = new (aNodeInfo) nsMathMLElement(aNodeInfo); + NS_ENSURE_TRUE(it, NS_ERROR_OUT_OF_MEMORY); + + NS_ADDREF(*aResult = it); + return NS_OK; +} diff --git a/content/xml/document/src/nsXMLContentSink.cpp b/content/xml/document/src/nsXMLContentSink.cpp index 817a2774895..eeaa83ded6a 100644 --- a/content/xml/document/src/nsXMLContentSink.cpp +++ b/content/xml/document/src/nsXMLContentSink.cpp @@ -909,28 +909,6 @@ nsXMLContentSink::MaybeStartLayout(PRBool aIgnorePendingSheets) StartLayout(aIgnorePendingSheets); } -#ifdef MOZ_MATHML -//////////////////////////////////////////////////////////////////////// -// MathML Element Factory - temporary location for bug 132844 -// Will be factored out post 1.0 - -nsresult -NS_NewMathMLElement(nsIContent** aResult, nsINodeInfo* aNodeInfo) -{ - static const char kMathMLStyleSheetURI[] = "resource://gre/res/mathml.css"; - - aNodeInfo->SetIDAttributeAtom(nsGkAtoms::id); - - // this bit of code is to load mathml.css on demand - nsIDocument *doc = aNodeInfo->GetDocument(); - if (doc) - doc->EnsureCatalogStyleSheet(kMathMLStyleSheetURI); - - return NS_NewXMLElement(aResult, aNodeInfo); -} -#endif // MOZ_MATHML - - //////////////////////////////////////////////////////////////////////// PRBool diff --git a/dom/src/base/nsHistory.cpp b/dom/src/base/nsHistory.cpp index 5f98bca7267..2efa1c491f3 100644 --- a/dom/src/base/nsHistory.cpp +++ b/dom/src/base/nsHistory.cpp @@ -295,7 +295,7 @@ nsHistory::Go() nsPresContext *pcx; if (doc && (shell = doc->GetPrimaryShell()) && (pcx = shell->GetPresContext())) { - pcx->ClearStyleDataAndReflow(); + pcx->RebuildAllStyleData(); } return NS_OK; diff --git a/dom/src/base/nsLocation.cpp b/dom/src/base/nsLocation.cpp index 386c7807ac8..8945b0278f9 100644 --- a/dom/src/base/nsLocation.cpp +++ b/dom/src/base/nsLocation.cpp @@ -892,7 +892,7 @@ nsLocation::Reload() nsPresContext *pcx; if (doc && (shell = doc->GetPrimaryShell()) && (pcx = shell->GetPresContext())) { - pcx->ClearStyleDataAndReflow(); + pcx->RebuildAllStyleData(); } return NS_OK; diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index cb10b00000f..15dd1bf2e0f 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1835,6 +1835,7 @@ nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument *aDocument, , mCountersDirty(PR_FALSE) , mInitialContainingBlockIsAbsPosContainer(PR_FALSE) , mIsDestroyingFrameTree(PR_FALSE) + , mRebuildAllStyleData(PR_FALSE) { if (!gGotXBLFormPrefs) { gGotXBLFormPrefs = PR_TRUE; @@ -13263,6 +13264,39 @@ nsCSSFrameConstructor::ProcessOneRestyle(nsIContent* aContent, #define RESTYLE_ARRAY_STACKSIZE 128 +void +nsCSSFrameConstructor::RebuildAllStyleData() +{ + mRebuildAllStyleData = PR_FALSE; + + if (!mPresShell || !mPresShell->GetRootFrame()) + return; + + // Tell the style set to get the old rule tree out of the way + // so we can recalculate while maintaining rule tree immutability + nsresult rv = mPresShell->StyleSet()->BeginReconstruct(); + if (NS_FAILED(rv)) + return; + + // Recalculate all of the style contexts for the document + // Note that we can ignore the return value of ComputeStyleChangeFor + // because we never need to reframe the root frame + // XXX This could be made faster by not rerunning rule matching + // (but note that nsPresShell::SetPreferenceStyleRules currently depends + // on us re-running rule matching here + nsStyleChangeList changeList; + mPresShell->FrameManager()->ComputeStyleChangeFor(mPresShell->GetRootFrame(), + &changeList, nsChangeHint(0)); + // Process the required changes + ProcessRestyledFrames(changeList); + // Tell the style set it's safe to destroy the old rule tree. We + // must do this after the ProcessRestyledFrames call in case the + // change list has frame reconstructs in it (since frames to be + // reconstructed will still have their old style context pointers + // until they are destroyed). + mPresShell->StyleSet()->EndReconstruct(); +} + void nsCSSFrameConstructor::ProcessPendingRestyles() { @@ -13309,6 +13343,12 @@ nsCSSFrameConstructor::ProcessPendingRestyles() #ifdef DEBUG mPresShell->VerifyStyleTree(); #endif + + if (mRebuildAllStyleData) { + // We probably wasted a lot of work up above, but this seems safest + // and it should be rarely used. + RebuildAllStyleData(); + } } void @@ -13346,6 +13386,14 @@ nsCSSFrameConstructor::PostRestyleEvent(nsIContent* aContent, } } +void +nsCSSFrameConstructor::PostRebuildAllStyleDataEvent() +{ + mRebuildAllStyleData = PR_TRUE; + // Get a restyle event posted if necessary + mPresShell->ReconstructStyleDataInternal(); +} + NS_IMETHODIMP nsCSSFrameConstructor::RestyleEvent::Run() { if (!mConstructor) diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index fe2a28cf7a7..738e7b4d2a3 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -177,10 +177,24 @@ public: // If the caller wants that to happen synchronously, it needs to handle that // itself. void ProcessPendingRestyles(); + + void RebuildAllStyleData(); void PostRestyleEvent(nsIContent* aContent, nsReStyleHint aRestyleHint, nsChangeHint aMinChangeHint); + /** + * Asynchronously clear style data from the root frame downwards and ensure + * it will all be rebuilt. This is safe to call anytime; it will schedule + * a restyle and take effect next time style changes are flushed. + * This method is used to recompute the style data when some change happens + * outside of any style rules, like a color preference change or a change + * in a system font size, or to fix things up when an optimization in the + * style data has become invalid. We assume that the root frame will not + * need to be reframed. + */ + void PostRebuildAllStyleDataEvent(); + // Request to create a continuing frame nsresult CreateContinuingFrame(nsPresContext* aPresContext, nsIFrame* aFrame, @@ -1134,6 +1148,7 @@ private: PRPackedBool mCountersDirty : 1; PRPackedBool mInitialContainingBlockIsAbsPosContainer : 1; PRPackedBool mIsDestroyingFrameTree : 1; + PRPackedBool mRebuildAllStyleData : 1; nsRevocableEventPtr mRestyleEvent; diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 58807b4de68..b314960b01b 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -701,38 +701,6 @@ nsPresContext::GetUserPreferences() SetBidi(bidiOptions, PR_FALSE); } -void -nsPresContext::ClearStyleDataAndReflow() -{ - // This method is used to recompute the style data when some change happens - // outside of any style rules, like a color preference change or a change - // in a system font size - if (mShell && mShell->GetRootFrame()) { - // Tell the style set to get the old rule tree out of the way - // so we can recalculate while maintaining rule tree immutability - nsresult rv = mShell->StyleSet()->BeginReconstruct(); - if (NS_FAILED(rv)) - return; - // Recalculate all of the style contexts for the document - // Note that we can ignore the return value of ComputeStyleChangeFor - // because we never need to reframe the root frame - // XXX This could be made faster by not rerunning rule matching - // (but note that nsPresShell::SetPreferenceStyleRules currently depends - // on us re-running rule matching here - nsStyleChangeList changeList; - mShell->FrameManager()->ComputeStyleChangeFor(mShell->GetRootFrame(), - &changeList, nsChangeHint(0)); - // Tell the frame constructor to process the required changes - mShell->FrameConstructor()->ProcessRestyledFrames(changeList); - // Tell the style set it's safe to destroy the old rule tree. We - // must do this after the ProcessRestyledFrames call in case the - // change list has frame reconstructs in it (since frames to be - // reconstructed will still have their old style context pointers - // until they are destroyed). - mShell->StyleSet()->EndReconstruct(); - } -} - static const char sMinFontSizePref[] = "browser.display.auto_quality_min_font_size"; void @@ -755,13 +723,13 @@ nsPresContext::PreferenceChanged(const char* aPrefName) nscoord height = NSToCoordRound(oldHeightDevPixels*AppUnitsPerDevPixel()); vm->SetWindowDimensions(width, height); - ClearStyleDataAndReflow(); + RebuildAllStyleData(); } return; } if (!nsCRT::strcmp(aPrefName, sMinFontSizePref)) { mAutoQualityMinFontSizePixelsPref = nsContentUtils::GetIntPref(sMinFontSizePref); - ClearStyleDataAndReflow(); + RebuildAllStyleData(); return; } // we use a zero-delay timer to coalesce multiple pref updates @@ -796,7 +764,7 @@ nsPresContext::UpdateAfterPreferencesChanged() } mDeviceContext->FlushFontCache(); - ClearStyleDataAndReflow(); + RebuildAllStyleData(); } nsresult @@ -982,8 +950,7 @@ nsPresContext::Observe(nsISupports* aSubject, if (!nsCRT::strcmp(aTopic, "charset")) { UpdateCharSet(NS_LossyConvertUTF16toASCII(aData)); mDeviceContext->FlushFontCache(); - ClearStyleDataAndReflow(); - + RebuildAllStyleData(); return NS_OK; } @@ -1174,7 +1141,7 @@ nsPresContext::SetFullZoom(float aZoom) mFullZoom = aZoom; GetViewManager()->SetWindowDimensions(NSToCoordRound(oldWidthDevPixels*AppUnitsPerDevPixel()), NSToCoordRound(oldHeightDevPixels*AppUnitsPerDevPixel())); - ClearStyleDataAndReflow(); + RebuildAllStyleData(); mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel(); } @@ -1284,14 +1251,14 @@ nsPresContext::GetBidiUtils() } void -nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceReflow) +nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceRestyle) { // Don't do all this stuff unless the options have changed. if (aSource == GetBidi()) { return; } - NS_ASSERTION(!(aForceReflow && (GetBidi() == 0)), + NS_ASSERTION(!(aForceRestyle && (GetBidi() == 0)), "ForceReflow on new prescontext"); Document()->SetBidiOptions(aSource); @@ -1311,8 +1278,8 @@ nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceReflow) SetVisualMode(IsVisualCharset(doc->GetDocumentCharacterSet())); } } - if (aForceReflow) { - ClearStyleDataAndReflow(); + if (aForceRestyle) { + RebuildAllStyleData(); } } @@ -1373,7 +1340,7 @@ nsPresContext::ThemeChangedInternal() // immutability has been violated since any style rule that uses // system colors or fonts (and probably -moz-appearance as well) has // changed. - nsPresContext::ClearStyleDataAndReflow(); + RebuildAllStyleData(); } void @@ -1409,7 +1376,21 @@ nsPresContext::SysColorChangedInternal() // data without reflowing/updating views will lead to incorrect change hints // later, because when generating change hints, any style structs which have // been cleared and not reread are assumed to not be used at all. - ClearStyleDataAndReflow(); + // XXXroc not sure what to make of the above comment, because we don't reflow + // synchronously here + RebuildAllStyleData(); +} + +void +nsPresContext::RebuildAllStyleData() +{ + mShell->FrameConstructor()->RebuildAllStyleData(); +} + +void +nsPresContext::PostRebuildAllStyleDataEvent() +{ + mShell->FrameConstructor()->PostRebuildAllStyleDataEvent(); } void diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index a5e5ffad0bb..cffdb6b5151 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -201,6 +201,9 @@ public: { return GetPresShell()->FrameManager(); } #endif + void RebuildAllStyleData(); + void PostRebuildAllStyleDataEvent(); + /** * Access compatibility mode for this context. This is the same as * our document's compatibility mode. @@ -238,11 +241,6 @@ public: */ nsIAtom* Medium() { return mMedium; } - /** - * Clear style data from the root frame downwards, and reflow. - */ - NS_HIDDEN_(void) ClearStyleDataAndReflow(); - void* AllocateFromShell(size_t aSize) { if (mShell) @@ -468,7 +466,7 @@ public: float TextZoom() { return mTextZoom; } void SetTextZoom(float aZoom) { mTextZoom = aZoom; - ClearStyleDataAndReflow(); + RebuildAllStyleData(); } float GetFullZoom() { return mFullZoom; } @@ -637,7 +635,7 @@ public: * Set the Bidi options for the presentation context */ NS_HIDDEN_(void) SetBidi(PRUint32 aBidiOptions, - PRBool aForceReflow = PR_FALSE); + PRBool aForceRestyle = PR_FALSE); /** * Get the Bidi options for the presentation context diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index 99847cd771e..f7d0f6ae6a0 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -428,6 +428,10 @@ #define NS_STYLE_FONT_LIST 15 #define NS_STYLE_FONT_FIELD 16 +// defaults per MathML spec +#define NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER 0.71f +#define NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT 8 + // See nsStylePosition::mWidth, mMinWidth, mMaxWidth #define NS_STYLE_WIDTH_MAX_CONTENT 0 #define NS_STYLE_WIDTH_MIN_CONTENT 1 diff --git a/layout/build/Makefile.in b/layout/build/Makefile.in index 32184a3be0d..fecad7d6d72 100644 --- a/layout/build/Makefile.in +++ b/layout/build/Makefile.in @@ -178,9 +178,10 @@ endif ifdef MOZ_MATHML SHARED_LIBRARY_LIBS += \ - ../mathml/content/src/$(LIB_PREFIX)gkmathmlcon_s.$(LIB_SUFFIX) \ - ../mathml/base/src/$(LIB_PREFIX)gkmathmlbase_s.$(LIB_SUFFIX) \ - $(NULL) + ../mathml/content/src/$(LIB_PREFIX)gkmathmlcon_s.$(LIB_SUFFIX) \ + ../mathml/base/src/$(LIB_PREFIX)gkmathmlbase_s.$(LIB_SUFFIX) \ + $(DEPTH)/content/mathml/content/src/$(LIB_PREFIX)gkcontentmathml_s.$(LIB_SUFFIX) \ + $(NULL) endif ifdef MOZ_XTF @@ -191,10 +192,10 @@ endif ifdef MOZ_SVG SHARED_LIBRARY_LIBS += \ - ../svg/base/src/$(LIB_PREFIX)gksvgbase_s.$(LIB_SUFFIX) \ + ../svg/base/src/$(LIB_PREFIX)gksvgbase_s.$(LIB_SUFFIX) \ $(DEPTH)/content/svg/document/src/$(LIB_PREFIX)gkconsvgdoc_s.$(LIB_SUFFIX) \ $(DEPTH)/content/svg/content/src/$(LIB_PREFIX)gkcontentsvg_s.$(LIB_SUFFIX) \ - $(NULL) + $(NULL) endif ifdef MOZ_PLAINTEXT_EDITOR_ONLY diff --git a/layout/mathml/base/src/Makefile.in b/layout/mathml/base/src/Makefile.in index b3fb2d09971..a09504b9a4b 100644 --- a/layout/mathml/base/src/Makefile.in +++ b/layout/mathml/base/src/Makefile.in @@ -76,6 +76,8 @@ LOCAL_INCLUDES = \ -I$(srcdir)/../../../generic \ -I$(srcdir)/../../../tables \ -I$(srcdir)/../../content/src \ + -I$(topsrcdir)/content/base/src \ + -I$(topsrcdir)/content/mathml/content/src \ -I$(srcdir)/../../../xul/base/src \ $(NULL) diff --git a/layout/mathml/base/src/nsIMathMLFrame.h b/layout/mathml/base/src/nsIMathMLFrame.h index 7ebdfb25163..e758c8bbd90 100644 --- a/layout/mathml/base/src/nsIMathMLFrame.h +++ b/layout/mathml/base/src/nsIMathMLFrame.h @@ -226,19 +226,15 @@ public: TransmitAutomaticData() = 0; /* UpdatePresentationData : - * Increments the scriptlevel of the frame, and updates its displaystyle and - * compression flags. The displaystyle flag of an environment gets updated - * according to the MathML specification. A frame becomes "compressed" (or - * "cramped") according to TeX rendering rules (TeXBook, Ch.17, p.140-141). + * Updates the frame's displaystyle and compression flags. The displaystyle + * flag of an environment gets updated according to the MathML specification. + * A frame becomes "compressed" (or "cramped") according to TeX rendering + * rules (TeXBook, Ch.17, p.140-141). * * Note that is the only tag which allows to set - * - * to reset or increment the scriptlevel in a manual way. + * * Therefore has its own peculiar version of this method. * - * @param aScriptLevelIncrement [in] - * The value with which to increment mScriptLevel in the frame. - * * @param aFlagsValues [in] * The new values (e.g., display, compress) that are going to be * updated. @@ -255,20 +251,17 @@ public: * update some flags in the frame, leaving the other flags unchanged. */ NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, + UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aWhichFlags) = 0; /* UpdatePresentationDataFromChildAt : - * Increments the scriplevel and sets the displaystyle and compression flags - * on the whole tree. For child frames at aFirstIndex up to aLastIndex, this - * method sets their displaystyle and compression flags, and increment their - * mScriptLevel with aScriptLevelIncrement. The update is propagated down - * the subtrees of each of these child frames. + * Sets displaystyle and compression flags on the whole tree. For child frames + * at aFirstIndex up to aLastIndex, this method sets their displaystyle and + * compression flags. The update is propagated down the subtrees of each of + * these child frames. * * Note that is the only tag which allows - * - * to reset or increment the scriptlevel in a manual way. + * * Therefore has its own peculiar version of this method. * * @param aFirstIndex [in] @@ -278,9 +271,6 @@ public: * Index of the last child where to stop the update. * A value of -1 means up to last existing child. * - * @param aScriptLevelIncrement [in] - * The value with which to increment mScriptLevel in the whole sub-trees. - * * @param aFlagsValues [in] * The new values (e.g., display, compress) that are going to be * assigned in the whole sub-trees. @@ -292,40 +282,8 @@ public: NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aWhichFlags) = 0; - - /* ReResolveScriptStyle : - * During frame construction, the Style System gives us style contexts in - * which the sizes of the fonts are not suitable for scripting elements. - * Our expected behavior is that, when given the markup base arguments, - * we want to render the 'base' in a normal size, and the 'arguments' in a smaller - * size. This is a common functionality to tags like msub, msup, msubsup, mover, - * munder, munderover, mmultiscripts. Moreover, we want the reduction of the font - * size to happen in a top-down manner within the hierarchies of sub-expressions; - * and more importantly, we don't want the sizes to keep decreasing up to a point - * where the scripts become unreadably small. - * - * In general, this scaling effet arises when the scriptlevel changes between a - * parent and a child. Whenever the scriptlevel changes, either automatically or - * by being explicitly incremented, decremented, or set, the current font size has - * to be multiplied by the predefined value of 'scriptsizemultiplier' to the power - * of the change in the scriptlevel, and this scaling effect (downwards or upwards) - * has to be propagated down the subtrees, with the caveat that the font size is - * never allowed to go below the predefined value of 'scriptminsize' within a - * sub-expression. - * - * ReResolveScriptStyle() will walk a subtree to cause this mathml-specific behavior - * to happen. The method is recursive and only a top-level parent wishing to reflect - * the changes in its children needs to call to the method. - * - * This function is *very* expensive. Unfortunately, there isn't much - * to do about it at the moment. For background on the problem @see - * http://groups.google.com/groups?selm=3A9192B5.D22B6C38%40maths.uq.edu.au - */ - NS_IMETHOD - ReResolveScriptStyle(PRInt32 aParentScriptLevel) = 0; }; // struct used by a container frame to keep track of its embellishments. @@ -379,15 +337,10 @@ struct nsPresentationData { // up-pointer on the mstyle frame, if any, that defines the scope nsIFrame* mstyle; - // level of nested frames within: msub, msup, msubsup, munder, - // mover, munderover, mmultiscripts, mfrac, mroot, mtable. - PRInt32 scriptLevel; - nsPresentationData() { flags = 0; baseFrame = nsnull; mstyle = nsnull; - scriptLevel = 0; } }; @@ -422,12 +375,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMathMLFrame, NS_IMATHMLFRAME_IID) // horizontal stretch command on all their non-empty children #define NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY 0x00000008 -// This bit is set if the frame has the explicit attribute -// scriptlevel="value". It is only relevant to because that's -// the only tag where the attribute is allowed by the spec. -// Note: the flag is not set if the instead has an incremental +/-value. -#define NS_MATHML_EXPLICIT_SCRIPTLEVEL 0x00000010 - // This bit is set if the frame has the explicit attribute // displaystyle="true" or "false". It is only relevant to and // because they are the only tags where the attribute is allowed by the spec. @@ -464,9 +411,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMathMLFrame, NS_IMATHMLFRAME_IID) #define NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(_flags) \ (NS_MATHML_EXPLICIT_DISPLAYSTYLE == ((_flags) & NS_MATHML_EXPLICIT_DISPLAYSTYLE)) -#define NS_MATHML_HAS_EXPLICIT_SCRIPTLEVEL(_flags) \ - (NS_MATHML_EXPLICIT_SCRIPTLEVEL == ((_flags) & NS_MATHML_EXPLICIT_SCRIPTLEVEL)) - #define NS_MATHML_HAS_ERROR(_flags) \ (NS_MATHML_ERROR == ((_flags) & NS_MATHML_ERROR)) diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.cpp b/layout/mathml/base/src/nsMathMLContainerFrame.cpp index 358e001b5da..de0fbfbfd7b 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.cpp +++ b/layout/mathml/base/src/nsMathMLContainerFrame.cpp @@ -64,6 +64,7 @@ #include "nsStyleSet.h" #include "nsDisplayList.h" #include "nsCSSFrameConstructor.h" +#include "nsIReflowCallback.h" NS_DEFINE_CID(kInlineFrameCID, NS_INLINE_FRAME_CID); @@ -569,29 +570,28 @@ nsMathMLContainerFrame::FinalizeReflow(nsIRenderingContext& aRenderingContext, // a subtree that may contain non-mathml container frames /* static */ void nsMathMLContainerFrame::PropagatePresentationDataFor(nsIFrame* aFrame, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { - if (!aFrame || (!aFlagsToUpdate && !aScriptLevelIncrement)) + if (!aFrame || !aFlagsToUpdate) return; nsIMathMLFrame* mathMLFrame; aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); if (mathMLFrame) { // update - mathMLFrame->UpdatePresentationData(aScriptLevelIncrement, aFlagsValues, + mathMLFrame->UpdatePresentationData(aFlagsValues, aFlagsToUpdate); // propagate using the base method to make sure that the control // is passed on to MathML frames that may be overloading the method mathMLFrame->UpdatePresentationDataFromChildAt(0, -1, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + aFlagsValues, aFlagsToUpdate); } else { // propagate down the subtrees nsIFrame* childFrame = aFrame->GetFirstChild(nsnull); while (childFrame) { PropagatePresentationDataFor(childFrame, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + aFlagsValues, aFlagsToUpdate); childFrame = childFrame->GetNextSibling(); } } @@ -601,11 +601,10 @@ nsMathMLContainerFrame::PropagatePresentationDataFor(nsIFrame* aFrame, nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(nsIFrame* aParentFrame, PRInt32 aFirstChildIndex, PRInt32 aLastChildIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { - if (!aParentFrame || (!aFlagsToUpdate && !aScriptLevelIncrement)) + if (!aParentFrame || !aFlagsToUpdate) return; PRInt32 index = 0; nsIFrame* childFrame = aParentFrame->GetFirstChild(nsnull); @@ -614,131 +613,13 @@ nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(nsIFrame* aPa ((aLastChildIndex <= 0) || ((aLastChildIndex > 0) && (index <= aLastChildIndex)))) { PropagatePresentationDataFor(childFrame, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + aFlagsValues, aFlagsToUpdate); } index++; childFrame = childFrame->GetNextSibling(); } } -// helper to let the scriptstyle re-resolution pass through -// a subtree that may contain non-mathml container frames. -// This function is *very* expensive. Unfortunately, there isn't much -// to do about it at the moment. For background on the problem @see -// http://groups.google.com/groups?selm=3A9192B5.D22B6C38%40maths.uq.edu.au -/* static */ void -nsMathMLContainerFrame::PropagateScriptStyleFor(nsIFrame* aFrame, - PRInt32 aParentScriptLevel) -{ - if (!aFrame) - return; - nsIMathMLFrame* mathMLFrame; - aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - // we will re-resolve our style data based on our current scriptlevel - nsPresentationData presentationData; - mathMLFrame->GetPresentationData(presentationData); - PRInt32 gap = presentationData.scriptLevel - aParentScriptLevel; - - // since we are a MathML frame, our current scriptlevel becomes - // the one to use when we will propagate the recursion - aParentScriptLevel = presentationData.scriptLevel; - - nsStyleContext* oldStyleContext = aFrame->GetStyleContext(); - nsStyleContext* parentContext = oldStyleContext->GetParent(); - - nsIContent* content = aFrame->GetContent(); - if (!gap) { - // unset any -moz-math-font-size attribute without notifying that we want a reflow - // (but leave it to the primary frame to do that, a child pseudo can't overrule) - if (!aFrame->GetParent() || aFrame->GetParent()->GetContent() != content) - content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::MOZfontsize, PR_FALSE); - } - else { - // By default scriptminsize=8pt and scriptsizemultiplier=0.71 - nscoord scriptminsize = aFrame->PresContext()->PointsToAppUnits(NS_MATHML_SCRIPTMINSIZE); - float scriptsizemultiplier = NS_MATHML_SCRIPTSIZEMULTIPLIER; -#if 0 - // XXX Bug 44201 - // user-supplied scriptminsize and scriptsizemultiplier that are - // restricted to particular elements are not supported because our - // css rules are fixed in mathml.css and are applicable to all elements. - - // see if there is a scriptminsize attribute on a that wraps us - GetAttribute(nsnull, presentationData.mstyle, - nsGkAtoms::scriptminsize_, fontsize); - if (!fontsize.IsEmpty()) { - nsCSSValue cssValue; - if (ParseNumericValue(fontsize, cssValue)) { - nsCSSUnit unit = cssValue.GetUnit(); - if (eCSSUnit_Number == unit) - scriptminsize = nscoord(float(scriptminsize) * cssValue.GetFloatValue()); - else if (eCSSUnit_Percent == unit) - scriptminsize = nscoord(float(scriptminsize) * cssValue.GetPercentValue()); - else if (eCSSUnit_Null != unit) - scriptminsize = CalcLength(mStyleContext, cssValue); - } - } -#endif - - // figure out the incremental factor - nsAutoString fontsize; - if (0 > gap) { // the size is going to be increased - if (gap < NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT) - gap = NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT; - gap = -gap; - scriptsizemultiplier = 1.0f / scriptsizemultiplier; - fontsize.AssignLiteral("-"); - } - else { // the size is going to be decreased - if (gap > NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT) - gap = NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT; - fontsize.AssignLiteral("+"); - } - fontsize.AppendInt(gap, 10); - // we want to make sure that the size will stay readable - const nsStyleFont* font = parentContext->GetStyleFont(); - nscoord newFontSize = font->mFont.size; - while (0 < gap--) { - newFontSize = (nscoord)((float)(newFontSize) * scriptsizemultiplier); - } - if (newFontSize <= scriptminsize) { - fontsize.AssignLiteral("scriptminsize"); - } - - // set the -moz-math-font-size attribute without notifying that we want a reflow - content->SetAttr(kNameSpaceID_None, nsGkAtoms::MOZfontsize, - fontsize, PR_FALSE); - } - - // now, re-resolve the style contexts in our subtree - nsFrameManager *fm = aFrame->PresContext()->FrameManager(); - nsStyleChangeList changeList; - fm->ComputeStyleChangeFor(aFrame, &changeList, NS_STYLE_HINT_NONE); -#ifdef DEBUG - // Use the parent frame to make sure we catch in-flows and such - nsIFrame* parentFrame = aFrame->GetParent(); - fm->DebugVerifyStyleTree(parentFrame ? parentFrame : aFrame); -#endif - } - - // recurse down the subtrees for changes that may arise deep down - nsIFrame* childFrame = aFrame->GetFirstChild(nsnull); - while (childFrame) { - childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - // propagate using the base method to make sure that the control - // is passed on to MathML frames that may be overloading the method - mathMLFrame->ReResolveScriptStyle(aParentScriptLevel); - } - else { - PropagateScriptStyleFor(childFrame, aParentScriptLevel); - } - childFrame = childFrame->GetNextSibling(); - } -} - - /* ////////////////// * Frame construction * ============================================================================= @@ -776,22 +657,6 @@ nsMathMLContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, return rv; } -// This method is called in a top-down manner, as we descend the frame tree -// during its construction -NS_IMETHODIMP -nsMathMLContainerFrame::Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow) -{ - MapCommonAttributesIntoCSS(PresContext(), aContent); - - // let the base class do its Init() - return nsHTMLContainerFrame::Init(aContent, aParent, aPrevInFlow); - - // ...We will build our automatic MathML data once the entire ... - // tree is constructed. -} - // Note that this method re-builds the automatic data in the children -- not // in aParentFrame itself (except for those particular operations that the // parent frame may do in its TransmitAutomaticData()). @@ -827,7 +692,6 @@ nsMathMLContainerFrame::ReLayoutChildren(nsIFrame* aParentFrame, return NS_OK; // walk-up to the first frame that is a MathML frame, stop if we reach - PRInt32 parentScriptLevel = 0; nsIFrame* frame = aParentFrame; while (1) { nsIFrame* parent = frame->GetParent(); @@ -837,12 +701,8 @@ nsMathMLContainerFrame::ReLayoutChildren(nsIFrame* aParentFrame, // stop if it is a MathML frame nsIMathMLFrame* mathMLFrame; frame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - nsPresentationData parentData; - mathMLFrame->GetPresentationData(parentData); - parentScriptLevel = parentData.scriptLevel; + if (mathMLFrame) break; - } // stop if we reach the root tag nsIContent* content = frame->GetContent(); @@ -863,22 +723,6 @@ nsMathMLContainerFrame::ReLayoutChildren(nsIFrame* aParentFrame, // re-sync the presentation data and embellishment data of our children RebuildAutomaticDataForChildren(frame); - // re-resolve the style data to sync any change of script sizes - nsIFrame* childFrame = aParentFrame->GetFirstChild(nsnull); - while (childFrame) { - nsIMathMLFrame* mathMLFrame; - childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - // propagate using the base method to make sure that the control - // is passed on to MathML frames that may be overloading the method - mathMLFrame->ReResolveScriptStyle(parentScriptLevel); - } - else { - PropagateScriptStyleFor(childFrame, parentScriptLevel); - } - childFrame = childFrame->GetNextSibling(); - } - // Ask our parent frame to reflow us nsIFrame* parent = frame->GetParent(); NS_ASSERTION(parent, "No parent to pass the reflow request up to"); @@ -963,10 +807,6 @@ nsMathMLContainerFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aModType) { - // Attributes common to MathML tags - if (CommonAttributeChangedFor(PresContext(), mContent, aAttribute)) - return NS_OK; - // XXX Since they are numerous MathML attributes that affect layout, and // we can't check all of them here, play safe by requesting a reflow. // XXXldb This should only do work for attributes that cause changes! @@ -1303,11 +1143,12 @@ public: InitMetricsForChild(); // add inter frame spacing + const nsStyleFont* font = mParentFrame->GetStyleFont(); nscoord space = - GetInterFrameSpacing(mParentFrame->mPresentationData.scriptLevel, + GetInterFrameSpacing(font->mScriptLevel, prevFrameType, mChildFrameType, &mFromFrameType, &mCarrySpace); - mX += space * GetThinSpace(mParentFrame->GetStyleFont()); + mX += space * GetThinSpace(font); return *this; } @@ -1402,6 +1243,38 @@ nsMathMLContainerFrame::PositionRowChildFrames(nscoord aOffsetX, } } +class ForceReflow : public nsIReflowCallback { +public: + virtual PRBool ReflowFinished() { + return PR_TRUE; + } + virtual void ReflowCallbackCanceled() {} +}; + +// We only need one of these so we just make it a static global, no need +// to dynamically allocate/destroy it. +static ForceReflow gForceReflow; + +void +nsMathMLContainerFrame::SetIncrementScriptLevel(PRInt32 aChildIndex, PRBool aIncrement) +{ + nsIFrame* child = nsFrameList(GetFirstChild(nsnull)).FrameAt(aChildIndex); + if (!child) + return; + nsIContent* content = child->GetContent(); + if (!content->IsNodeOfType(nsINode::eMATHML)) + return; + nsMathMLElement* element = static_cast(content); + + if (element->GetIncrementScriptLevel() == aIncrement) + return; + + // XXXroc this does a ContentStatesChanged, is it safe to call here? If + // not we should do it in a post-reflow callback. + element->SetIncrementScriptLevel(aIncrement, PR_TRUE); + PresContext()->PresShell()->PostReflowCallback(&gForceReflow); +} + // helpers to fix the inter-spacing when is the only parent // e.g., it fixes f q f I @@ -1450,7 +1323,7 @@ nsMathMLContainerFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize) nsIAtom *parentTag = parentContent->Tag(); if (parentTag == nsGkAtoms::math || parentTag == nsGkAtoms::mtd_) { - gap = GetInterFrameSpacingFor(mPresentationData.scriptLevel, mParent, this); + gap = GetInterFrameSpacingFor(GetStyleFont()->mScriptLevel, mParent, this); // add our own italic correction nscoord leftCorrection = 0, italicCorrection = 0; GetItalicCorrection(mBoundingMetrics, leftCorrection, italicCorrection); diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.h b/layout/mathml/base/src/nsMathMLContainerFrame.h index 49dcc6ebe2d..ce256264bd5 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.h +++ b/layout/mathml/base/src/nsMathMLContainerFrame.h @@ -61,16 +61,6 @@ * to position children in various customized ways. */ -// Parameters to handle the change of font-size induced by changing the -// scriptlevel. These are hard-coded values that match with the rules in -// mathml.css. Note that mScriptLevel can exceed these bounds, but the -// scaling effect on the font-size will be bounded. The following bounds can -// be expanded provided the new corresponding rules are added in mathml.css. -#define NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT +5 -#define NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT -5 -#define NS_MATHML_SCRIPTSIZEMULTIPLIER 0.71f -#define NS_MATHML_SCRIPTMINSIZE 8 - // Options for the preferred size at which to stretch our stretchy children #define STRETCH_CONSIDER_ACTUAL_SIZE 0x00000001 // just use our current size #define STRETCH_CONSIDER_EMBELLISHMENTS 0x00000002 // size calculations include embellishments @@ -100,21 +90,25 @@ public: NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { PropagatePresentationDataFromChildAt(this, aFirstIndex, aLastIndex, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); - return NS_OK; - } - - NS_IMETHOD - ReResolveScriptStyle(PRInt32 aParentScriptLevel) - { - PropagateScriptStyleFor(this, aParentScriptLevel); + aFlagsValues, aFlagsToUpdate); return NS_OK; } + + // helper to set the "increment script level" flag on the element belonging + // to a child frame given by aChildIndex. + // When this flag is set, the style system will increment the scriptlevel + // for the child element. This is needed for situations where the style system + // cannot itself determine the scriptlevel (mfrac, munder, mover, munderover). + // This should be called during reflow. We set the flag and if it changed, + // we request appropriate restyling and also queue a post-reflow callback + // to ensure that restyle and reflow happens immediately after the current + // reflow. + void + SetIncrementScriptLevel(PRInt32 aChildIndex, PRBool aIncrement); // -------------------------------------------------------------------------- // Overloaded nsHTMLContainerFrame methods -- see documentation in nsIFrame.h @@ -125,11 +119,6 @@ public: nsHTMLContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML)); } - NS_IMETHOD - Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow); - NS_IMETHOD AppendFrames(nsIAtom* aListName, nsIFrame* aFrameList); @@ -252,17 +241,10 @@ public: nsBoundingMetrics& aBoundingMetrics, eMathMLFrameType* aMathMLFrameType = nsnull); - // helper to let the scriptstyle re-resolution pass through - // a subtree that may contain non-MathML container frames - static void - PropagateScriptStyleFor(nsIFrame* aFrame, - PRInt32 aParentScriptLevel); - // helper to let the update of presentation data pass through // a subtree that may contain non-MathML container frames static void PropagatePresentationDataFor(nsIFrame* aFrame, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); @@ -270,7 +252,6 @@ public: PropagatePresentationDataFromChildAt(nsIFrame* aParentFrame, PRInt32 aFirstChildIndex, PRInt32 aLastChildIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); @@ -352,24 +333,10 @@ public: NS_ASSERTION(!aListName, "unexpected frame list"); nsresult rv = nsBlockFrame::SetInitialChildList(aListName, aChildList); // re-resolve our subtree to set any mathml-expected data - nsMathMLContainerFrame::MapCommonAttributesIntoCSS(PresContext(), this); nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this); return rv; } - NS_IMETHOD - Reflow(nsPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) - { - if (mScriptStyleChanged) { - mScriptStyleChanged = PR_FALSE; - nsMathMLContainerFrame::PropagateScriptStyleFor(this, 0); - } - return nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); - } - NS_IMETHOD AppendFrames(nsIAtom* aListName, nsIFrame* aFrameList) @@ -421,15 +388,6 @@ protected: AddStateBits(NS_BLOCK_SPACE_MGR); } virtual ~nsMathMLmathBlockFrame() {} - - NS_IMETHOD - DidSetStyleContext() - { - mScriptStyleChanged = PR_TRUE; - return nsBlockFrame::DidSetStyleContext(); - } - - PRBool mScriptStyleChanged; }; // -------------- @@ -445,24 +403,10 @@ public: NS_ASSERTION(!aListName, "unexpected frame list"); nsresult rv = nsInlineFrame::SetInitialChildList(aListName, aChildList); // re-resolve our subtree to set any mathml-expected data - nsMathMLContainerFrame::MapCommonAttributesIntoCSS(PresContext(), this); nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this); return rv; } - NS_IMETHOD - Reflow(nsPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) - { - if (mScriptStyleChanged) { - mScriptStyleChanged = PR_FALSE; - nsMathMLContainerFrame::PropagateScriptStyleFor(this, 0); - } - return nsInlineFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); - } - NS_IMETHOD AppendFrames(nsIAtom* aListName, nsIFrame* aFrameList) @@ -510,15 +454,6 @@ public: protected: nsMathMLmathInlineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {} virtual ~nsMathMLmathInlineFrame() {} - - NS_IMETHOD - DidSetStyleContext() - { - mScriptStyleChanged = PR_TRUE; - return nsInlineFrame::DidSetStyleContext(); - } - - PRBool mScriptStyleChanged; }; #endif /* nsMathMLContainerFrame_h___ */ diff --git a/layout/mathml/base/src/nsMathMLForeignFrameWrapper.h b/layout/mathml/base/src/nsMathMLForeignFrameWrapper.h index c4a317cfc18..9bd21b34c76 100644 --- a/layout/mathml/base/src/nsMathMLForeignFrameWrapper.h +++ b/layout/mathml/base/src/nsMathMLForeignFrameWrapper.h @@ -59,19 +59,11 @@ public: NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(this, - aFirstIndex, aLastIndex, aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); - return NS_OK; - } - - NS_IMETHOD - ReResolveScriptStyle(PRInt32 aParentScriptLevel) - { - nsMathMLContainerFrame::PropagateScriptStyleFor(this, aParentScriptLevel); + aFirstIndex, aLastIndex, aFlagsValues, aFlagsToUpdate); return NS_OK; } diff --git a/layout/mathml/base/src/nsMathMLFrame.cpp b/layout/mathml/base/src/nsMathMLFrame.cpp index 6c6516c77e1..fe5e790413d 100644 --- a/layout/mathml/base/src/nsMathMLFrame.cpp +++ b/layout/mathml/base/src/nsMathMLFrame.cpp @@ -117,13 +117,11 @@ nsMathMLFrame::InheritAutomaticData(nsIFrame* aParent) mPresentationData.flags = 0; mPresentationData.baseFrame = nsnull; mPresentationData.mstyle = nsnull; - mPresentationData.scriptLevel = 0; - // by default, just inherit the display & scriptlevel of our parent + // by default, just inherit the display of our parent nsPresentationData parentData; GetPresentationDataFrom(aParent, parentData); mPresentationData.mstyle = parentData.mstyle; - mPresentationData.scriptLevel = parentData.scriptLevel; if (NS_MATHML_IS_DISPLAYSTYLE(parentData.flags)) { mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; } @@ -136,11 +134,9 @@ nsMathMLFrame::InheritAutomaticData(nsIFrame* aParent) } NS_IMETHODIMP -nsMathMLFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, +nsMathMLFrame::UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aWhichFlags) { - mPresentationData.scriptLevel += aScriptLevelIncrement; // update flags that are relevant to this call if (NS_MATHML_IS_DISPLAYSTYLE(aWhichFlags)) { // updating the displaystyle flag is allowed @@ -215,7 +211,6 @@ nsMathMLFrame::GetPresentationDataFrom(nsIFrame* aFrame, aPresentationData.flags = 0; aPresentationData.baseFrame = nsnull; aPresentationData.mstyle = nsnull; - aPresentationData.scriptLevel = 0; nsIFrame* frame = aFrame; while (frame) { @@ -351,106 +346,6 @@ nsMathMLFrame::GetAxisHeight(nsIRenderingContext& aRenderingContext, } } -// ================ -// Utilities for parsing and retrieving numeric values -// All returned values are in twips. - -/* -The REC says: - An explicit plus sign ('+') is not allowed as part of a numeric value - except when it is specifically listed in the syntax (as a quoted '+' or "+"), - - Units allowed - ID Description - em ems (font-relative unit traditionally used for horizontal lengths) - ex exs (font-relative unit traditionally used for vertical lengths) - px pixels, or pixel size of a "typical computer display" - in inches (1 inch = 2.54 centimeters) - cm centimeters - mm millimeters - pt points (1 point = 1/72 inch) - pc picas (1 pica = 12 points) - % percentage of default value - -Implementation here: - The numeric value is valid only if it is of the form [-] nnn.nnn [h/v-unit] -*/ - -/* static */ PRBool -nsMathMLFrame::ParseNumericValue(nsString& aString, - nsCSSValue& aCSSValue) -{ - aCSSValue.Reset(); - aString.CompressWhitespace(); // aString is not a const in this code... - - PRInt32 stringLength = aString.Length(); - if (!stringLength) - return PR_FALSE; - - nsAutoString number, unit; - - // see if the negative sign is there - PRInt32 i = 0; - PRUnichar c = aString[0]; - if (c == '-') { - number.Append(c); - i++; - - // skip any space after the negative sign - if (i < stringLength && nsCRT::IsAsciiSpace(aString[i])) - i++; - } - - // Gather up characters that make up the number - PRBool gotDot = PR_FALSE; - for ( ; i < stringLength; i++) { - c = aString[i]; - if (gotDot && c == '.') - return PR_FALSE; // two dots encountered - else if (c == '.') - gotDot = PR_TRUE; - else if (!nsCRT::IsAsciiDigit(c)) { - aString.Right(unit, stringLength - i); - unit.CompressWhitespace(); // some authors leave blanks before the unit - break; - } - number.Append(c); - } - - // on exit, also return a nicer string version of the value in case - // the caller wants it (e.g., this removes whitespace before units) - aString.Assign(number); - aString.Append(unit); - - // Convert number to floating point - PRInt32 errorCode; - float floatValue = number.ToFloat(&errorCode); - if (errorCode) - return PR_FALSE; - - nsCSSUnit cssUnit; - if (unit.IsEmpty()) { - cssUnit = eCSSUnit_Number; // no explicit unit, this is a number that will act as a multiplier - } - else if (unit.EqualsLiteral("%")) { - aCSSValue.SetPercentValue(floatValue / 100.0f); - return PR_TRUE; - } - else if (unit.EqualsLiteral("em")) cssUnit = eCSSUnit_EM; - else if (unit.EqualsLiteral("ex")) cssUnit = eCSSUnit_XHeight; - else if (unit.EqualsLiteral("px")) cssUnit = eCSSUnit_Pixel; - else if (unit.EqualsLiteral("in")) cssUnit = eCSSUnit_Inch; - else if (unit.EqualsLiteral("cm")) cssUnit = eCSSUnit_Centimeter; - else if (unit.EqualsLiteral("mm")) cssUnit = eCSSUnit_Millimeter; - else if (unit.EqualsLiteral("pt")) cssUnit = eCSSUnit_Point; - else if (unit.EqualsLiteral("pc")) cssUnit = eCSSUnit_Pica; - else // unexpected unit - return PR_FALSE; - - aCSSValue.SetFloatValue(floatValue, cssUnit); - return PR_TRUE; -} - /* static */ nscoord nsMathMLFrame::CalcLength(nsPresContext* aPresContext, nsStyleContext* aStyleContext, @@ -560,247 +455,6 @@ nsCSSMapping { const char* cssProperty; }; -static void -GetMathMLAttributeStyleSheet(nsPresContext* aPresContext, - nsIStyleSheet** aSheet) -{ - static const char kTitle[] = "Internal MathML/CSS Attribute Style Sheet"; - *aSheet = nsnull; - - // first, look if the attribute stylesheet is already there - nsStyleSet *styleSet = aPresContext->StyleSet(); - NS_ASSERTION(styleSet, "no style set"); - - nsAutoString title; - for (PRInt32 i = styleSet->SheetCount(nsStyleSet::eAgentSheet) - 1; - i >= 0; --i) { - nsIStyleSheet *sheet = styleSet->StyleSheetAt(nsStyleSet::eAgentSheet, i); - nsCOMPtr cssSheet(do_QueryInterface(sheet)); - if (cssSheet) { - cssSheet->GetTitle(title); - if (title.Equals(NS_ConvertASCIItoUTF16(kTitle))) { - *aSheet = sheet; - NS_IF_ADDREF(*aSheet); - return; - } - } - } - - // then, create a new one if it isn't yet there - nsCOMPtr uri; - NS_NewURI(getter_AddRefs(uri), "about:internal-mathml-attribute-stylesheet"); - if (!uri) - return; - nsCOMPtr cssSheet(do_CreateInstance(kCSSStyleSheetCID)); - if (!cssSheet) - return; - cssSheet->SetURIs(uri, nsnull, uri); - cssSheet->SetTitle(NS_ConvertASCIItoUTF16(kTitle)); - // all done, no further activity from the net involved, so we better do this - cssSheet->SetComplete(); - - nsCOMPtr domSheet(do_QueryInterface(cssSheet)); - if (domSheet) { - PRUint32 index; - domSheet->InsertRule(NS_LITERAL_STRING("@namespace url(http://www.w3.org/1998/Math/MathML);"), - 0, &index); - } - - // insert the stylesheet into the styleset without notifying observers - // XXX Should this be at a different level? - styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, cssSheet); - *aSheet = cssSheet; - NS_ADDREF(*aSheet); -} - -/* static */ PRInt32 -nsMathMLFrame::MapCommonAttributesIntoCSS(nsPresContext* aPresContext, - nsIContent* aContent) -{ - // normal case, quick return if there are no attributes - NS_ASSERTION(aContent, "null arg"); - PRUint32 attrCount = 0; - if (aContent) - attrCount = aContent->GetAttrCount(); - if (!attrCount) - return 0; - - // need to initialize here -- i.e., after registering nsGkAtoms - static const nsCSSMapping - kCSSMappingTable[] = { - {kMathMLversion2, nsGkAtoms::mathcolor_, "color:"}, - {kMathMLversion1, nsGkAtoms::color, "color:"}, - {kMathMLversion2, nsGkAtoms::mathsize_, "font-size:"}, - {kMathMLversion1, nsGkAtoms::fontsize_, "font-size:"}, - {kMathMLversion1, nsGkAtoms::fontfamily_, "font-family:"}, - {kMathMLversion2, nsGkAtoms::mathbackground_, "background-color:"}, - {kMathMLversion1, nsGkAtoms::background, "background-color:"}, - {0, nsnull, nsnull} - }; - - nsCOMPtr doc; - nsCOMPtr sheet; - nsCOMPtr cssSheet; - nsCOMPtr domSheet; - - PRInt32 ruleCount = 0; - for (PRUint32 i = 0; i < attrCount; ++i) { - const nsAttrName* name = aContent->GetAttrNameAt(i); - if (name->NamespaceID() != kNameSpaceID_None) - continue; - - nsIAtom* attrAtom = name->LocalName(); - - // lookup the equivalent CSS property - const nsCSSMapping* map = kCSSMappingTable; - while (map->attrAtom && map->attrAtom != attrAtom) - ++map; - if (!map->attrAtom) - continue; - nsAutoString cssProperty(NS_ConvertASCIItoUTF16(map->cssProperty)); - - nsAutoString attrValue; - aContent->GetAttr(kNameSpaceID_None, attrAtom, attrValue); - if (attrValue.IsEmpty()) - continue; - nsAutoString escapedAttrValue; - nsStyleUtil::EscapeCSSString(attrValue, escapedAttrValue); - - // don't add rules that are already in mathml.css - // (this will also clean up whitespace before units - see bug 125303) - if (attrAtom == nsGkAtoms::fontsize_ || attrAtom == nsGkAtoms::mathsize_) { - nsCSSValue cssValue; - nsAutoString numericValue(attrValue); - if (!ParseNumericValue(numericValue, cssValue)) - continue; - // on exit, ParseNumericValue also returns a nicer string - // in which the whitespace before the unit is cleaned up - cssProperty.Append(numericValue); - } - else - cssProperty.Append(attrValue); - - nsAutoString attrName; - attrAtom->ToString(attrName); - - // make a style rule that maps to the equivalent CSS property - nsAutoString selector, cssRule; - selector.Assign(NS_LITERAL_STRING("[") + attrName + - NS_LITERAL_STRING("=\"") + escapedAttrValue + - NS_LITERAL_STRING("\"]")); - cssRule.Assign(selector + - NS_LITERAL_STRING("{") + cssProperty + NS_LITERAL_STRING("}")); - - if (!sheet) { - // first time... we do this to defer the lookup up to the - // point where we encounter attributes that actually matter - doc = aContent->GetDocument(); - if (!doc) - return 0; - GetMathMLAttributeStyleSheet(aPresContext, getter_AddRefs(sheet)); - if (!sheet) - return 0; - // by construction, these cannot be null at this point - cssSheet = do_QueryInterface(sheet); - domSheet = do_QueryInterface(sheet); - NS_ASSERTION(cssSheet && domSheet, "unexpected null pointers"); - // we will keep the sheet orphan as we populate it. This way, - // observers of the document won't be notified and we avoid any troubles - // that may come from reconstructing the frame tree. Our rules only need - // a re-resolve of style data and a reflow, not a reconstruct-all... - sheet->SetOwningDocument(nsnull); - } - - // check for duplicate, if a similar rule is already there, - // don't bother to add another one - PRInt32 k, count; - cssSheet->StyleRuleCount(count); - for (k = 0; k < count; ++k) { - nsAutoString tmpSelector; - nsCOMPtr tmpRule; - cssSheet->GetStyleRuleAt(k, *getter_AddRefs(tmpRule)); - nsCOMPtr tmpStyleRule = do_QueryInterface(tmpRule); - if (tmpStyleRule) { - tmpStyleRule->GetSelectorText(tmpSelector); - NS_ASSERTION(tmpSelector.CharAt(0) != '*', "unexpected universal symbol"); -#ifdef DEBUG_rbs - nsCAutoString str; - LossyAppendUTF16toASCII(selector, str); - str.AppendLiteral(" vs "); - LossyAppendUTF16toASCII(tmpSelector, str); - printf("Attr selector %s %s\n", str.get(), - tmpSelector.Equals(selector)? " ... match" : " ... nomatch"); -#endif - if (tmpSelector.Equals(selector)) { - k = -1; - break; - } - } - } - if (k >= 0) { - // insert the rule (note: when the sheet already has @namespace and - // friends, insert after them, e.g., at the end, otherwise it won't work) - // For MathML 2, insert at the end to give it precedence - PRInt32 pos = (map->compatibility == kMathMLversion2) ? count : 1; - PRUint32 index; - domSheet->InsertRule(cssRule, pos, &index); - ++ruleCount; - } - } - // restore the sheet to its owner - if (sheet) { - sheet->SetOwningDocument(doc); - } - - return ruleCount; -} - -/* static */ PRInt32 -nsMathMLFrame::MapCommonAttributesIntoCSS(nsPresContext* aPresContext, - nsIFrame* aFrame) -{ - PRInt32 ruleCount = MapCommonAttributesIntoCSS(aPresContext, aFrame->GetContent()); - if (!ruleCount) - return 0; - - // now, re-resolve the style contexts in our subtree - nsFrameManager *fm = aPresContext->FrameManager(); - nsStyleChangeList changeList; - fm->ComputeStyleChangeFor(aFrame, &changeList, NS_STYLE_HINT_NONE); -#ifdef DEBUG - // Use the parent frame to make sure we catch in-flows and such - nsIFrame* parentFrame = aFrame->GetParent(); - fm->DebugVerifyStyleTree(parentFrame ? parentFrame : aFrame); -#endif - - return ruleCount; -} - -/* static */ PRBool -nsMathMLFrame::CommonAttributeChangedFor(nsPresContext* aPresContext, - nsIContent* aContent, - nsIAtom* aAttribute) -{ - if (aAttribute == nsGkAtoms::mathcolor_ || - aAttribute == nsGkAtoms::color || - aAttribute == nsGkAtoms::mathsize_ || - aAttribute == nsGkAtoms::fontsize_ || - aAttribute == nsGkAtoms::fontfamily_ || - aAttribute == nsGkAtoms::mathbackground_ || - aAttribute == nsGkAtoms::background) { - - MapCommonAttributesIntoCSS(aPresContext, aContent); - - // That's all folks. Common attributes go in the internal MathML attribute - // stylesheet. So when nsCSSFrameConstructor checks if the content - // HasAttributeDependentStyle(), it will detect them and issue a - // PostRestyleEvent() to re-resolve the style data and reflow if needed. - return PR_TRUE; - } - - return PR_FALSE; -} - #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) class nsDisplayMathMLBoundingMetrics : public nsDisplayItem { public: diff --git a/layout/mathml/base/src/nsMathMLFrame.h b/layout/mathml/base/src/nsMathMLFrame.h index 5a0b8eaaed7..05e41030681 100644 --- a/layout/mathml/base/src/nsMathMLFrame.h +++ b/layout/mathml/base/src/nsMathMLFrame.h @@ -49,6 +49,7 @@ #include "nsIMathMLFrame.h" #include "nsFrame.h" #include "nsCSSValue.h" +#include "nsMathMLElement.h" class nsMathMLChar; @@ -149,26 +150,18 @@ public: } NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, + UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { return NS_OK; } - NS_IMETHOD - ReResolveScriptStyle(PRInt32 aParentScriptLevel) - { - return NS_OK; - } - // helper to give a style context suitable for doing the stretching to the // MathMLChar. Frame classes that use this should make the extra style contexts // accessible to the Style System via Get/Set AdditionalStyleContext. @@ -223,8 +216,10 @@ public: // utilities to parse and retrieve numeric values in CSS units // All values are stored in twips. static PRBool - ParseNumericValue(nsString& aString, - nsCSSValue& aCSSValue); + ParseNumericValue(const nsString& aString, + nsCSSValue& aCSSValue) { + return nsMathMLElement::ParseNumericValue(aString, aCSSValue, PR_FALSE); + } static nscoord CalcLength(nsPresContext* aPresContext, @@ -433,24 +428,6 @@ public: nsIFontMetrics* aFontMetrics, nscoord& aAxisHeight); - // ================ - // helpers to map attributes into CSS rules (work-around to bug 69409 which - // is not scheduled to be fixed anytime soon) - static PRInt32 - MapCommonAttributesIntoCSS(nsPresContext* aPresContext, - nsIContent* aContent); - static PRInt32 - MapCommonAttributesIntoCSS(nsPresContext* aPresContext, - nsIFrame* aFrame); - - // helper used by all AttributeChanged() methods. It handles - // those attributes that are common to all tags. - // @return true if the attribue is handled. - static PRBool - CommonAttributeChangedFor(nsPresContext* aPresContext, - nsIContent* aContent, - nsIAtom* aAttribute); - protected: #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) nsresult DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder, diff --git a/layout/mathml/base/src/nsMathMLmfencedFrame.cpp b/layout/mathml/base/src/nsMathMLmfencedFrame.cpp index 91009c63a13..976a42a926e 100644 --- a/layout/mathml/base/src/nsMathMLmfencedFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmfencedFrame.cpp @@ -267,7 +267,8 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, PRInt32 i; nsCOMPtr fm; - aReflowState.rendContext->SetFont(aForFrame->GetStyleFont()->mFont, nsnull); + const nsStyleFont* font = aForFrame->GetStyleFont(); + aReflowState.rendContext->SetFont(font->mFont, nsnull); aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm)); nscoord axisHeight, em; GetAxisHeight(*aReflowState.rendContext, fm, axisHeight); @@ -390,19 +391,19 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext, ///////////////// // opening fence ... ReflowChar(aPresContext, *aReflowState.rendContext, aOpenChar, - NS_MATHML_OPERATOR_FORM_PREFIX, presentationData.scriptLevel, + NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); ///////////////// // separators ... for (i = 0; i < aSeparatorsCount; i++) { ReflowChar(aPresContext, *aReflowState.rendContext, &aSeparatorsChar[i], - NS_MATHML_OPERATOR_FORM_INFIX, presentationData.scriptLevel, + NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); } ///////////////// // closing fence ... ReflowChar(aPresContext, *aReflowState.rendContext, aCloseChar, - NS_MATHML_OPERATOR_FORM_POSTFIX, presentationData.scriptLevel, + NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); ////////////////// diff --git a/layout/mathml/base/src/nsMathMLmfracFrame.cpp b/layout/mathml/base/src/nsMathMLmfracFrame.cpp index 3669cc16630..9a3d663b9e4 100644 --- a/layout/mathml/base/src/nsMathMLmfracFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmfracFrame.cpp @@ -130,13 +130,14 @@ nsMathMLmfracFrame::TransmitAutomaticData() // false increments scriptlevel by 1, within numerator and denominator. // 2. The TeXbook (Ch 17. p.141) says the numerator inherits the compression // while the denominator is compressed - PRInt32 increment = - NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) ? 0 : 1; - mInnerScriptLevel = mPresentationData.scriptLevel + increment; - UpdatePresentationDataFromChildAt(0, -1, increment, + SetIncrementScriptLevel(0, !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)); + // XXXroc how come point 1 above says we should increment scriptlevel for + // the denominator, but the old code didn't? + + UpdatePresentationDataFromChildAt(0, -1, ~NS_MATHML_DISPLAYSTYLE, NS_MATHML_DISPLAYSTYLE); - UpdatePresentationDataFromChildAt(1, 1, 0, + UpdatePresentationDataFromChildAt(1, 1, NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); @@ -477,55 +478,9 @@ nsMathMLmfracFrame::AttributeChanged(PRInt32 aNameSpaceID, AttributeChanged(aNameSpaceID, aAttribute, aModType); } -NS_IMETHODIMP -nsMathMLmfracFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate) -{ - // mfrac is special... The REC says: - // The element sets displaystyle to "false", or if it was already - // false increments scriptlevel by 1, within numerator and denominator. - // @see similar peculiarities for , , - - // This means that - // 1. If our displaystyle is being changed from true to false, we have - // to propagate an inner scriptlevel increment to our children - // 2. If the displaystyle is changed from false to true, we have to undo - // any incrementation that was done on the inner scriptlevel - - if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsToUpdate)) { - if (mInnerScriptLevel > mPresentationData.scriptLevel) { - // we get here if our displaystyle is currently false - NS_ASSERTION(!NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags), "out of sync"); - if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) { - // ...and is being set to true, so undo the inner increment now - mInnerScriptLevel = mPresentationData.scriptLevel; - UpdatePresentationDataFromChildAt(0, -1, -1, 0, 0); - } - } - else { - // case of mInnerScriptLevel == mPresentationData.scriptLevel, our - // current displaystyle is true; we increment the inner scriptlevel if - // our displaystyle is about to be set to false; since mInnerScriptLevel - // is changed, we can only get here once - NS_ASSERTION(NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags), "out of sync"); - if (!NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) { - mInnerScriptLevel = mPresentationData.scriptLevel + 1; - UpdatePresentationDataFromChildAt(0, -1, 1, 0, 0); - } - } - } - - mInnerScriptLevel += aScriptLevelIncrement; - return nsMathMLContainerFrame:: - UpdatePresentationData(aScriptLevelIncrement, aFlagsValues, - aFlagsToUpdate); -} - NS_IMETHODIMP nsMathMLmfracFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { @@ -545,7 +500,7 @@ nsMathMLmfracFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstInde #endif return nsMathMLContainerFrame:: UpdatePresentationDataFromChildAt(aFirstIndex, aLastIndex, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + aFlagsValues, aFlagsToUpdate); } // ---------------------- diff --git a/layout/mathml/base/src/nsMathMLmfracFrame.h b/layout/mathml/base/src/nsMathMLmfracFrame.h index d32f7ac7660..87e3592dde5 100644 --- a/layout/mathml/base/src/nsMathMLmfracFrame.h +++ b/layout/mathml/base/src/nsMathMLmfracFrame.h @@ -124,15 +124,9 @@ public: NS_IMETHOD TransmitAutomaticData(); - NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate); - NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); @@ -157,7 +151,6 @@ protected: PRBool IsBevelled(); - PRInt32 mInnerScriptLevel; nsRect mLineRect; nsMathMLChar* mSlashChar; }; diff --git a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp index cccb4b6ec9f..23da493be49 100644 --- a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp @@ -73,7 +73,7 @@ nsMathMLmmultiscriptsFrame::TransmitAutomaticData() // The REC says: // The element increments scriptlevel by 1, and sets // displaystyle to "false", within each of its arguments except base - UpdatePresentationDataFromChildAt(1, -1, 1, + UpdatePresentationDataFromChildAt(1, -1, ~NS_MATHML_DISPLAYSTYLE, NS_MATHML_DISPLAYSTYLE); // The TeXbook (Ch 17. p.141) says the superscript inherits the compression @@ -106,7 +106,7 @@ nsMathMLmmultiscriptsFrame::TransmitAutomaticData() } for (PRInt32 i = subScriptFrames.Count() - 1; i >= 0; i--) { childFrame = (nsIFrame*)subScriptFrames[i]; - PropagatePresentationDataFor(childFrame, 0, + PropagatePresentationDataFor(childFrame, NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); } @@ -158,7 +158,8 @@ nsMathMLmmultiscriptsFrame::Place(nsIRenderingContext& aRenderingContext, ProcessAttributes(); // get x-height (an ex) - aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull); + const nsStyleFont* font = GetStyleFont(); + aRenderingContext.SetFont(font->mFont, nsnull); nsCOMPtr fm; aRenderingContext.GetFontMetrics(*getter_AddRefs(fm)); @@ -217,7 +218,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIRenderingContext& aRenderingContext, // get sup script shift depending on current script level and display style // Rule 18c, App. G, TeXbook nscoord supScriptShift; - if ( mPresentationData.scriptLevel == 0 && + if ( font->mScriptLevel == 0 && NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) && !NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { // Style D in TeXbook diff --git a/layout/mathml/base/src/nsMathMLmoFrame.cpp b/layout/mathml/base/src/nsMathMLmoFrame.cpp index 2a697a0aff2..4193a614dbe 100644 --- a/layout/mathml/base/src/nsMathMLmoFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmoFrame.cpp @@ -397,7 +397,7 @@ nsMathMLmoFrame::ProcessOperatorData() // tuning if we don't want too much extra space when we are a script. // (with its fonts, TeX sets lspace=0 & rspace=0 as soon as scriptlevel>0. // Our fonts can be anything, so...) - if (mPresentationData.scriptLevel > 0) { + if (GetStyleFont()->mScriptLevel > 0) { if (NS_MATHML_OPERATOR_EMBELLISH_IS_ISOLATED(mFlags)) { // could be an isolated accent or script, e.g., x^{+}, just zero out mEmbellishData.leftSpace = 0; diff --git a/layout/mathml/base/src/nsMathMLmoverFrame.cpp b/layout/mathml/base/src/nsMathMLmoverFrame.cpp index 3e66a0f42f5..bf42708ac7c 100644 --- a/layout/mathml/base/src/nsMathMLmoverFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmoverFrame.cpp @@ -82,12 +82,10 @@ nsMathMLmoverFrame::AttributeChanged(PRInt32 aNameSpaceID, } NS_IMETHODIMP -nsMathMLmoverFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, +nsMathMLmoverFrame::UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { - nsMathMLContainerFrame::UpdatePresentationData( - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate); // disable the stretch-all flag if we are going to act like a superscript if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { @@ -102,7 +100,6 @@ nsMathMLmoverFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement NS_IMETHODIMP nsMathMLmoverFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { @@ -126,8 +123,7 @@ nsMathMLmoverFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstInde aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE; aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE; } - PropagatePresentationDataFor(childFrame, aScriptLevelIncrement, - aFlagsValues, aFlagsToUpdate); + PropagatePresentationDataFor(childFrame, aFlagsValues, aFlagsToUpdate); } index++; childFrame = childFrame->GetNextSibling(); @@ -219,11 +215,10 @@ XXX The winner is the outermost in conflicting settings like these: that math accents and \overline change uncramped styles to their cramped counterparts. */ - PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) - ? 0 : 1; + SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)); PRUint32 compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) ? NS_MATHML_COMPRESSED : 0; - PropagatePresentationDataFor(overscriptFrame, increment, + PropagatePresentationDataFor(overscriptFrame, ~NS_MATHML_DISPLAYSTYLE | compress, NS_MATHML_DISPLAYSTYLE | compress); diff --git a/layout/mathml/base/src/nsMathMLmoverFrame.h b/layout/mathml/base/src/nsMathMLmoverFrame.h index e5339319e16..c28e33e0991 100644 --- a/layout/mathml/base/src/nsMathMLmoverFrame.h +++ b/layout/mathml/base/src/nsMathMLmoverFrame.h @@ -64,14 +64,12 @@ public: TransmitAutomaticData(); NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, + UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); diff --git a/layout/mathml/base/src/nsMathMLmrootFrame.cpp b/layout/mathml/base/src/nsMathMLmrootFrame.cpp index fdeb5d380b2..0b153c7f2ea 100644 --- a/layout/mathml/base/src/nsMathMLmrootFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmrootFrame.cpp @@ -111,10 +111,10 @@ nsMathMLmrootFrame::TransmitAutomaticData() // The element increments scriptlevel by 2, and sets displaystyle to // "false", within index, but leaves both attributes unchanged within base. // 2. The TeXbook (Ch 17. p.141) says \sqrt is compressed - UpdatePresentationDataFromChildAt(1, 1, 2, + UpdatePresentationDataFromChildAt(1, 1, ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); - UpdatePresentationDataFromChildAt(0, 0, 0, + UpdatePresentationDataFromChildAt(0, 0, NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); return NS_OK; diff --git a/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp b/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp index 20cffd82b5e..19587d7600e 100644 --- a/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp @@ -124,7 +124,7 @@ nsMathMLmsqrtFrame::TransmitAutomaticData() // The element leaves both attributes [displaystyle and scriptlevel] // unchanged within all its arguments. // 2. The TeXBook (Ch 17. p.141) says that \sqrt is cramped - UpdatePresentationDataFromChildAt(0, -1, 0, + UpdatePresentationDataFromChildAt(0, -1, NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); diff --git a/layout/mathml/base/src/nsMathMLmstyleFrame.cpp b/layout/mathml/base/src/nsMathMLmstyleFrame.cpp index ab48344b2ed..1f2f81f2871 100644 --- a/layout/mathml/base/src/nsMathMLmstyleFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmstyleFrame.cpp @@ -77,23 +77,6 @@ nsMathMLmstyleFrame::InheritAutomaticData(nsIFrame* aParent) // see if the displaystyle attribute is there nsMathMLFrame::FindAttrDisplaystyle(mContent, mPresentationData); - // see if the scriptlevel attribute is there - nsAutoString value; - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::scriptlevel_, value); - if (!value.IsEmpty()) { - PRInt32 errorCode, userValue; - userValue = value.ToInteger(&errorCode); - if (!errorCode) { - if (value[0] != '+' && value[0] != '-') { // record that it is an explicit value - mPresentationData.flags |= NS_MATHML_EXPLICIT_SCRIPTLEVEL; - mPresentationData.scriptLevel = userValue; - } - else { - mPresentationData.scriptLevel += userValue; // incremental value... - } - } - } - return NS_OK; } @@ -112,8 +95,7 @@ nsMathMLmstyleFrame::TransmitAutomaticData() // Since UpdatePresentation() and UpdatePresentationDataFromChildAt() can be called // by a parent, ensure that the explicit attributes of take precedence NS_IMETHODIMP -nsMathMLmstyleFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, +nsMathMLmstyleFrame::UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aWhichFlags) { if (NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(mPresentationData.flags)) { @@ -121,19 +103,13 @@ nsMathMLmstyleFrame::UpdatePresentationData(PRInt32 aScriptLevelIncremen aWhichFlags &= ~NS_MATHML_DISPLAYSTYLE; aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE; } - if (NS_MATHML_HAS_EXPLICIT_SCRIPTLEVEL(mPresentationData.flags)) { - // our current state takes precedence, disallow updating the scriptlevel - aScriptLevelIncrement = 0; - } - return nsMathMLContainerFrame::UpdatePresentationData( - aScriptLevelIncrement, aFlagsValues, aWhichFlags); + return nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aWhichFlags); } NS_IMETHODIMP nsMathMLmstyleFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aWhichFlags) { @@ -142,16 +118,11 @@ nsMathMLmstyleFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstInd aWhichFlags &= ~NS_MATHML_DISPLAYSTYLE; aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE; } - if (NS_MATHML_HAS_EXPLICIT_SCRIPTLEVEL(mPresentationData.flags)) { - // our current state takes precedence, disallow updating the scriptlevel - aScriptLevelIncrement = 0; - } // let the base class worry about the update return nsMathMLContainerFrame::UpdatePresentationDataFromChildAt( - aFirstIndex, aLastIndex, aScriptLevelIncrement, - aFlagsValues, aWhichFlags); + aFirstIndex, aLastIndex, aFlagsValues, aWhichFlags); } NS_IMETHODIMP @@ -159,10 +130,6 @@ nsMathMLmstyleFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aModType) { - // Attributes common to MathML tags - if (CommonAttributeChangedFor(PresContext(), mContent, aAttribute)) - return NS_OK; - // Other attributes can affect too many things, ask our parent to re-layout // its children so that we can pick up changes in our attributes & transmit // them in our subtree. However, our siblings will be re-laid too. We used diff --git a/layout/mathml/base/src/nsMathMLmstyleFrame.h b/layout/mathml/base/src/nsMathMLmstyleFrame.h index fb3eafccfa8..0bc9e2cd8d7 100644 --- a/layout/mathml/base/src/nsMathMLmstyleFrame.h +++ b/layout/mathml/base/src/nsMathMLmstyleFrame.h @@ -63,14 +63,12 @@ public: TransmitAutomaticData(); NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, + UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); diff --git a/layout/mathml/base/src/nsMathMLmsubFrame.cpp b/layout/mathml/base/src/nsMathMLmsubFrame.cpp index 4e380ab3826..340ec43e8c7 100644 --- a/layout/mathml/base/src/nsMathMLmsubFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsubFrame.cpp @@ -74,7 +74,7 @@ nsMathMLmsubFrame::TransmitAutomaticData() // The element increments scriptlevel by 1, and sets displaystyle to // "false", within subscript, but leaves both attributes unchanged within base. // 2. The TeXbook (Ch 17. p.141) says the subscript is compressed - UpdatePresentationDataFromChildAt(1, -1, 1, + UpdatePresentationDataFromChildAt(1, -1, ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); diff --git a/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp b/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp index 55b9bfe151f..aa33cec9725 100644 --- a/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp @@ -76,10 +76,10 @@ nsMathMLmsubsupFrame::TransmitAutomaticData() // unchanged within base. // 2. The TeXbook (Ch 17. p.141) says the superscript inherits the compression // while the subscript is compressed - UpdatePresentationDataFromChildAt(1, -1, 1, + UpdatePresentationDataFromChildAt(1, -1, ~NS_MATHML_DISPLAYSTYLE, NS_MATHML_DISPLAYSTYLE); - UpdatePresentationDataFromChildAt(1, 1, 0, + UpdatePresentationDataFromChildAt(1, 1, NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); @@ -254,7 +254,7 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(nsPresContext* aPresContext, nscoord supScriptShift; nsPresentationData presentationData; aFrame->GetPresentationData(presentationData); - if ( presentationData.scriptLevel == 0 && + if ( aFrame->GetStyleFont()->mScriptLevel == 0 && NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) && !NS_MATHML_IS_COMPRESSED(presentationData.flags)) { // Style D in TeXbook diff --git a/layout/mathml/base/src/nsMathMLmsupFrame.cpp b/layout/mathml/base/src/nsMathMLmsupFrame.cpp index f7d97a24860..c36ee3b5b33 100644 --- a/layout/mathml/base/src/nsMathMLmsupFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsupFrame.cpp @@ -74,7 +74,7 @@ nsMathMLmsupFrame::TransmitAutomaticData() // "false", within superscript, but leaves both attributes unchanged within base. // 2. The TeXbook (Ch 17. p.141) says the superscript *inherits* the compression, // so we don't set the compression flag. Our parent will propagate its own. - UpdatePresentationDataFromChildAt(1, -1, 1, + UpdatePresentationDataFromChildAt(1, -1, ~NS_MATHML_DISPLAYSTYLE, NS_MATHML_DISPLAYSTYLE); @@ -190,7 +190,7 @@ nsMathMLmsupFrame::PlaceSuperScript(nsPresContext* aPresContext, nscoord supScriptShift; nsPresentationData presentationData; aFrame->GetPresentationData (presentationData); - if ( presentationData.scriptLevel == 0 && + if ( aFrame->GetStyleFont()->mScriptLevel == 0 && NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) && !NS_MATHML_IS_COMPRESSED(presentationData.flags)) { // Style D in TeXbook diff --git a/layout/mathml/base/src/nsMathMLmtableFrame.cpp b/layout/mathml/base/src/nsMathMLmtableFrame.cpp index 5abaf2afe1d..f691a77e61f 100644 --- a/layout/mathml/base/src/nsMathMLmtableFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmtableFrame.cpp @@ -350,22 +350,12 @@ nsMathMLmtableOuterFrame::~nsMathMLmtableOuterFrame() { } -NS_IMETHODIMP -nsMathMLmtableOuterFrame::Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow) -{ - nsresult rv = nsTableOuterFrame::Init(aContent, aParent, aPrevInFlow); - nsMathMLFrame::MapCommonAttributesIntoCSS(PresContext(), aContent); - return rv; -} - NS_IMETHODIMP nsMathMLmtableOuterFrame::InheritAutomaticData(nsIFrame* aParent) { // XXX the REC says that by default, displaystyle=false in - // let the base class inherit the scriptlevel and displaystyle from our parent + // let the base class inherit the displaystyle from our parent nsMathMLFrame::InheritAutomaticData(aParent); // see if the displaystyle attribute is there and let it override what we inherited @@ -379,8 +369,7 @@ nsMathMLmtableOuterFrame::InheritAutomaticData(nsIFrame* aParent) // Since UpdatePresentation() and UpdatePresentationDataFromChildAt() can be called // by a parent, ensure that the displaystyle attribute of mtable takes precedence NS_IMETHODIMP -nsMathMLmtableOuterFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, +nsMathMLmtableOuterFrame::UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aWhichFlags) { if (NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(mPresentationData.flags)) { @@ -389,14 +378,12 @@ nsMathMLmtableOuterFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE; } - return nsMathMLFrame::UpdatePresentationData( - aScriptLevelIncrement, aFlagsValues, aWhichFlags); + return nsMathMLFrame::UpdatePresentationData(aFlagsValues, aWhichFlags); } NS_IMETHODIMP nsMathMLmtableOuterFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aWhichFlags) { @@ -407,7 +394,7 @@ nsMathMLmtableOuterFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex } nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(this, - aFirstIndex, aLastIndex, aScriptLevelIncrement, aFlagsValues, aWhichFlags); + aFirstIndex, aLastIndex, aFlagsValues, aWhichFlags); return NS_OK; } @@ -417,10 +404,6 @@ nsMathMLmtableOuterFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aModType) { - // Attributes common to MathML tags - if (nsMathMLFrame::CommonAttributeChangedFor(PresContext(), mContent, aAttribute)) - return NS_OK; - // Attributes specific to : // frame : in mathml.css // framespacing : not yet supported @@ -456,7 +439,6 @@ nsMathMLmtableOuterFrame::AttributeChanged(PRInt32 aNameSpaceID, // presentational data, and issue a style-changed reflow request if (aAttribute == nsGkAtoms::displaystyle_) { nsMathMLContainerFrame::RebuildAutomaticDataForChildren(mParent); - nsMathMLContainerFrame::PropagateScriptStyleFor(tableFrame, mPresentationData.scriptLevel); // Need to reflow the parent, not us, because this can actually // affect siblings. PresContext()->PresShell()-> @@ -706,25 +688,11 @@ nsMathMLmtrFrame::~nsMathMLmtrFrame() { } -NS_IMETHODIMP -nsMathMLmtrFrame::Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow) -{ - nsresult rv = nsTableRowFrame::Init(aContent, aParent, aPrevInFlow); - nsMathMLFrame::MapCommonAttributesIntoCSS(PresContext(), aContent); - return rv; -} - NS_IMETHODIMP nsMathMLmtrFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aModType) { - // Attributes common to MathML tags - if (nsMathMLFrame::CommonAttributeChangedFor(PresContext(), mContent, aAttribute)) - return NS_OK; - // Attributes specific to : // groupalign : Not yet supported. // rowalign : Fully specified in mathml.css, and so HasAttributeDependentStyle() will @@ -781,16 +749,6 @@ nsMathMLmtdFrame::~nsMathMLmtdFrame() { } -NS_IMETHODIMP -nsMathMLmtdFrame::Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow) -{ - nsresult rv = nsTableCellFrame::Init(aContent, aParent, aPrevInFlow); - nsMathMLFrame::MapCommonAttributesIntoCSS(PresContext(), aContent); - return rv; -} - PRInt32 nsMathMLmtdFrame::GetRowSpan() { @@ -834,10 +792,6 @@ nsMathMLmtdFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aModType) { - // Attributes common to MathML tags - if (nsMathMLFrame::CommonAttributeChangedFor(PresContext(), mContent, aAttribute)) - return NS_OK; - // Attributes specific to : // groupalign : Not yet supported // rowalign : in mathml.css diff --git a/layout/mathml/base/src/nsMathMLmtableFrame.h b/layout/mathml/base/src/nsMathMLmtableFrame.h index bbf0322c505..5bfbb23f045 100644 --- a/layout/mathml/base/src/nsMathMLmtableFrame.h +++ b/layout/mathml/base/src/nsMathMLmtableFrame.h @@ -60,31 +60,17 @@ public: InheritAutomaticData(nsIFrame* aParent); NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, + UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aWhichFlags); NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aWhichFlags); - NS_IMETHOD - ReResolveScriptStyle(PRInt32 aParentScriptLevel) - { - nsMathMLContainerFrame::PropagateScriptStyleFor(this, aParentScriptLevel); - return NS_OK; - } - // overloaded nsTableOuterFrame methods - NS_IMETHOD - Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow); - NS_IMETHOD Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -182,11 +168,6 @@ public: // overloaded nsTableRowFrame methods - NS_IMETHOD - Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow); - NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, @@ -251,11 +232,6 @@ public: // overloaded nsTableCellFrame methods - NS_IMETHOD - Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow); - NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, @@ -287,19 +263,11 @@ public: NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(this, - aFirstIndex, aLastIndex, aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); - return NS_OK; - } - - NS_IMETHOD - ReResolveScriptStyle(PRInt32 aParentScriptLevel) - { - nsMathMLContainerFrame::PropagateScriptStyleFor(this, aParentScriptLevel); + aFirstIndex, aLastIndex, aFlagsValues, aFlagsToUpdate); return NS_OK; } diff --git a/layout/mathml/base/src/nsMathMLmunderFrame.cpp b/layout/mathml/base/src/nsMathMLmunderFrame.cpp index 56f2e637a94..2ffd7e01674 100644 --- a/layout/mathml/base/src/nsMathMLmunderFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmunderFrame.cpp @@ -82,12 +82,10 @@ nsMathMLmunderFrame::AttributeChanged(PRInt32 aNameSpaceID, } NS_IMETHODIMP -nsMathMLmunderFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, +nsMathMLmunderFrame::UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { - nsMathMLContainerFrame::UpdatePresentationData( - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate); // disable the stretch-all flag if we are going to act like a subscript if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { @@ -102,7 +100,6 @@ nsMathMLmunderFrame::UpdatePresentationData(PRInt32 aScriptLevelIncremen NS_IMETHODIMP nsMathMLmunderFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { @@ -126,8 +123,7 @@ nsMathMLmunderFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstInd aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE; aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE; } - PropagatePresentationDataFor(childFrame, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + PropagatePresentationDataFor(childFrame, aFlagsValues, aFlagsToUpdate); } index++; childFrame = childFrame->GetNextSibling(); @@ -217,9 +213,8 @@ XXX The winner is the outermost setting in conflicting settings like these: The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a say it should be compressed */ - PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags) - ? 0 : 1; - PropagatePresentationDataFor(underscriptFrame, increment, + SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)); + PropagatePresentationDataFor(underscriptFrame, ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); diff --git a/layout/mathml/base/src/nsMathMLmunderFrame.h b/layout/mathml/base/src/nsMathMLmunderFrame.h index 706da06f7e7..0126fe70fea 100644 --- a/layout/mathml/base/src/nsMathMLmunderFrame.h +++ b/layout/mathml/base/src/nsMathMLmunderFrame.h @@ -64,14 +64,12 @@ public: TransmitAutomaticData(); NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, + UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); diff --git a/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp b/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp index 8b00a2eee01..6e93454cfa2 100644 --- a/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp @@ -83,12 +83,10 @@ nsMathMLmunderoverFrame::AttributeChanged(PRInt32 aNameSpaceID, } NS_IMETHODIMP -nsMathMLmunderoverFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, +nsMathMLmunderoverFrame::UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { - nsMathMLContainerFrame::UpdatePresentationData(aScriptLevelIncrement, - aFlagsValues, aFlagsToUpdate); + nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate); // disable the stretch-all flag if we are going to act like a subscript-superscript pair if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { @@ -103,7 +101,6 @@ nsMathMLmunderoverFrame::UpdatePresentationData(PRInt32 aScriptLevelIncr NS_IMETHODIMP nsMathMLmunderoverFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate) { @@ -132,8 +129,7 @@ nsMathMLmunderoverFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirs aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE; aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE; } - PropagatePresentationDataFor(childFrame, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + PropagatePresentationDataFor(childFrame, aFlagsValues, aFlagsToUpdate); } index++; childFrame = childFrame->GetNextSibling(); @@ -242,11 +238,10 @@ nsMathMLmunderoverFrame::TransmitAutomaticData() that math accents and \overline change uncramped styles to their cramped counterparts. */ - PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) - ? 0 : 1; PRUint32 compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) ? NS_MATHML_COMPRESSED : 0; - PropagatePresentationDataFor(overscriptFrame, increment, + SetIncrementScriptLevel(2, !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)); + PropagatePresentationDataFor(overscriptFrame, ~NS_MATHML_DISPLAYSTYLE | compress, NS_MATHML_DISPLAYSTYLE | compress); @@ -254,9 +249,8 @@ nsMathMLmunderoverFrame::TransmitAutomaticData() The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a say it should be compressed */ - increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags) - ? 0 : 1; - PropagatePresentationDataFor(underscriptFrame, increment, + SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)); + PropagatePresentationDataFor(underscriptFrame, ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); diff --git a/layout/mathml/base/src/nsMathMLmunderoverFrame.h b/layout/mathml/base/src/nsMathMLmunderoverFrame.h index 06de1b5e517..4456e08fe03 100644 --- a/layout/mathml/base/src/nsMathMLmunderoverFrame.h +++ b/layout/mathml/base/src/nsMathMLmunderoverFrame.h @@ -64,14 +64,12 @@ public: TransmitAutomaticData(); NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, + UpdatePresentationData(PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); NS_IMETHOD UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); diff --git a/layout/mathml/content/src/mathml.css b/layout/mathml/content/src/mathml.css index 1d585d7ca54..385d7c6a3c9 100644 --- a/layout/mathml/content/src/mathml.css +++ b/layout/mathml/content/src/mathml.css @@ -84,40 +84,6 @@ math[display="inline"] { [-moz-math-font-style="invariant"] { font-style: normal; /* a non-stylable character preserves its own style */ } -/* change of size induced by changing the scriptlevel */ -[-moz-math-font-size="+1"] { - font-size: 71%; -} -[-moz-math-font-size="+2"] { - font-size: 50%; -} -[-moz-math-font-size="+3"] { - font-size: 36%; -} -[-moz-math-font-size="+4"] { - font-size: 25%; -} -[-moz-math-font-size="+5"] { - font-size: 18%; -} -[-moz-math-font-size="scriptminsize"] { - font-size: 8pt; -} -[-moz-math-font-size="-1"] { - font-size: 141%; -} -[-moz-math-font-size="-2"] { - font-size: 200%; -} -[-moz-math-font-size="-3"] { - font-size: 283%; -} -[-moz-math-font-size="-4"] { - font-size: 400%; -} -[-moz-math-font-size="-5"] { - font-size: 566%; -} /**************************************************************************/ /* attributes common to all tags */ @@ -139,34 +105,6 @@ math[display="inline"] { [fontweight="bold"] { font-weight: bold; } -/* fontsize */ -[fontsize="xx-small"] { - font-size: xx-small; -} -[fontsize="x-small"] { - font-size: x-small; -} -[fontsize="small"] { - font-size: small; -} -[fontsize="smaller"] { - font-size: smaller; -} -[fontsize="medium"] { - font-size: medium; -} -[fontsize="large"] { - font-size: large; -} -[fontsize="larger"] { - font-size: larger; -} -[fontsize="x-large"] { - font-size: x-large; -} -[fontsize="xx-large"] { - font-size: xx-large; -} /* attributes from MathML 2.0 */ @@ -176,14 +114,6 @@ math[display="inline"] { mathbackground (replaces 'background'): #rgb | #rrggbb | html-color-name */ -/* mathsize (replaces 'fontsize'): - small, big, number v-unit (a numeric value is handled in the back-end) */ -[mathsize="small"] { - font-size: small; -} -[mathsize="big"] { - font-size: large; -} /* mathvariant (replaces 'fontstyle' & 'fontweight' & 'fontslant'): normal | bold | italic | bold-italic | double-struck | bold-fraktur | script | bold-script | fraktur | sans-serif | bold-sans-serif | sans-serif-italic | @@ -481,3 +411,21 @@ semantics > :not(:first-child) { display: inline-block !important; position: static !important; } + +/*****************************************/ +/* Controlling scriptlevel */ +/*****************************************/ + +/* mfrac, munder, mover and munderover change the scriptlevels of their children using + -moz-math-increment-script-level because regular CSS rules are insufficient to + control when the scriptlevel should be incremented */ +:-moz-math-increment-script-level { -moz-script-level:+1; } + +/* all other cases can be described using regular CSS, so we do it this way because it's + more efficient and less code */ +mroot > :not(:first-child) { -moz-script-level:+2; } + +msub > :not(:first-child), +msup > :not(:first-child), +msubsup > :not(:first-child), +mmultiscripts > :not(:first-child) { -moz-script-level:+1; } diff --git a/layout/reftests/bugs/355548-1-ref.xml b/layout/reftests/bugs/355548-1-ref.xml new file mode 100644 index 00000000000..d0757977251 --- /dev/null +++ b/layout/reftests/bugs/355548-1-ref.xml @@ -0,0 +1,36 @@ + + +

+ Id + Id + Id + Id +

+ +

+ Id + Id +

+ +

+ Id + Id + Id +

+

+ Id + Id + Id +

+

+ Id + Id + Id +

+

+ Id + Id + Id +

+ + diff --git a/layout/reftests/bugs/355548-1.xml b/layout/reftests/bugs/355548-1.xml new file mode 100644 index 00000000000..95449c1a791 --- /dev/null +++ b/layout/reftests/bugs/355548-1.xml @@ -0,0 +1,36 @@ + + +

+ Id + Id + Id + Id +

+ +

+ Id + Id +

+ +

+ Id + Id + Id +

+

+ Id + Id + Id +

+

+ Id + Id + Id +

+

+ Id + Id + Id +

+ + diff --git a/layout/reftests/bugs/355548-2-ref.xml b/layout/reftests/bugs/355548-2-ref.xml new file mode 100644 index 00000000000..dce6d1457f7 --- /dev/null +++ b/layout/reftests/bugs/355548-2-ref.xml @@ -0,0 +1,25 @@ + + +

+ Id + Id + Id +

+ +

+ Id +

+ +

+ Id + Id + Id +

+

+ Id + Id + Id + Id +

+ + diff --git a/layout/reftests/bugs/355548-2.xml b/layout/reftests/bugs/355548-2.xml new file mode 100644 index 00000000000..6bc567a40c0 --- /dev/null +++ b/layout/reftests/bugs/355548-2.xml @@ -0,0 +1,38 @@ + + + +

+ Id + + Id + + Id +

+ +

+ + Id +

+ +

+ + Id + + Id + Id +

+ +

+ + Id + + Id + + Id + + Id +

+ + + diff --git a/layout/reftests/bugs/355548-3-ref.xml b/layout/reftests/bugs/355548-3-ref.xml new file mode 100644 index 00000000000..d4f2e9fb085 --- /dev/null +++ b/layout/reftests/bugs/355548-3-ref.xml @@ -0,0 +1,67 @@ + + +

+ Id +

+ +

+ Id + Id + Id + Id +

+ +

+ Id + Id + Id + Id + Id + Id +

+ +

+ Id + Id +

+ +

+ Id + Id + Id + Id +

+ +

+ Id + Id +

+ +

+ Id + Id + Id + Id +

+ +

+ Id + Id + Id + Id + Id + Id +

+ +

+ Id + Id + Id + Id + Id + Id + Id +

+ + + diff --git a/layout/reftests/bugs/355548-3.xml b/layout/reftests/bugs/355548-3.xml new file mode 100644 index 00000000000..b1a6958b48c --- /dev/null +++ b/layout/reftests/bugs/355548-3.xml @@ -0,0 +1,78 @@ + + + +

+ + Id +

+ +

+ Id + Id + + Id + + Id +

+ +

+ Id + Id + Id + + Id + Id + Id +

+ +

+ Id + Id +

+ +

+ Id + Id + + Id + + Id +

+ +

+ Id + Id +

+ +

+ Id + Id + + Id + + Id +

+ +

+ + Id + Id + Id + Id + Id + Id +

+ +

+ + Id + Id + Id + Id + Id + Id + Id +

+ + + diff --git a/layout/reftests/bugs/355548-4-ref.xml b/layout/reftests/bugs/355548-4-ref.xml new file mode 100644 index 00000000000..4424c25d3d8 --- /dev/null +++ b/layout/reftests/bugs/355548-4-ref.xml @@ -0,0 +1,11 @@ + + + + + +

Hello

+Id + + diff --git a/layout/reftests/bugs/355548-4.xml b/layout/reftests/bugs/355548-4.xml new file mode 100644 index 00000000000..5a73aff01cf --- /dev/null +++ b/layout/reftests/bugs/355548-4.xml @@ -0,0 +1,41 @@ + + + + + + +

Hello

+ + diff --git a/layout/reftests/bugs/355548-5-ref.xml b/layout/reftests/bugs/355548-5-ref.xml new file mode 100644 index 00000000000..fb71442ab4d --- /dev/null +++ b/layout/reftests/bugs/355548-5-ref.xml @@ -0,0 +1,7 @@ + + +

+ Id +

+ + diff --git a/layout/reftests/bugs/355548-5.xml b/layout/reftests/bugs/355548-5.xml new file mode 100644 index 00000000000..30dbbc88315 --- /dev/null +++ b/layout/reftests/bugs/355548-5.xml @@ -0,0 +1,7 @@ + + +

+ Id +

+ + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 7175ad58233..f4738c9b969 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -304,6 +304,11 @@ fails == 352980-1h.html 352980-1-ref.html == 352980-3d.html 352980-3-ref.html == 352980-3e.html 352980-3-ref.html == 352980-3f.html 352980-3-ref.html +== 355548-1.xml 355548-1-ref.xml +== 355548-2.xml 355548-2-ref.xml +== 355548-3.xml 355548-3-ref.xml +== 355548-4.xml 355548-4-ref.xml +== 355548-5.xml 355548-5-ref.xml == 359903-1.html 359903-1-ref.html == 359869-1.html 359869-1-ref.html == 359903-2.html 359903-2-ref.html diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 0eb01ce79d1..7426e6f6560 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -4618,6 +4618,10 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode, case eCSSProperty_border_left_width_rtl_source: case eCSSProperty_border_right_width_ltr_source: case eCSSProperty_border_right_width_rtl_source: +#ifdef MOZ_MATHML + case eCSSProperty_script_size_multiplier: + case eCSSProperty_script_min_size: +#endif NS_ERROR("not currently parsed here"); return PR_FALSE; @@ -4933,6 +4937,16 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode, return ParseVariant(aErrorCode, aValue, VARIANT_HK, nsCSSProps::kPositionKTable); case eCSSProperty_richness: return ParseVariant(aErrorCode, aValue, VARIANT_HN, nsnull); +#ifdef MOZ_MATHML + // script-level can take Integer or Number values, but only Integer ("relative") + // values can be specified in a style sheet. Also we only allow this property + // when unsafe rules are enabled, because otherwise it could interfere + // with rulenode optimizations if used in a non-MathML-enabled document. + case eCSSProperty_script_level: + if (!mUnsafeRulesEnabled) + return PR_FALSE; + return ParseVariant(aErrorCode, aValue, VARIANT_HI, nsnull); +#endif case eCSSProperty_speak: return ParseVariant(aErrorCode, aValue, VARIANT_HMK | VARIANT_NONE, nsCSSProps::kSpeakKTable); diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index fa7ffe55e97..6967f9d889c 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -517,6 +517,14 @@ CSS_PROP_XUL(-moz-box-orient, box_orient, MozBoxOrient, XUL, mBoxOrient, eCSSTyp CSS_PROP_XUL(-moz-box-pack, box_pack, MozBoxPack, XUL, mBoxPack, eCSSType_Value, kBoxPackKTable) // XXX bug 3935 CSS_PROP_XUL(-moz-box-ordinal-group, box_ordinal_group, MozBoxOrdinalGroup, XUL, mBoxOrdinal, eCSSType_Value, nsnull) +#ifdef MOZ_MATHML +#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL +CSS_PROP_FONT(-moz-script-level, script_level, ScriptLevel, Font, mScriptLevel, eCSSType_Value, nsnull) +CSS_PROP_FONT(-moz-script-size-multiplier, script_size_multiplier, ScriptSizeMultiplier, Font, mScriptSizeMultiplier, eCSSType_Value, nsnull) +CSS_PROP_FONT(-moz-script-min-size, script_min_size, ScriptMinSize, Font, mScriptMinSize, eCSSType_Value, nsnull) +#endif +#endif + #ifdef MOZ_SVG // XXX treat SVG's CSS Properties as internal for now. // Do we want to create an nsIDOMSVGCSS2Properties interface? diff --git a/layout/style/nsCSSPseudoClassList.h b/layout/style/nsCSSPseudoClassList.h index d29a673a037..a940ec4529a 100644 --- a/layout/style/nsCSSPseudoClassList.h +++ b/layout/style/nsCSSPseudoClassList.h @@ -94,6 +94,10 @@ CSS_PSEUDO_CLASS(mozIsHTML, ":-moz-is-html") // Matches anything when the specified look-and-feel metric is set CSS_PSEUDO_CLASS(mozSystemMetric, ":-moz-system-metric") +#ifdef MOZ_MATHML +CSS_PSEUDO_CLASS(mozMathIncrementScriptLevel, ":-moz-math-increment-script-level") +#endif + // CSS 3 UI // http://www.w3.org/TR/2004/CR-css3-ui-20040511/#pseudo-classes CSS_PSEUDO_CLASS(required, ":required") diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 318ebb97415..9aa02421810 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -1335,6 +1335,11 @@ static PRBool SelectorMatches(RuleProcessorData &data, result = data.mIsHTMLContent && data.mContent->GetNameSpaceID() == kNameSpaceID_None; } +#ifdef MOZ_MATHML + else if (nsCSSPseudoClasses::mozMathIncrementScriptLevel == pseudoClass->mAtom) { + stateToCheck = NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL; + } +#endif else { NS_ERROR("CSS parser parsed a pseudo-class that we do not handle"); result = PR_FALSE; // unknown pseudo class @@ -1918,6 +1923,9 @@ PRBool IsStateSelector(nsCSSSelector& aSelector) (pseudoClass->mAtom == nsCSSPseudoClasses::outOfRange) || (pseudoClass->mAtom == nsCSSPseudoClasses::mozReadOnly) || (pseudoClass->mAtom == nsCSSPseudoClasses::mozReadWrite) || +#ifdef MOZ_MATHML + (pseudoClass->mAtom == nsCSSPseudoClasses::mozMathIncrementScriptLevel) || +#endif (pseudoClass->mAtom == nsCSSPseudoClasses::defaultPseudo)) { return PR_TRUE; } diff --git a/layout/style/nsCSSStruct.h b/layout/style/nsCSSStruct.h index 26fccbbad19..39f16a7842b 100644 --- a/layout/style/nsCSSStruct.h +++ b/layout/style/nsCSSStruct.h @@ -210,6 +210,12 @@ struct nsCSSFont : public nsCSSStruct { nsCSSValue mSizeAdjust; // NEW nsCSSValue mStretch; // NEW +#ifdef MOZ_MATHML + nsCSSValue mScriptLevel; // Integer values mean "relative", Number values mean "absolute" + nsCSSValue mScriptSizeMultiplier; + nsCSSValue mScriptMinSize; +#endif + private: nsCSSFont(const nsCSSFont& aOther); // NOT IMPLEMENTED }; diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 75de635074e..2f57d3341c3 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -185,7 +185,7 @@ static void EnsureBlockDisplay(PRUint8& display) } // XXX This should really be done in the CSS parser. -nsString& Unquote(nsString& aString) +static nsString& Unquote(nsString& aString) { PRUnichar start = aString.First(); PRUnichar end = aString.Last(); @@ -200,13 +200,17 @@ nsString& Unquote(nsString& aString) return aString; } -nscoord CalcLength(const nsCSSValue& aValue, - const nsFont* aFont, - nsStyleContext* aStyleContext, - nsPresContext* aPresContext, - PRBool& aInherited) +static nscoord CalcLengthWith(const nsCSSValue& aValue, + nscoord aFontSize, + const nsStyleFont* aStyleFont, + nsStyleContext* aStyleContext, + nsPresContext* aPresContext, + PRBool& aInherited) { NS_ASSERTION(aValue.IsLengthUnit(), "not a length unit"); + NS_ASSERTION(aStyleFont || aStyleContext, "Must have style data"); + NS_ASSERTION(aPresContext, "Must have prescontext"); + if (aValue.IsFixedLengthUnit()) { return aPresContext->TwipsToAppUnits(aValue.GetLengthTwips()); } @@ -216,31 +220,35 @@ nscoord CalcLength(const nsCSSValue& aValue, } // Common code for all units other than pixels: aInherited = PR_TRUE; - const nsFont* font; - if (aStyleContext) { - font = &aStyleContext->GetStyleFont()->mFont; - } else { - font = aFont; + if (!aStyleFont) { + aStyleFont = aStyleContext->GetStyleFont(); + } + if (aFontSize == -1) { + // XXX Should this be aStyleFont->mSize instead to avoid taking minfontsize + // prefs into account? + aFontSize = aStyleFont->mFont.size; } switch (unit) { case eCSSUnit_EM: case eCSSUnit_Char: { - return NSToCoordRound(aValue.GetFloatValue() * (float)font->size); + return NSToCoordRound(aValue.GetFloatValue() * float(aFontSize)); // XXX scale against font metrics height instead? } case eCSSUnit_EN: { - return NSToCoordRound((aValue.GetFloatValue() * (float)font->size) / 2.0f); + return NSToCoordRound((aValue.GetFloatValue() * float(aFontSize)) / 2.0f); } case eCSSUnit_XHeight: { - nsCOMPtr fm = aPresContext->GetMetricsFor(*font); + nsFont font = aStyleFont->mFont; + font.size = aFontSize; + nsCOMPtr fm = aPresContext->GetMetricsFor(font); nscoord xHeight; fm->GetXHeight(xHeight); - return NSToCoordRound(aValue.GetFloatValue() * (float)xHeight); + return NSToCoordRound(aValue.GetFloatValue() * float(xHeight)); } case eCSSUnit_CapHeight: { NS_NOTYETIMPLEMENTED("cap height unit"); - nscoord capHeight = ((font->size / 3) * 2); // XXX HACK! - return NSToCoordRound(aValue.GetFloatValue() * (float)capHeight); + nscoord capHeight = ((aFontSize / 3) * 2); // XXX HACK! + return NSToCoordRound(aValue.GetFloatValue() * float(capHeight)); } default: NS_NOTREACHED("unexpected unit"); @@ -249,6 +257,16 @@ nscoord CalcLength(const nsCSSValue& aValue, return 0; } +static nscoord CalcLength(const nsCSSValue& aValue, + nsStyleContext* aStyleContext, + nsPresContext* aPresContext, + PRBool& aInherited) +{ + NS_ASSERTION(aStyleContext, "Must have style data"); + + return CalcLengthWith(aValue, -1, nsnull, aStyleContext, aPresContext, aInherited); +} + #define SETCOORD_NORMAL 0x01 // N #define SETCOORD_AUTO 0x02 // A #define SETCOORD_INHERIT 0x04 // H @@ -294,8 +312,8 @@ static PRBool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord, } else if (((aMask & SETCOORD_LENGTH) != 0) && aValue.IsLengthUnit()) { - aCoord.SetCoordValue(CalcLength(aValue, nsnull, aStyleContext, aPresContext, aInherited)); - } + aCoord.SetCoordValue(CalcLength(aValue, aStyleContext, aPresContext, aInherited)); + } else if (((aMask & SETCOORD_PERCENT) != 0) && (aValue.GetUnit() == eCSSUnit_Percent)) { aCoord.SetPercentValue(aValue.GetPercentValue()); @@ -676,6 +694,9 @@ CheckFontCallback(const nsRuleDataStruct& aData, (size.GetUnit() == eCSSUnit_Enumerated && (size.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER || size.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER)) || +#ifdef MOZ_MATHML + fontData.mScriptLevel.GetUnit() == eCSSUnit_Integer || +#endif (weight.GetUnit() == eCSSUnit_Enumerated && (weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER || weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER))) { @@ -949,6 +970,16 @@ QuotesAtOffset(const nsRuleDataStruct& aRuleDataStruct, size_t aOffset) (reinterpret_cast(&aRuleDataStruct) + aOffset); } +#if defined(MOZ_MATHML) && defined(DEBUG) +static PRBool +AreAllMathMLPropertiesUndefined(const nsCSSFont& aRuleData) +{ + return aRuleData.mScriptLevel.GetUnit() == eCSSUnit_Null && + aRuleData.mScriptSizeMultiplier.GetUnit() == eCSSUnit_Null && + aRuleData.mScriptMinSize.GetUnit() == eCSSUnit_Null; +} +#endif + inline nsRuleNode::RuleDetail nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, const nsRuleDataStruct& aRuleDataStruct) @@ -1038,6 +1069,13 @@ nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, aSID, total, specified, inherited); #endif +#ifdef MOZ_MATHML + NS_ASSERTION(aSID != eStyleStruct_Font || + mPresContext->Document()->GetMathMLEnabled() || + AreAllMathMLPropertiesUndefined(static_cast(aRuleDataStruct)), + "MathML style property was defined even though MathML is disabled"); +#endif + /* * Return the most specific information we can: prefer None or Full * over Partial, and Reset or Inherited over Mixed, since we can @@ -1046,7 +1084,18 @@ nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, nsRuleNode::RuleDetail result; if (inherited == total) result = eRuleFullInherited; - else if (specified == total) { + else if (specified == total +#ifdef MOZ_MATHML + // MathML defines 3 properties in Font that will never be set when + // MathML is not in use. Therefore if all but three + // properties have been set, and MathML is not enabled, we can treat + // this as fully specified. Code in nsMathMLElementFactory will + // rebuild the rule tree and style data when MathML is first enabled + // (see nsMathMLElement::BindToTree). + || (aSID == eStyleStruct_Font && specified + 3 == total && + !mPresContext->Document()->GetMathMLEnabled()) +#endif + ) { if (inherited == 0) result = eRuleFullReset; else @@ -1885,13 +1934,201 @@ nsRuleNode::AdjustLogicalBoxProp(nsStyleContext* aContext, } \ \ return data_; - + +#ifdef MOZ_MATHML +// This function figures out how much scaling should be suppressed to +// satisfy scriptminsize. This is our attempt to implement +// http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2 +// This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier +// have been set in aFont. +// +// Here are the invariants we enforce: +// 1) A decrease in size must not reduce the size below minscriptsize. +// 2) An increase in size must not increase the size above the size we would +// have if minscriptsize had not been applied anywhere. +// 3) The scriptlevel-induced size change must between 1.0 and the parent's +// scriptsizemultiplier^(new script level - old script level), as close to the +// latter as possible subject to constraints 1 and 2. +static nscoord +ComputeScriptLevelSize(const nsStyleFont* aFont, const nsStyleFont* aParentFont, + nsPresContext* aPresContext, nscoord* aUnconstrainedSize) +{ + PRInt32 scriptLevelChange = + aFont->mScriptLevel - aParentFont->mScriptLevel; + if (scriptLevelChange == 0) { + *aUnconstrainedSize = aParentFont->mScriptUnconstrainedSize; + // Constraint #3 says that we cannot change size, and #1 and #2 are always + // satisfied with no change. It's important this be fast because it covers + // all non-MathML content. + return aParentFont->mSize; + } + + // Compute actual value of minScriptSize + nscoord minScriptSize = + nsStyleFont::ZoomText(aPresContext, aParentFont->mScriptMinSize); + + double scriptLevelScale = + pow(aParentFont->mScriptSizeMultiplier, scriptLevelChange); + // Compute the size we would have had if minscriptsize had never been applied + *aUnconstrainedSize = + NSToCoordRound(aParentFont->mScriptUnconstrainedSize*scriptLevelScale); + // Compute the size we could get via scriptlevel change + nscoord scriptLevelSize = + NSToCoordRound(aParentFont->mSize*scriptLevelScale); + if (scriptLevelScale <= 1.0) { + if (aParentFont->mSize <= minScriptSize) { + // We can't decrease the font size at all, so just stick to no change + // (authors are allowed to explicitly set the font size smaller than + // minscriptsize) + return aParentFont->mSize; + } + // We can decrease, so apply constraint #1 + return PR_MAX(minScriptSize, scriptLevelSize); + } else { + // scriptminsize can only make sizes larger than the unconstrained size + NS_ASSERTION(*aUnconstrainedSize <= scriptLevelSize, "How can this ever happen?"); + // Apply constraint #2 + return PR_MIN(scriptLevelSize, PR_MAX(*aUnconstrainedSize, minScriptSize)); + } +} +#endif + +/* static */ void +nsRuleNode::SetFontSize(nsPresContext* aPresContext, + const nsRuleDataFont& aFontData, + const nsStyleFont* aFont, + const nsStyleFont* aParentFont, + nscoord* aSize, + const nsFont& aSystemFont, + nscoord aParentSize, + nscoord aScriptLevelAdjustedParentSize, + PRBool aUsedStartStruct, + PRBool& aInherited) +{ + PRBool zoom = PR_FALSE; + PRInt32 baseSize = (PRInt32) aPresContext-> + GetDefaultFont(aFont->mFlags & NS_STYLE_FONT_FACE_MASK)->size; + if (eCSSUnit_Enumerated == aFontData.mSize.GetUnit()) { + PRInt32 value = aFontData.mSize.GetIntValue(); + PRInt32 scaler = aPresContext->FontScaler(); + float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); + + zoom = PR_TRUE; + if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) && + (value <= NS_STYLE_FONT_SIZE_XXLARGE)) { + *aSize = nsStyleUtil::CalcFontPointSize(value, baseSize, + scaleFactor, aPresContext, eFontSize_CSS); + } + else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) { + // is not specified in CSS, so we don't use eFontSize_CSS. + *aSize = nsStyleUtil::CalcFontPointSize(value, baseSize, + scaleFactor, aPresContext); + } + else if (NS_STYLE_FONT_SIZE_LARGER == value || + NS_STYLE_FONT_SIZE_SMALLER == value) { + aInherited = PR_TRUE; + + // Un-zoom so we use the tables correctly. We'll then rezoom due + // to the |zoom = PR_TRUE| above. + // Note that relative units here use the parent's size unadjusted + // for scriptlevel changes. A scriptlevel change between us and the parent + // is simply ignored. + nscoord parentSize = + nsStyleFont::UnZoomText(aPresContext, aParentSize); + + if (NS_STYLE_FONT_SIZE_LARGER == value) { + *aSize = nsStyleUtil::FindNextLargerFontSize(parentSize, + baseSize, scaleFactor, aPresContext, eFontSize_CSS); + NS_ASSERTION(*aSize > parentSize, + "FindNextLargerFontSize failed"); + } + else { + *aSize = nsStyleUtil::FindNextSmallerFontSize(parentSize, + baseSize, scaleFactor, aPresContext, eFontSize_CSS); + NS_ASSERTION(*aSize < parentSize || + parentSize <= nsPresContext::CSSPixelsToAppUnits(1), + "FindNextSmallerFontSize failed"); + } + } else { + NS_NOTREACHED("unexpected value"); + } + } + else if (aFontData.mSize.IsLengthUnit()) { + // Note that font-based length units use the parent's size unadjusted + // for scriptlevel changes. A scriptlevel change between us and the parent + // is simply ignored. + *aSize = CalcLengthWith(aFontData.mSize, aParentSize, aParentFont, nsnull, + aPresContext, aInherited); + zoom = aFontData.mSize.IsFixedLengthUnit() || + aFontData.mSize.GetUnit() == eCSSUnit_Pixel; + } + else if (eCSSUnit_Percent == aFontData.mSize.GetUnit()) { + aInherited = PR_TRUE; + // Note that % units use the parent's size unadjusted for scriptlevel + // changes. A scriptlevel change between us and the parent is simply + // ignored. + *aSize = NSToCoordRound(aParentSize * + aFontData.mSize.GetPercentValue()); + zoom = PR_FALSE; + } + else if (eCSSUnit_System_Font == aFontData.mSize.GetUnit()) { + // this becomes our cascading size + *aSize = aSystemFont.size; + zoom = PR_TRUE; + } + else if (eCSSUnit_Inherit == aFontData.mSize.GetUnit()) { + aInherited = PR_TRUE; + // We apply scriptlevel change for this case, because the default is + // to inherit and we don't want explicit "inherit" to differ from the + // default. + *aSize = aScriptLevelAdjustedParentSize; + zoom = PR_FALSE; + } + else if (eCSSUnit_Initial == aFontData.mSize.GetUnit()) { + // The initial value is 'medium', which has magical sizing based on + // the generic font family, so do that here too. + *aSize = baseSize; + zoom = PR_TRUE; + } else { + NS_ASSERTION(eCSSUnit_Null == aFontData.mSize.GetUnit(), + "What kind of font-size value is this?"); +#ifdef MOZ_MATHML + // if aUsedStartStruct is true, then every single property in the + // font struct is being set all at once. This means scriptlevel is not + // going to have any influence on the font size; there is no need to + // do anything here. + if (!aUsedStartStruct && aParentSize != aScriptLevelAdjustedParentSize) { + // There was no rule affecting the size but the size has been + // affected by the parent's size via scriptlevel change. So treat + // this as inherited. + aInherited = PR_TRUE; + *aSize = aScriptLevelAdjustedParentSize; + } +#endif + } + + // We want to zoom the cascaded size so that em-based measurements, + // line-heights, etc., work. + if (zoom) { + *aSize = nsStyleFont::ZoomText(aPresContext, *aSize); + } +} + +static PRInt8 ClampTo8Bit(PRInt32 aValue) { + if (aValue < -128) + return -128; + if (aValue > 127) + return 127; + return PRInt8(aValue); +} + /* static */ void nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext, nscoord aMinFontSize, PRUint8 aGenericFontID, const nsRuleDataFont& aFontData, const nsStyleFont* aParentFont, - nsStyleFont* aFont, PRBool& aInherited) + nsStyleFont* aFont, PRBool aUsedStartStruct, + PRBool& aInherited) { const nsFont* defaultVariableFont = aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID); @@ -2082,85 +2319,79 @@ nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext, aFont->mFont.weight = defaultVariableFont->weight; } +#ifdef MOZ_MATHML + // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so + // they're available for font-size computation. + + // -moz-script-min-size: length + if (aFontData.mScriptMinSize.IsLengthUnit()) { + aFont->mScriptMinSize = + CalcLength(aFontData.mScriptMinSize, aContext, aPresContext, aInherited); + } + + // -moz-script-size-multiplier: factor, inherit + if (eCSSUnit_Number == aFontData.mScriptSizeMultiplier.GetUnit()) { + aFont->mScriptSizeMultiplier = aFontData.mScriptSizeMultiplier.GetFloatValue(); + NS_ASSERTION(aFont->mScriptSizeMultiplier >= 0.0f, "Cannot have negative script size multiplier"); + } + else if (eCSSUnit_Inherit == aFontData.mScriptSizeMultiplier.GetUnit()) { + aInherited = PR_TRUE; + aFont->mScriptSizeMultiplier = aParentFont->mScriptSizeMultiplier; + } + else if (eCSSUnit_Initial == aFontData.mScriptSizeMultiplier.GetUnit()) { + aFont->mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER; + } + + // -moz-script-level: integer, number, inherit + if (eCSSUnit_Integer == aFontData.mScriptLevel.GetUnit()) { + // "relative" + aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + aFontData.mScriptLevel.GetIntValue()); + } + else if (eCSSUnit_Number == aFontData.mScriptLevel.GetUnit()) { + // "absolute" + aFont->mScriptLevel = ClampTo8Bit(PRInt32(aFontData.mScriptLevel.GetFloatValue())); + } + else if (eCSSUnit_Inherit == aFontData.mScriptSizeMultiplier.GetUnit()) { + aInherited = PR_TRUE; + aFont->mScriptLevel = aParentFont->mScriptLevel; + } + else if (eCSSUnit_Initial == aFontData.mScriptSizeMultiplier.GetUnit()) { + aFont->mScriptLevel = 0; + } +#endif + // font-size: enum, length, percent, inherit - PRBool zoom = PR_FALSE; - PRInt32 baseSize = (PRInt32) aPresContext-> - GetDefaultFont(aFont->mFlags & NS_STYLE_FONT_FACE_MASK)->size; - if (eCSSUnit_Enumerated == aFontData.mSize.GetUnit()) { - PRInt32 value = aFontData.mSize.GetIntValue(); - PRInt32 scaler = aPresContext->FontScaler(); - float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); - - zoom = PR_TRUE; - if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) && - (value <= NS_STYLE_FONT_SIZE_XXLARGE)) { - aFont->mSize = nsStyleUtil::CalcFontPointSize(value, baseSize, - scaleFactor, aPresContext, eFontSize_CSS); - } - else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) { - // is not specified in CSS, so we don't use eFontSize_CSS. - aFont->mSize = nsStyleUtil::CalcFontPointSize(value, baseSize, - scaleFactor, aPresContext); - } - else if (NS_STYLE_FONT_SIZE_LARGER == value || - NS_STYLE_FONT_SIZE_SMALLER == value) { - - aInherited = PR_TRUE; - - // Un-zoom so we use the tables correctly. We'll then rezoom due - // to the |zoom = PR_TRUE| above. - nscoord parentSize = - nsStyleFont::UnZoomText(aPresContext, aParentFont->mSize); - - if (NS_STYLE_FONT_SIZE_LARGER == value) { - aFont->mSize = nsStyleUtil::FindNextLargerFontSize(parentSize, - baseSize, scaleFactor, aPresContext, eFontSize_CSS); - NS_ASSERTION(aFont->mSize > parentSize, - "FindNextLargerFontSize failed"); - } - else { - aFont->mSize = nsStyleUtil::FindNextSmallerFontSize(parentSize, - baseSize, scaleFactor, aPresContext, eFontSize_CSS); - NS_ASSERTION(aFont->mSize < parentSize || - parentSize <= nsPresContext::CSSPixelsToAppUnits(1), - "FindNextSmallerFontSize failed"); - } - } else { - NS_NOTREACHED("unexpected value"); - } + nscoord scriptLevelAdjustedParentSize = aParentFont->mSize; +#ifdef MOZ_MATHML + nscoord scriptLevelAdjustedUnconstrainedParentSize; + scriptLevelAdjustedParentSize = + ComputeScriptLevelSize(aFont, aParentFont, aPresContext, + &scriptLevelAdjustedUnconstrainedParentSize); + NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize, + "If we have a start struct, we should have reset everything coming in here"); +#endif + SetFontSize(aPresContext, aFontData, aFont, aParentFont, &aFont->mSize, + systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize, + aUsedStartStruct, aInherited); +#ifdef MOZ_MATHML + if (aParentFont->mSize == aParentFont->mScriptUnconstrainedSize && + scriptLevelAdjustedParentSize == scriptLevelAdjustedUnconstrainedParentSize) { + // Fast path: we have not been affected by scriptminsize so we don't + // need to call SetFontSize again to compute the + // scriptminsize-unconstrained size. This is OK even if we have a + // start struct, because if we have a start struct then 'font-size' + // was specified and so scriptminsize has no effect. + aFont->mScriptUnconstrainedSize = aFont->mSize; + } else { + SetFontSize(aPresContext, aFontData, aFont, aParentFont, + &aFont->mScriptUnconstrainedSize, systemFont, + aParentFont->mScriptUnconstrainedSize, + scriptLevelAdjustedUnconstrainedParentSize, + aUsedStartStruct, aInherited); } - else if (aFontData.mSize.IsLengthUnit()) { - aFont->mSize = CalcLength(aFontData.mSize, &aParentFont->mFont, nsnull, aPresContext, aInherited); - zoom = aFontData.mSize.IsFixedLengthUnit() || - aFontData.mSize.GetUnit() == eCSSUnit_Pixel; - } - else if (eCSSUnit_Percent == aFontData.mSize.GetUnit()) { - aInherited = PR_TRUE; - aFont->mSize = NSToCoordRound(float(aParentFont->mSize) * - aFontData.mSize.GetPercentValue()); - zoom = PR_FALSE; - } - else if (eCSSUnit_System_Font == aFontData.mSize.GetUnit()) { - // this becomes our cascading size - aFont->mSize = systemFont.size; - zoom = PR_TRUE; - } - else if (eCSSUnit_Inherit == aFontData.mSize.GetUnit()) { - aInherited = PR_TRUE; - aFont->mSize = aParentFont->mSize; - zoom = PR_FALSE; - } - else if (eCSSUnit_Initial == aFontData.mSize.GetUnit()) { - // The initial value is 'medium', which has magical sizing based on - // the generic font family, so do that here too. - aFont->mSize = baseSize; - zoom = PR_TRUE; - } - - // We want to zoom the cascaded size so that em-based measurements, - // line-heights, etc., work. - if (zoom) - aFont->mSize = nsStyleFont::ZoomText(aPresContext, aFont->mSize); + NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize, + "scriptminsize should never be making things bigger"); +#endif // enforce the user' specified minimum font-size on the value that we expose aFont->mFont.size = PR_MAX(aFont->mSize, aMinFontSize); @@ -2213,18 +2444,12 @@ nsRuleNode::SetGenericFont(nsPresContext* aPresContext, // we will start with the default generic font from the presentation // context. Otherwise we start with the higher context. const nsFont* defaultFont = aPresContext->GetDefaultFont(aGenericFontID); - nsStyleFont parentFont(*defaultFont); - parentFont.mSize = parentFont.mFont.size - = nsStyleFont::ZoomText(aPresContext, parentFont.mSize); + nsStyleFont parentFont(*defaultFont, aPresContext); if (higherContext) { const nsStyleFont* tmpFont = higherContext->GetStyleFont(); - parentFont.mFlags = tmpFont->mFlags; - parentFont.mFont = tmpFont->mFont; - parentFont.mSize = tmpFont->mSize; + parentFont = *tmpFont; } - aFont->mFlags = parentFont.mFlags; - aFont->mFont = parentFont.mFont; - aFont->mSize = parentFont.mSize; + *aFont = parentFont; PRBool dummy; PRUint32 fontBit = nsCachedStyleData::GetBitForSID(eStyleStruct_Font); @@ -2261,16 +2486,15 @@ nsRuleNode::SetGenericFont(nsPresContext* aPresContext, fontData.mFamily.Reset(); nsRuleNode::SetFont(aPresContext, context, aMinFontSize, - aGenericFontID, fontData, &parentFont, aFont, dummy); + aGenericFontID, fontData, &parentFont, aFont, + PR_FALSE, dummy); // XXX Not sure if we need to do this here // If we have a post-resolve callback, handle that now. if (ruleData.mPostResolveCallback) (ruleData.mPostResolveCallback)((nsStyleStruct*)aFont, &ruleData); - parentFont.mFlags = aFont->mFlags; - parentFont.mFont = aFont->mFont; - parentFont.mSize = aFont->mSize; + parentFont = *aFont; } } @@ -2308,7 +2532,7 @@ nsRuleNode::ComputeFontData(nsStyleStruct* aStartStruct, // using the 'font' shorthand). // See if there is a minimum font-size constraint to honor - nscoord minimumFontSize = + nscoord minimumFontSize = mPresContext->GetCachedIntPref(kPresContext_MinimumFontSize); if (minimumFontSize < 0) @@ -2366,7 +2590,8 @@ nsRuleNode::ComputeFontData(nsStyleStruct* aStartStruct, if (generic == kGenericFont_NONE) { // continue the normal processing nsRuleNode::SetFont(mPresContext, aContext, minimumFontSize, generic, - fontData, parentFont, font, inherited); + fontData, parentFont, font, + aStartStruct != nsnull, inherited); } else { // re-calculate the font as a generic font @@ -2943,7 +3168,7 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct, display->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO; } else if (displayData.mClip.mTop.IsLengthUnit()) { - display->mClip.y = CalcLength(displayData.mClip.mTop, nsnull, aContext, mPresContext, inherited); + display->mClip.y = CalcLength(displayData.mClip.mTop, aContext, mPresContext, inherited); fullAuto = PR_FALSE; } if (eCSSUnit_Auto == displayData.mClip.mBottom.GetUnit()) { @@ -2954,7 +3179,7 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct, display->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO; } else if (displayData.mClip.mBottom.IsLengthUnit()) { - display->mClip.height = CalcLength(displayData.mClip.mBottom, nsnull, aContext, mPresContext, inherited) - + display->mClip.height = CalcLength(displayData.mClip.mBottom, aContext, mPresContext, inherited) - display->mClip.y; fullAuto = PR_FALSE; } @@ -2963,7 +3188,7 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct, display->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO; } else if (displayData.mClip.mLeft.IsLengthUnit()) { - display->mClip.x = CalcLength(displayData.mClip.mLeft, nsnull, aContext, mPresContext, inherited); + display->mClip.x = CalcLength(displayData.mClip.mLeft, aContext, mPresContext, inherited); fullAuto = PR_FALSE; } if (eCSSUnit_Auto == displayData.mClip.mRight.GetUnit()) { @@ -2974,7 +3199,7 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct, display->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO; } else if (displayData.mClip.mRight.IsLengthUnit()) { - display->mClip.width = CalcLength(displayData.mClip.mRight, nsnull, aContext, mPresContext, inherited) - + display->mClip.width = CalcLength(displayData.mClip.mRight, aContext, mPresContext, inherited) - display->mClip.x; fullAuto = PR_FALSE; } @@ -3277,7 +3502,7 @@ nsRuleNode::ComputeBackgroundData(nsStyleStruct* aStartStruct, bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_LENGTH; } else if (colorData.mBackPosition.mXValue.IsLengthUnit()) { - bg->mBackgroundXPosition.mCoord = CalcLength(colorData.mBackPosition.mXValue, nsnull, + bg->mBackgroundXPosition.mCoord = CalcLength(colorData.mBackPosition.mXValue, aContext, mPresContext, inherited); bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_LENGTH; bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_PERCENT; @@ -3316,7 +3541,7 @@ nsRuleNode::ComputeBackgroundData(nsStyleStruct* aStartStruct, bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_LENGTH; } else if (colorData.mBackPosition.mYValue.IsLengthUnit()) { - bg->mBackgroundYPosition.mCoord = CalcLength(colorData.mBackPosition.mYValue, nsnull, + bg->mBackgroundYPosition.mCoord = CalcLength(colorData.mBackPosition.mYValue, aContext, mPresContext, inherited); bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_LENGTH; bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_PERCENT; @@ -3779,23 +4004,23 @@ nsRuleNode::ComputeListData(nsStyleStruct* aStartStruct, if (eCSSUnit_Auto == listData.mImageRegion.mTop.GetUnit()) list->mImageRegion.y = 0; else if (listData.mImageRegion.mTop.IsLengthUnit()) - list->mImageRegion.y = CalcLength(listData.mImageRegion.mTop, nsnull, aContext, mPresContext, inherited); + list->mImageRegion.y = CalcLength(listData.mImageRegion.mTop, aContext, mPresContext, inherited); if (eCSSUnit_Auto == listData.mImageRegion.mBottom.GetUnit()) list->mImageRegion.height = 0; else if (listData.mImageRegion.mBottom.IsLengthUnit()) - list->mImageRegion.height = CalcLength(listData.mImageRegion.mBottom, nsnull, aContext, + list->mImageRegion.height = CalcLength(listData.mImageRegion.mBottom, aContext, mPresContext, inherited) - list->mImageRegion.y; if (eCSSUnit_Auto == listData.mImageRegion.mLeft.GetUnit()) list->mImageRegion.x = 0; else if (listData.mImageRegion.mLeft.IsLengthUnit()) - list->mImageRegion.x = CalcLength(listData.mImageRegion.mLeft, nsnull, aContext, mPresContext, inherited); + list->mImageRegion.x = CalcLength(listData.mImageRegion.mLeft, aContext, mPresContext, inherited); if (eCSSUnit_Auto == listData.mImageRegion.mRight.GetUnit()) list->mImageRegion.width = 0; else if (listData.mImageRegion.mRight.IsLengthUnit()) - list->mImageRegion.width = CalcLength(listData.mImageRegion.mRight, nsnull, aContext, mPresContext, inherited) - + list->mImageRegion.width = CalcLength(listData.mImageRegion.mRight, aContext, mPresContext, inherited) - list->mImageRegion.x; } diff --git a/layout/style/nsRuleNode.h b/layout/style/nsRuleNode.h index 377441df1d0..49ae15db9d8 100644 --- a/layout/style/nsRuleNode.h +++ b/layout/style/nsRuleNode.h @@ -600,13 +600,25 @@ protected: #endif // helpers for |ComputeFontData| that need access to |mNoneBits|: + static NS_HIDDEN_(void) SetFontSize(nsPresContext* aPresContext, + const nsRuleDataFont& aFontData, + const nsStyleFont* aFont, + const nsStyleFont* aParentFont, + nscoord* aSize, + const nsFont& aSystemFont, + nscoord aParentSize, + nscoord aScriptLevelAdjustedParentSize, + PRBool aUsedStartStruct, + PRBool& aInherited); + static NS_HIDDEN_(void) SetFont(nsPresContext* aPresContext, nsStyleContext* aContext, nscoord aMinFontSize, PRUint8 aGenericFontID, const nsRuleDataFont& aFontData, const nsStyleFont* aParentFont, - nsStyleFont* aFont, PRBool& aInherited); + nsStyleFont* aFont, + PRBool aStartStruct, PRBool& aInherited); static NS_HIDDEN_(void) SetGenericFont(nsPresContext* aPresContext, nsStyleContext* aContext, diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 83b7868e9e1..3bc4ddf4bbc 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -106,33 +106,45 @@ static PRBool EqualImages(imgIRequest *aImage1, imgIRequest* aImage2) // -------------------- // nsStyleFont // -nsStyleFont::nsStyleFont() - : mFlags(NS_STYLE_FONT_DEFAULT), - mFont(nsnull, NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL, - NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE, 0), - mSize(0) -{ } - -nsStyleFont::nsStyleFont(const nsFont& aFont) - : mFlags(NS_STYLE_FONT_DEFAULT), - mFont(aFont), - mSize(aFont.size) +nsStyleFont::nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext) + : mFont(aFont), + mFlags(NS_STYLE_FONT_DEFAULT) { + mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size); +#ifdef MOZ_MATHML + mScriptUnconstrainedSize = mSize; + mScriptMinSize = aPresContext->TwipsToAppUnits( + NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT)); + mScriptLevel = 0; + mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER; +#endif } nsStyleFont::nsStyleFont(const nsStyleFont& aSrc) - : mFlags(aSrc.mFlags), - mFont(aSrc.mFont), - mSize(aSrc.mSize) + : mFont(aSrc.mFont) + , mSize(aSrc.mSize) + , mFlags(aSrc.mFlags) +#ifdef MOZ_MATHML + , mScriptLevel(aSrc.mScriptLevel) + , mScriptUnconstrainedSize(aSrc.mScriptUnconstrainedSize) + , mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier) + , mScriptMinSize(aSrc.mScriptMinSize) +#endif { } - nsStyleFont::nsStyleFont(nsPresContext* aPresContext) - : mFlags(NS_STYLE_FONT_DEFAULT), - mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID))) + : mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID))), + mFlags(NS_STYLE_FONT_DEFAULT) { mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size); +#ifdef MOZ_MATHML + mScriptUnconstrainedSize = mSize; + mScriptMinSize = aPresContext->TwipsToAppUnits( + NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT)); + mScriptLevel = 0; + mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER; +#endif } void* diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 0c2b9c92c9c..34e5ab53f38 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -89,8 +89,7 @@ struct nsStyleStruct { // The lifetime of these objects is managed by the presshell's arena. struct nsStyleFont : public nsStyleStruct { - nsStyleFont(void); - nsStyleFont(const nsFont& aFont); + nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext); nsStyleFont(const nsStyleFont& aStyleFont); nsStyleFont(nsPresContext *aPresContext); ~nsStyleFont(void) {} @@ -103,16 +102,25 @@ struct nsStyleFont : public nsStyleStruct { static nscoord ZoomText(nsPresContext* aPresContext, nscoord aSize); static nscoord UnZoomText(nsPresContext* aPresContext, nscoord aSize); - + void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW; void Destroy(nsPresContext* aContext); - PRUint8 mFlags; // [inherited] See nsStyleConsts.h nsFont mFont; // [inherited] nscoord mSize; // [inherited] Our "computed size". Can be different from mFont.size // which is our "actual size" and is enforced to be >= the user's // preferred min-size. mFont.size should be used for display purposes // while mSize is the value to return in getComputedStyle() for example. + PRUint8 mFlags; // [inherited] See nsStyleConsts.h + +#ifdef MOZ_MATHML + // MathML scriptlevel support + PRInt8 mScriptLevel; // [inherited] + // The value mSize would have had if scriptminsize had never been applied + nscoord mScriptUnconstrainedSize; + nscoord mScriptMinSize; // [inherited] length + float mScriptSizeMultiplier; // [inherited] +#endif }; struct nsStyleColor : public nsStyleStruct { diff --git a/layout/style/test/ListCSSProperties.cpp b/layout/style/test/ListCSSProperties.cpp index 7bd44f9f44b..c2e40bf10bb 100644 --- a/layout/style/test/ListCSSProperties.cpp +++ b/layout/style/test/ListCSSProperties.cpp @@ -152,7 +152,10 @@ const char *gInaccessibleProperties[] = { "padding-left-ltr-source", "padding-left-rtl-source", "padding-right-ltr-source", - "padding-right-rtl-source" + "padding-right-rtl-source", + "-moz-script-level", // parsed by UA sheets only + "-moz-script-size-multiplier", + "-moz-script-min-size" }; inline int