Merge mozilla-central to tabcandy-central.

This commit is contained in:
Edward Lee 2010-08-12 03:55:08 -07:00
Родитель a5d931381b 0d197ee585
Коммит 038e101e68
79 изменённых файлов: 1399 добавлений и 504 удалений

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

@ -4,6 +4,8 @@ skin testpilot skin skin/all/
skin testpilot-os skin skin/linux/ os=Linux
skin testpilot-os skin skin/mac/ os=Darwin
skin testpilot-os skin skin/win/ os=WINNT
overlay chrome://browser/content/macBrowserOverlay.xul chrome://testpilot/content/tp-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion<4.0b1pre
overlay chrome://browser/content/macBrowserOverlay.xul chrome://testpilot/content/feedback-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion>=4.0b1pre
overlay chrome://browser/content/browser.xul chrome://testpilot/content/tp-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion<=3.6.*
overlay chrome://browser/content/browser.xul chrome://testpilot/content/feedback-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion>3.7a1pre
# For the menubar on Mac

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

@ -286,11 +286,9 @@ var TestPilotXulWindow = {
let openInTab = (task.taskType == TaskConstants.TYPE_LEGACY);
this.addDescription(textVbox, task.title, task.summary);
if (task.showMoreInfoLink) {
this.addXulLink(
textVbox, this._stringBundle.getString("testpilot.moreInfo"),
task.defaultUrl, openInTab);
}
this.addXulLink(
textVbox, this._stringBundle.getString("testpilot.moreInfo"),
task.defaultUrl, openInTab);
// Create the rightmost status area, depending on status:
let statusVbox = document.createElement("vbox");

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

@ -7,8 +7,10 @@
#feedback-menu-button .toolbarbutton-text {
display: -moz-box;
margin: 0;
color: -moz-dialogtext;
text-shadow: none;
}
#feedback-menu-button .toolbarbutton-icon {
display: none;
}

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

@ -166,10 +166,6 @@ var TestPilotTask = {
return url + this._id;
},
get showMoreInfoLink() {
return true;
},
// event handlers:
onExperimentStartup: function TestPilotTask_onExperimentStartup() {
@ -1021,10 +1017,6 @@ TestPilotWebSurvey.prototype = {
return this.infoPageUrl;
},
get showMoreInfoLink() {
return false;
},
onDetailPageOpened: function TPWS_onDetailPageOpened() {
/* Once you view the URL of the survey, we'll assume you've taken it.
* There's no reliable way to tell whether you have or not, so let's

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

@ -6777,14 +6777,12 @@ var gBookmarkAllTabsHandler = {
this._updateCommandState();
},
_updateCommandState: function BATH__updateCommandState(aTabClose) {
let numTabs = gBrowser.visibleTabs.length;
_updateCommandState: function BATH__updateCommandState() {
let remainingTabs = gBrowser.visibleTabs.filter(function(tab) {
return gBrowser._removingTabs.indexOf(tab) == -1;
});
// The TabClose event is fired before the tab is removed from the DOM
if (aTabClose)
numTabs--;
if (numTabs > 1)
if (remainingTabs.length > 1)
this._command.removeAttribute("disabled");
else
this._command.setAttribute("disabled", "true");
@ -6796,7 +6794,7 @@ var gBookmarkAllTabsHandler = {
// nsIDOMEventListener
handleEvent: function(aEvent) {
this._updateCommandState(aEvent.type == "TabClose");
this._updateCommandState();
}
};

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

@ -1025,7 +1025,8 @@
// == 1 false YES
// == 1 true NO
// > 1 false/true NO
var owner = (aURIs.length > 1) || aLoadInBackground ? null : this.selectedTab;
var multiple = aURIs.length > 1;
var owner = multiple || aLoadInBackground ? null : this.selectedTab;
var firstTabAdded = null;
if (aReplace) {
@ -1037,7 +1038,7 @@
}
}
else
firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: true});
firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: multiple});
var tabNum = this.tabContainer.selectedIndex;
for (let i = 1; i < aURIs.length; ++i) {
@ -1333,10 +1334,19 @@
<parameter name="aParams"/>
<body>
<![CDATA[
var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
if (aParams)
var animate = aParams.animate;
// Handle requests for synchronously removing an already
// asynchronously closing tab.
if (!animate &&
this._removingTabs.indexOf(aTab) > -1) {
this._endRemoveTab(aTab);
return;
}
var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
if (!this._beginRemoveTab(aTab, false, null, true))
return;
@ -1576,12 +1586,15 @@
}
let removing = this._removingTabs;
let ignoreRemoving = function(tab) removing.indexOf(tab) == -1;
function keepRemaining(tab) {
// A tab remains only if it's not being removed nor blurred
return removing.indexOf(tab) == -1 && tab != aTab;
}
// Switch to a visible tab unless there aren't any remaining
let remainingTabs = this.visibleTabs.filter(ignoreRemoving);
let remainingTabs = this.visibleTabs.filter(keepRemaining);
if (remainingTabs.length == 0)
remainingTabs = Array.filter(this.tabs, ignoreRemoving);
remainingTabs = Array.filter(this.tabs, keepRemaining);
// Try to find a remaining tab that comes after the given tab
var tab = aTab;
@ -1589,8 +1602,15 @@
tab = tab.nextSibling;
} while (tab && remainingTabs.indexOf(tab) == -1);
// If no tab was found, give the end of the remaining tabs
this.selectedTab = tab ? tab : remainingTabs.pop();
if (!tab) {
tab = aTab;
do {
tab = tab.previousSibling;
} while (tab && remainingTabs.indexOf(tab) == -1);
}
this.selectedTab = tab;
]]>
</body>
</method>
@ -1786,11 +1806,8 @@
if (aIndex < 0)
aIndex += tabs.length;
if (aIndex >= 0 && aIndex < tabs.length) {
let nextTab = tabs[aIndex];
if (nextTab != this.selectedTab)
this.selectedTab = nextTab;
}
if (aIndex >= 0 && aIndex < tabs.length)
this.selectedTab = tabs[aIndex];
if (aEvent) {
aEvent.preventDefault();
@ -2417,9 +2434,9 @@
</method>
<method name="_canScrollToElement">
<parameter name="tab"/>
<body>
return !tab.pinned;
</body>
<body><![CDATA[
return !tab.pinned && !tab.hidden;
]]></body>
</method>
</implementation>
@ -2431,7 +2448,7 @@
var tabs = document.getBindingParent(this);
tabs.removeAttribute("overflow");
tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser._endRemoveTab,
tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser.removeTab,
tabs.tabbrowser);
tabs._positionPinnedTabs();
@ -2596,9 +2613,8 @@
if (this.childNodes.length == 1 && this._closeWindowWithLastTab)
this.setAttribute("closebuttons", "noclose");
else {
let tab = this.childNodes.item(this.tabbrowser._numPinnedTabs);
if (tab && tab.hidden)
tab = this.tabbrowser.visibleTabs[0];
// Grab the last tab for size comparison
let tab = this.tabbrowser.visibleTabs.pop();
if (tab && tab.getBoundingClientRect().width > this.mTabClipWidth)
this.setAttribute("closebuttons", "alltabs");
else

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

@ -5,6 +5,11 @@ function test() {
gBrowser.removeTab(tab);
is(tab.parentNode, null, "tab removed immediately");
tab = gBrowser.addTab("about:blank", { skipAnimation: true });
gBrowser.removeTab(tab, { animate: true });
gBrowser.removeTab(tab);
is(tab.parentNode, null, "tab removed immediately when calling removeTab again after the animation was kicked off");
waitForExplicitFinish();
Services.prefs.setBoolPref("browser.tabs.animate", true);

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

@ -19,7 +19,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Edward Lee <edilee@mozilla.com>
* Edward Lee <edilee@mozilla.com>
*
* 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

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

@ -115,6 +115,7 @@ _BROWSER_TEST_FILES = \
browser_524745.js \
browser_528776.js \
browser_579879.js \
browser_586147.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

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

@ -0,0 +1,84 @@
/* ***** 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 sessionstore test code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Edward Lee <edilee@mozilla.com>
*
* 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 ***** */
function observeOneRestore(callback) {
let topic = "sessionstore-browser-state-restored";
Services.obs.addObserver(function() {
Services.obs.removeObserver(arguments.callee, topic, false);
callback();
}, topic, false);
};
function test() {
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
// There should be one tab when we start the test
let [origTab] = gBrowser.visibleTabs;
let hiddenTab = gBrowser.addTab();
is(gBrowser.visibleTabs.length, 2, "should have 2 tabs before hiding");
gBrowser.showOnlyTheseTabs([origTab]);
is(gBrowser.visibleTabs.length, 1, "only 1 after hiding");
ok(hiddenTab.hidden, "sanity check that it's hidden");
let extraTab = gBrowser.addTab();
let state = ss.getBrowserState();
let stateObj = JSON.parse(state);
let tabs = stateObj.windows[0].tabs;
is(tabs.length, 3, "just checking that browser state is correct");
ok(!tabs[0].hidden, "first tab is visible");
ok(tabs[1].hidden, "second is hidden");
ok(!tabs[2].hidden, "third is visible");
// Make the third tab hidden and then restore the modified state object
tabs[2].hidden = true;
observeOneRestore(function() {
let testWindow = Services.wm.getEnumerator("navigator:browser").getNext();
is(testWindow.gBrowser.visibleTabs.length, 1, "only restored 1 visible tab");
let tabs = testWindow.gBrowser.tabs;
ok(!tabs[0].hidden, "first is still visible");
ok(tabs[1].hidden, "second tab is still hidden");
ok(tabs[2].hidden, "third tab is now hidden");
// Restore the original state and clean up now that we're done
gBrowser.removeTab(hiddenTab);
gBrowser.removeTab(extraTab);
finish();
});
ss.setBrowserState(JSON.stringify(stateObj));
}

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

@ -11,9 +11,9 @@
@DLL_PREFIX@zlib@DLL_SUFFIX@
LICENSE
browserconfig.properties
chrome.manifest
chrome/US.jar
chrome/app-chrome.manifest
chrome/browser.manifest
chrome/chrome.rdf
chrome/chromelist.txt
chrome/classic.jar
@ -21,14 +21,18 @@ chrome/classic.manifest
chrome/comm.jar
chrome/comm.manifest
chrome/en-win.jar
chrome/en-US.manifest
chrome/help.jar
chrome/installed-chrome.txt
chrome/m3ffxtbr.jar
chrome/m3ffxtbr.manifest
chrome/overlayinfo/
chrome/pippki.manifest
chrome/reporter.jar
chrome/reporter.manifest
chrome/toolkit.manifest
component.reg
components/browser.manifest
components/components.list
components/@DLL_PREFIX@browserdirprovider@DLL_SUFFIX@
components/@DLL_PREFIX@brwsrdir@DLL_SUFFIX@

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

@ -882,7 +882,7 @@ toolbar[iconsize="small"] #fullscreen-button {
-moz-border-start: 1px solid ThreeDShadow;
}
#identity-box:focus {
#identity-box:-moz-focusring {
outline: 1px dotted -moz-DialogText;
}

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

@ -705,7 +705,7 @@ toolbar[iconsize="small"][mode="icons"] #forward-button:-moz-locale-dir(rtl) {
}
#identity-box:focus:not(:active):not([open="true"]) {
#identity-box:-moz-focusring {
-moz-box-shadow: 0 0 3px 1px -moz-mac-focusring inset,
0 0 3px 2px -moz-mac-focusring;
}

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

@ -60,11 +60,8 @@
#navigator-toolbox {
-moz-appearance: none;
border-top: none;
background-color: transparent;
}
#navigator-toolbox[tabsontop="true"] {
border-top: none;
border-bottom: 1px solid ThreeDShadow;
}
@ -81,7 +78,11 @@
}
#nav-bar:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop="true"] > #nav-bar {
#nav-bar[collapsed="true"] + toolbar:not(:-moz-lwtheme),
#nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop="true"] > #nav-bar,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar,
#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar {
background-image: -moz-linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
}
@ -850,13 +851,13 @@ toolbar:not([iconsize="small"])[mode="icons"] #forward-button:not([disabled="tru
background-color: hsl(92,45%,52%);
}
#identity-box:focus {
#identity-box:-moz-focusring {
outline: 1px dotted -moz-DialogText;
outline-offset: -3px;
}
#identity-box.verifiedDomain:focus ,
#identity-box.verifiedIdentity:focus {
#identity-box.verifiedDomain:-moz-focusring,
#identity-box.verifiedIdentity:-moz-focusring {
outline-color: white;
}
@ -1121,10 +1122,6 @@ richlistitem[type="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-i
-moz-box-shadow: 0 -1px ThreeDShadow inset;
}
#TabsToolbar[tabsontop="false"] {
border-bottom: 1px solid ThreeDShadow !important;
}
.tabbrowser-tabs:-moz-system-metric(touch-enabled) {
min-height: .73cm;
}

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

@ -437,7 +437,7 @@ public:
nsIViewManager* aViewManager,
nsStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult) = 0;
void DeleteShell() { mPresShell = nsnull; }
virtual void DeleteShell() = 0;
nsIPresShell* GetShell() const
{

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

@ -249,7 +249,7 @@ nsAttrValue::SetTo(const nsAttrValue& aOther)
case eAtomArray:
{
if (!EnsureEmptyAtomArray() ||
!GetAtomArrayValue()->AppendObjects(*otherCont->mAtomArray)) {
!GetAtomArrayValue()->AppendElements(*otherCont->mAtomArray)) {
Reset();
return;
}
@ -503,7 +503,7 @@ nsAttrValue::GetEnumString(nsAString& aResult, PRBool aRealTag) const
NS_NOTREACHED("couldn't find value in EnumTable");
}
PRInt32
PRUint32
nsAttrValue::GetAtomCount() const
{
ValueType type = Type();
@ -513,7 +513,7 @@ nsAttrValue::GetAtomCount() const
}
if (type == eAtomArray) {
return GetAtomArrayValue()->Count();
return GetAtomArrayValue()->Length();
}
return 0;
@ -531,7 +531,7 @@ nsAttrValue::AtomAt(PRInt32 aIndex) const
NS_ASSERTION(Type() == eAtomArray, "GetAtomCount must be confused");
return GetAtomArrayValue()->ObjectAt(aIndex);
return GetAtomArrayValue()->ElementAt(aIndex);
}
PRUint32
@ -592,9 +592,11 @@ nsAttrValue::HashValue() const
case eAtomArray:
{
PRUint32 retval = 0;
PRInt32 i, count = cont->mAtomArray->Count();
for (i = 0; i < count; ++i) {
retval ^= NS_PTR_TO_INT32(cont->mAtomArray->ObjectAt(i));
PRUint32 count = cont->mAtomArray->Length();
for (nsCOMPtr<nsIAtom> *cur = cont->mAtomArray->Elements(),
*end = cur + count;
cur != end; ++cur) {
retval ^= NS_PTR_TO_INT32(cur->get());
}
return retval;
}
@ -690,18 +692,10 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const
// For classlists we could be insensitive to order, however
// classlists are never mapped attributes so they are never compared.
PRInt32 count = thisCont->mAtomArray->Count();
if (count != otherCont->mAtomArray->Count()) {
if (!(*thisCont->mAtomArray == *otherCont->mAtomArray)) {
return PR_FALSE;
}
PRInt32 i;
for (i = 0; i < count; ++i) {
if (thisCont->mAtomArray->ObjectAt(i) !=
otherCont->mAtomArray->ObjectAt(i)) {
return PR_FALSE;
}
}
needsStringComparison = PR_TRUE;
break;
}
@ -827,19 +821,21 @@ nsAttrValue::Contains(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const
default:
{
if (Type() == eAtomArray) {
nsCOMArray<nsIAtom>* array = GetAtomArrayValue();
AtomArray* array = GetAtomArrayValue();
if (aCaseSensitive == eCaseMatters) {
return array->IndexOf(aValue) >= 0;
return array->IndexOf(aValue) != AtomArray::NoIndex;
}
nsDependentAtomString val1(aValue);
for (PRInt32 i = 0, count = array->Count(); i < count; ++i) {
for (nsCOMPtr<nsIAtom> *cur = array->Elements(),
*end = cur + array->Length();
cur != end; ++cur) {
// For performance reasons, don't do a full on unicode case
// insensitive string comparison. This is only used for quirks mode
// anyway.
if (nsContentUtils::EqualsIgnoreASCIICase(val1,
nsDependentAtomString(array->ObjectAt(i)))) {
nsDependentAtomString(*cur))) {
return PR_TRUE;
}
}
@ -913,9 +909,9 @@ nsAttrValue::ParseAtomArray(const nsAString& aValue)
return;
}
nsCOMArray<nsIAtom>* array = GetAtomArrayValue();
AtomArray* array = GetAtomArrayValue();
if (!array->AppendObject(classAtom)) {
if (!array->AppendElement(classAtom)) {
Reset();
return;
}
@ -930,7 +926,7 @@ nsAttrValue::ParseAtomArray(const nsAString& aValue)
classAtom = do_GetAtom(Substring(start, iter));
if (!array->AppendObject(classAtom)) {
if (!array->AppendElement(classAtom)) {
Reset();
return;
}
@ -1362,7 +1358,7 @@ nsAttrValue::EnsureEmptyAtomArray()
return PR_FALSE;
}
nsCOMArray<nsIAtom>* array = new nsCOMArray<nsIAtom>;
AtomArray* array = new AtomArray;
if (!array) {
Reset();
return PR_FALSE;

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

@ -50,6 +50,7 @@
#include "nsColor.h"
#include "nsCaseTreatment.h"
#include "nsMargin.h"
#include "nsCOMPtr.h"
typedef PRUptrdiff PtrBits;
class nsAString;
@ -57,7 +58,7 @@ class nsIAtom;
class nsICSSStyleRule;
class nsISVGValue;
class nsIDocument;
template<class E> class nsCOMArray;
template<class E> class nsTArray;
template<class E> class nsTPtrArray;
#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
@ -92,6 +93,8 @@ public:
class nsAttrValue {
public:
typedef nsTArray< nsCOMPtr<nsIAtom> > AtomArray;
nsAttrValue();
nsAttrValue(const nsAttrValue& aOther);
explicit nsAttrValue(const nsAString& aValue);
@ -151,7 +154,7 @@ public:
PRBool GetColorValue(nscolor& aColor) const;
inline PRInt16 GetEnumValue() const;
inline float GetPercentValue() const;
inline nsCOMArray<nsIAtom>* GetAtomArrayValue() const;
inline AtomArray* GetAtomArrayValue() const;
inline nsICSSStyleRule* GetCSSStyleRuleValue() const;
#ifdef MOZ_SVG
inline nsISVGValue* GetSVGValue() const;
@ -170,7 +173,7 @@ public:
// Methods to get access to atoms we may have
// Returns the number of atoms we have; 0 if we have none. It's OK
// to call this without checking the type first; it handles that.
PRInt32 GetAtomCount() const;
PRUint32 GetAtomCount() const;
// Returns the atom at aIndex (0-based). Do not call this with
// aIndex >= GetAtomCount().
nsIAtom* AtomAt(PRInt32 aIndex) const;
@ -333,7 +336,7 @@ private:
PRUint32 mEnumValue;
PRInt32 mPercent;
nsICSSStyleRule* mCSSStyleRule;
nsCOMArray<nsIAtom>* mAtomArray;
AtomArray* mAtomArray;
#ifdef MOZ_SVG
nsISVGValue* mSVGValue;
#endif
@ -426,7 +429,7 @@ nsAttrValue::GetPercentValue() const
/ 100.0f;
}
inline nsCOMArray<nsIAtom>*
inline nsAttrValue::AtomArray*
nsAttrValue::GetAtomArrayValue() const
{
NS_PRECONDITION(Type() == eAtomArray, "wrong type");

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

@ -6004,7 +6004,7 @@ nsContentUtils::ReparentClonedObjectToScope(JSContext* cx,
}
struct ClassMatchingInfo {
nsCOMArray<nsIAtom> mClasses;
nsAttrValue::AtomArray mClasses;
nsCaseTreatment mCaseTreatment;
};
@ -6020,14 +6020,14 @@ MatchClassNames(nsIContent* aContent, PRInt32 aNamespaceID, nsIAtom* aAtom,
// need to match *all* of the classes
ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
PRInt32 length = info->mClasses.Count();
PRUint32 length = info->mClasses.Length();
if (!length) {
// If we actually had no classes, don't match.
return PR_FALSE;
}
PRInt32 i;
PRUint32 i;
for (i = 0; i < length; ++i) {
if (!classAttr->Contains(info->mClasses.ObjectAt(i),
if (!classAttr->Contains(info->mClasses[i],
info->mCaseTreatment)) {
return PR_FALSE;
}
@ -6054,9 +6054,9 @@ AllocClassMatchingInfo(nsINode* aRootNode,
NS_ENSURE_TRUE(info, nsnull);
if (attrValue.Type() == nsAttrValue::eAtomArray) {
info->mClasses.AppendObjects(*(attrValue.GetAtomArrayValue()));
info->mClasses.SwapElements(*(attrValue.GetAtomArrayValue()));
} else if (attrValue.Type() == nsAttrValue::eAtom) {
info->mClasses.AppendObject(attrValue.GetAtomValue());
info->mClasses.AppendElement(attrValue.GetAtomValue());
}
info->mCaseTreatment =

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

@ -783,6 +783,36 @@ nsExternalResourceMap::Traverse(nsCycleCollectionTraversalCallback* aCallback) c
mMap.EnumerateRead(ExternalResourceTraverser, aCallback);
}
static PLDHashOperator
ExternalResourceHider(nsIURI* aKey,
nsExternalResourceMap::ExternalResource* aData,
void* aClosure)
{
aData->mViewer->Hide();
return PL_DHASH_NEXT;
}
void
nsExternalResourceMap::HideViewers()
{
mMap.EnumerateRead(ExternalResourceHider, nsnull);
}
static PLDHashOperator
ExternalResourceShower(nsIURI* aKey,
nsExternalResourceMap::ExternalResource* aData,
void* aClosure)
{
aData->mViewer->Show();
return PL_DHASH_NEXT;
}
void
nsExternalResourceMap::ShowViewers()
{
mMap.EnumerateRead(ExternalResourceShower, nsnull);
}
nsresult
nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
nsIDocumentViewer* aViewer,
@ -811,6 +841,9 @@ nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
} else {
doc->SetDisplayDocument(aDisplayDocument);
// Make sure that hiding our viewer will tear down its presentation.
aViewer->SetSticky(PR_FALSE);
rv = aViewer->Init(nsnull, nsIntRect(0, 0, 0, 0));
if (NS_SUCCEEDED(rv)) {
rv = aViewer->Open(nsnull, nsnull);
@ -3039,11 +3072,20 @@ nsDocument::doCreateShell(nsPresContext* aContext,
// Note: we don't hold a ref to the shell (it holds a ref to us)
mPresShell = shell;
mExternalResourceMap.ShowViewers();
shell.swap(*aInstancePtrResult);
return NS_OK;
}
void
nsDocument::DeleteShell()
{
mExternalResourceMap.HideViewers();
mPresShell = nsnull;
}
static void
SubDocClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
{
@ -7815,4 +7857,3 @@ nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
mCreatingStaticClone = PR_FALSE;
return clonedDoc.forget();
}

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

@ -375,6 +375,12 @@ public:
nsCOMPtr<nsILoadGroup> mLoadGroup;
};
// Hide all our viewers
void HideViewers();
// Show all our viewers
void ShowViewers();
protected:
class PendingLoad : public ExternalResourceLoad,
public nsIStreamListener
@ -588,6 +594,7 @@ public:
nsIViewManager* aViewManager,
nsStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult);
virtual void DeleteShell();
virtual nsresult SetSubDocumentFor(nsIContent *aContent,
nsIDocument* aSubDoc);

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

@ -1100,6 +1100,10 @@ nsHTMLParanoidFragmentSink::CloseContainer(const nsHTMLTag aTag)
{
nsresult rv = NS_OK;
if (mIgnoreNextCloseHead && aTag == eHTMLTag_head) {
mIgnoreNextCloseHead = PR_FALSE;
return NS_OK;
}
if (mSkip) {
mSkip = PR_FALSE;
return rv;
@ -1229,7 +1233,10 @@ nsHTMLParanoidFragmentSink::AddLeaf(const nsIParserNode& aNode)
nsresult rv = NS_OK;
if (mSkip) {
// We need to explicitly skip adding leaf nodes in the paranoid sink,
// otherwise things like the textnode under <title> get appended to
// the fragment itself, and won't be popped off in CloseContainer.
if (mSkip || mIgnoreNextCloseHead) {
return rv;
}

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

@ -52,6 +52,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=520182
<div id="jj" contenteditable="true"></div>
<iframe id="kk" src="about:blank"></iframe>
<div id="ll" contenteditable="true"></div>
<iframe id="mm" src="about:blank"></iframe>
<div id="nn" contenteditable="true"></div>
</div>
<pre id="test">
<script type="application/javascript">
@ -73,6 +75,7 @@ const invalidStyle3Payload = "foo<style>@import 'xxx.css';</style>baz";
const invalidStyle4Payload = "foo<span style=\"@import 'xxx.css';\">bar</span>baz";
const invalidStyle5Payload = "foo<span style=\"@font-face{font-family:xxx;src:'xxx.ttf';}\">bar</span>baz";
const invalidStyle6Payload = "foo<span style=\"@namespace xxx url(http://example.com/);\">bar</span>baz";
const invalidStyle7Payload = "<html><head><title>xxx</title></head><body>foo</body></html>";
const nestedStylePayload = "foo<style>#bar1{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-1&quot;/>');<style></style>#bar2{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-2&quot;/>');</style>baz";
const validImgSrc1Payload = "foo<img src=\"data:image/png,bar\">baz";
const validImgSrc2Payload = "foo<img src=\"javascript:void('bar');\">baz";
@ -333,6 +336,27 @@ var tests = [
payload: invalidStyle6Payload,
rootElement: function() document.getElementById("ll"),
checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
},
{
id: "mm",
isIFrame: true,
insertHTML: true,
payload: invalidStyle7Payload,
rootElement: function() document.getElementById("mm").contentDocument.documentElement,
checkResult: function(html) {
is(html.indexOf("xxx"), -1, "Should not have retained the title text");
isnot(html.indexOf("foo"), -1, "Should have retained the body text");
}
},
{
id: "nn",
insertHTML: true,
payload: invalidStyle7Payload,
rootElement: function() document.getElementById("nn"),
checkResult: function(html) {
is(html.indexOf("xxx"), -1, "Should not have retained the title text");
isnot(html.indexOf("foo"), -1, "Should have retained the body text");
}
}
];
@ -357,28 +381,37 @@ function runTest(test) {
} else
elem.focus();
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
if ("insertHTML" in test) {
if ("isIFrame" in test) {
elem.contentDocument.execCommand("inserthtml", false, test.payload);
} else {
getSelection().collapse(elem, 0);
document.execCommand("inserthtml", false, test.payload);
}
} else {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
.getService(Components.interfaces.nsIClipboard);
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
.getService(Components.interfaces.nsIClipboard);
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
.createInstance(Components.interfaces.nsITransferable);
var data = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
data.data = test.payload;
trans.addDataFlavor("text/html");
trans.setTransferData("text/html", data, data.data.length * 2);
clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
.createInstance(Components.interfaces.nsITransferable);
var data = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
data.data = test.payload;
trans.addDataFlavor("text/html");
trans.setTransferData("text/html", data, data.data.length * 2);
clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
mainWindow.goDoCommand("cmd_paste");
mainWindow.goDoCommand("cmd_paste");
}
if ("checkResult" in test) {
if ("isIFrame" in test) {

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

@ -214,7 +214,7 @@ cairo_d2d_create_device()
D3D10_1_SDK_VERSION,
&device->mD3D10Device);
if (FAILED(hr)) {
HRESULT hr = createD3DDevice(
hr = createD3DDevice(
NULL,
D3D10_DRIVER_TYPE_HARDWARE,
NULL,
@ -225,7 +225,7 @@ cairo_d2d_create_device()
&device->mD3D10Device);
if (FAILED(hr)) {
/* This is not guaranteed to be too fast! */
HRESULT hr = createD3DDevice(
hr = createD3DDevice(
NULL,
D3D10_DRIVER_TYPE_HARDWARE,
NULL,

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

@ -1115,12 +1115,12 @@ xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx, qsObjectHelper* aHelper,
const nsIID *iid, XPCNativeInterface **iface,
jsval *rval)
{
NS_PRECONDITION(iface, "Who did that and why?");
// From the T_INTERFACE case in XPCConvert::NativeData2JS.
// This is one of the slowest things quick stubs do.
JSContext *cx = lccx.GetJSContext();
if(!iface)
return xpc_qsThrow(cx, NS_ERROR_XPC_BAD_CONVERT_NATIVE);
// XXX The OBJ_IS_NOT_GLOBAL here is not really right. In
// fact, this code is depending on the fact that the

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

@ -860,7 +860,9 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
// it in one place (Show()) and require that callers call init(), open(),
// show() in that order or something.
if (!mPresContext &&
(aParentWidget || containerView || mDocument->GetDisplayDocument())) {
(aParentWidget || containerView ||
(mDocument->GetDisplayDocument() &&
mDocument->GetDisplayDocument()->GetShell()))) {
// Create presentation context
if (mIsPageMode) {
//Presentation context already created in SetPageMode which is calling this method

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

@ -109,6 +109,7 @@
using namespace mozilla::layers;
using namespace mozilla::dom;
namespace css = mozilla::css;
/**
* A namespace class for static layout utilities.
@ -1752,6 +1753,15 @@ static nscoord AddPercents(nsLayoutUtils::IntrinsicWidthType aType,
static PRBool GetAbsoluteCoord(const nsStyleCoord& aStyle, nscoord& aResult)
{
if (aStyle.IsCalcUnit()) {
if (aStyle.CalcHasPercent()) {
return PR_FALSE;
}
// If it has no percents, we can pass 0 for the percentage basis.
aResult = nsRuleNode::ComputeComputedCalc(aStyle, 0);
return PR_TRUE;
}
if (eStyleUnit_Coord != aStyle.GetUnit())
return PR_FALSE;
@ -2036,12 +2046,21 @@ nsLayoutUtils::IntrinsicForContainer(nsIRenderingContext *aRenderingContext,
PROP_WIDTH, w)) {
result = AddPercents(aType, w + coordOutsideWidth, pctOutsideWidth);
}
else if (aType == MIN_WIDTH && eStyleUnit_Percent == styleWidth.GetUnit() &&
else if (aType == MIN_WIDTH &&
// The only cases of coord-percent-calc() units that
// GetAbsoluteCoord didn't handle are percent and calc()s
// containing percent.
styleWidth.IsCoordPercentCalcUnit() &&
aFrame->IsFrameOfType(nsIFrame::eReplaced)) {
// A percentage width on replaced elements means they can shrink to 0.
result = 0; // let |min| handle padding/border/margin
}
else {
// NOTE: We could really do a lot better for percents and for some
// cases of calc() containing percent (certainly including any where
// the coefficient on the percent is positive and there are no max()
// expressions). However, doing better for percents wouldn't be
// backwards compatible.
result = AddPercents(aType, result, pctTotal);
}
@ -2138,15 +2157,12 @@ nsLayoutUtils::ComputeWidthValue(
"width less than zero");
nscoord result;
if (eStyleUnit_Coord == aCoord.GetUnit()) {
result = aCoord.GetCoordValue();
NS_ASSERTION(result >= 0, "width less than zero");
if (aCoord.IsCoordPercentCalcUnit()) {
result = nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockWidth);
// The result of a calc() expression might be less than 0; we
// should clamp at runtime (below). (Percentages and coords that
// are less than 0 have already been dropped by the parser.)
result -= aContentEdgeToBoxSizing;
} else if (eStyleUnit_Percent == aCoord.GetUnit()) {
NS_ASSERTION(aCoord.GetPercentValue() >= 0.0f, "width less than zero");
result = NSToCoordFloorClamped(aContainingBlockWidth *
aCoord.GetPercentValue()) -
aContentEdgeToBoxSizing;
} else if (eStyleUnit_Enumerated == aCoord.GetUnit()) {
PRInt32 val = aCoord.GetIntValue();
switch (val) {

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

@ -226,29 +226,9 @@ static inline PRBool IsFixedPaddingSize(nsStyleUnit aUnit) {
static inline PRBool IsFixedMarginSize(nsStyleUnit aUnit) {
return aUnit == eStyleUnit_Coord;
}
static inline PRBool IsFixedMaxSize(nsStyleUnit aUnit) {
return aUnit == eStyleUnit_None || aUnit == eStyleUnit_Coord;
}
static inline PRBool IsFixedOffset(nsStyleUnit aUnit) {
return aUnit == eStyleUnit_Coord;
}
static inline PRBool IsFixedHeight(nsStyleUnit aUnit) {
return aUnit == eStyleUnit_Coord;
}
static inline PRBool IsFixedWidth(const nsStyleCoord& aCoord)
{
return aCoord.GetUnit() == eStyleUnit_Coord ||
(aCoord.GetUnit() == eStyleUnit_Enumerated &&
(aCoord.GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT ||
aCoord.GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT));
}
static inline PRBool IsFixedMaxWidth(const nsStyleCoord& aCoord)
{
return aCoord.GetUnit() == eStyleUnit_None ||
IsFixedWidth(aCoord);
}
PRBool
nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
@ -286,9 +266,9 @@ nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// then our frame width does not depend on the parent width.
// Note that borders never depend on the parent width
// XXX All of the enumerated values except -moz-available are ok too.
if (!IsFixedWidth(pos->mWidth) ||
!IsFixedWidth(pos->mMinWidth) ||
!IsFixedMaxWidth(pos->mMaxWidth) ||
if (pos->WidthDependsOnContainer() ||
pos->MinWidthDependsOnContainer() ||
pos->MaxWidthDependsOnContainer() ||
!IsFixedPaddingSize(padding->mPadding.GetLeftUnit()) ||
!IsFixedPaddingSize(padding->mPadding.GetRightUnit())) {
return PR_TRUE;
@ -325,12 +305,12 @@ nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
// and height is a length or height and bottom are auto and top is not auto,
// then our frame height does not depend on the parent height.
// Note that borders never depend on the parent height
if (!(IsFixedHeight(pos->mHeight.GetUnit()) ||
(pos->mHeight.GetUnit() == eStyleUnit_Auto &&
if ((pos->HeightDependsOnContainer() &&
!(pos->mHeight.GetUnit() == eStyleUnit_Auto &&
pos->mOffset.GetBottomUnit() == eStyleUnit_Auto &&
pos->mOffset.GetTopUnit() != eStyleUnit_Auto)) ||
!IsFixedHeight(pos->mMinHeight.GetUnit()) ||
!IsFixedMaxSize(pos->mMaxHeight.GetUnit()) ||
pos->MinHeightDependsOnContainer() ||
pos->MaxHeightDependsOnContainer() ||
!IsFixedPaddingSize(padding->mPadding.GetTopUnit()) ||
!IsFixedPaddingSize(padding->mPadding.GetBottomUnit())) {
return PR_TRUE;

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

@ -3486,8 +3486,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
this, aFloatAvailableSpace.mHasFloats);
#endif
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aFloatAvailableSpace.mRect.x + borderPadding.left;
nscoord x = aFloatAvailableSpace.mRect.x;
nscoord availWidth = aFloatAvailableSpace.mRect.width;
nscoord availHeight;
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
@ -5557,11 +5556,9 @@ nsBlockFrame::AdjustFloatAvailableSpace(nsBlockReflowState& aState,
availWidth = aFloatAvailableSpace.width;
}
// aState.mY is relative to the border-top, make it relative to the content-top
nscoord contentYOffset = aState.mY - aState.BorderPadding().top;
nscoord availHeight = NS_UNCONSTRAINEDSIZE == aState.mContentArea.height
? NS_UNCONSTRAINEDSIZE
: NS_MAX(0, aState.mContentArea.height - contentYOffset);
: NS_MAX(0, aState.mContentArea.YMost() - aState.mY);
#ifdef DISABLE_FLOAT_BREAKING_IN_COLUMNS
if (availHeight != NS_UNCONSTRAINEDSIZE &&
@ -5574,8 +5571,8 @@ nsBlockFrame::AdjustFloatAvailableSpace(nsBlockReflowState& aState,
}
#endif
return nsRect(aState.BorderPadding().left,
aState.BorderPadding().top,
return nsRect(aState.mContentArea.x,
aState.mContentArea.y,
availWidth, availHeight);
}
@ -6610,7 +6607,7 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState,
// Reflow the bullet now
nsSize availSize;
// Make up a width since it doesn't really matter (XXX).
availSize.width = rs.ComputedWidth();
availSize.width = aState.mContentArea.width;
availSize.height = NS_UNCONSTRAINEDSIZE;
// Get the reason right.
@ -6644,26 +6641,22 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState,
// the block's border, and the bullet frame's margin.
nscoord x;
if (rs.mStyleVisibility->mDirection == NS_STYLE_DIRECTION_LTR) {
// Note: floatAvailSpace.x is relative to the content box and never
// less than zero. Converting to frame coordinates and subtracting
// the padding and border cancel each other out, and the NS_MAX()
// with 0 (or with the left border+padding) is even implied in the
// right place.
x = floatAvailSpace.x - reflowState.mComputedMargin.right - aMetrics.width;
// The floatAvailSpace.x gives us the content/float edge. Then we
// subtract out the left border/padding and the bullet's width and
// margin to offset the position.
x = floatAvailSpace.x - rs.mComputedBorderPadding.left
- reflowState.mComputedMargin.right - aMetrics.width;
} else {
// The XMost() of the available space and the computed width both
// give us offsets from the left content edge. Then we add the left
// border/padding to get into frame coordinates, and the right
// border/padding and the bullet's margin to offset the position.
x = NS_MIN(rs.ComputedWidth(), floatAvailSpace.XMost())
+ rs.mComputedBorderPadding.LeftRight()
// The XMost() of the available space give us offsets from the left
// border edge. Then we add the right border/padding and the
// bullet's margin to offset the position.
x = floatAvailSpace.XMost() + rs.mComputedBorderPadding.right
+ reflowState.mComputedMargin.left;
}
// Approximate the bullets position; vertical alignment will provide
// the final vertical location.
const nsMargin& bp = aState.BorderPadding();
nscoord y = bp.top;
nscoord y = aState.mContentArea.y;
mBullet->SetRect(nsRect(x, y, aMetrics.width, aMetrics.height));
mBullet->DidReflow(aState.mPresContext, &aState.mReflowState, NS_FRAME_REFLOW_FINISHED);
}

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

@ -278,24 +278,11 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
// from 10.3.3 to determine what to apply. At this point in the
// reflow auto left/right margins will have a zero value.
nscoord x = mSpace.x + aFrameRS.mComputedMargin.left;
nscoord y = mSpace.y + mTopMargin.get() + aClearance;
mX = tx = mSpace.x + aFrameRS.mComputedMargin.left;
mY = ty = mSpace.y + mTopMargin.get() + aClearance;
if ((mFrame->GetStateBits() & NS_BLOCK_FLOAT_MGR) == 0)
aFrameRS.mBlockDelta = mOuterReflowState.mBlockDelta + y - aLine->mBounds.y;
mX = x;
mY = y;
// Compute the translation to be used for adjusting the spacemanagager
// coordinate system for the frame. The spacemanager coordinates are
// <b>inside</b> the callers border+padding, but the x/y coordinates
// are not (recall that frame coordinates are relative to the parents
// origin and that the parents border/padding is <b>inside</b> the
// parent frame. Therefore we have to subtract out the parents
// border+padding before translating.
tx = x - mOuterReflowState.mComputedBorderPadding.left;
ty = y - mOuterReflowState.mComputedBorderPadding.top;
aFrameRS.mBlockDelta = mOuterReflowState.mBlockDelta + ty - aLine->mBounds.y;
}
// Let frame know that we are reflowing it

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

@ -102,9 +102,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
NS_ASSERTION(mFloatManager,
"FloatManager should be set in nsBlockReflowState" );
if (mFloatManager) {
// Translate into our content area and then save the
// coordinate system origin for later.
mFloatManager->Translate(borderPadding.left, borderPadding.top);
// Save the coordinate system origin for later.
mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY);
mFloatManager->PushState(&mFloatManagerStateBefore); // never popped
}
@ -139,8 +137,8 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
}
mY = borderPadding.top;
mContentArea.x = borderPadding.left;
mY = mContentArea.y = borderPadding.top;
mPrevChild = nsnull;
mCurrentLine = aFrame->end_lines();
@ -148,16 +146,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mMinLineHeight = aReflowState.CalcLineHeight();
}
nsBlockReflowState::~nsBlockReflowState()
{
// Restore the coordinate system, unless the float manager is null,
// which means it was just destroyed.
if (mFloatManager) {
const nsMargin& borderPadding = BorderPadding();
mFloatManager->Translate(-borderPadding.left, -borderPadding.top);
}
}
nsLineBox*
nsBlockReflowState::NewLineBox(nsIFrame* aFrame,
PRInt32 aCount,
@ -187,9 +175,9 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
// only give it free space. An example is a table frame - the
// tables do not flow around floats.
// However, we can let its margins intersect floats.
NS_ASSERTION(aFloatAvailableSpace.x >= 0, "bad avail space rect x");
NS_ASSERTION(aFloatAvailableSpace.x >= mContentArea.x, "bad avail space rect x");
NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
aFloatAvailableSpace.XMost() <= mContentArea.width,
aFloatAvailableSpace.XMost() <= mContentArea.XMost(),
"bad avail space rect width");
nscoord leftOffset, rightOffset;
@ -210,13 +198,13 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
aReplacedWidth->marginRight == os.mComputedMargin.right),
"unexpected aReplacedWidth");
nscoord leftFloatXOffset = aFloatAvailableSpace.x;
nscoord leftFloatXOffset = aFloatAvailableSpace.x - mContentArea.x;
leftOffset = NS_MAX(leftFloatXOffset, os.mComputedMargin.left) -
(aReplacedWidth ? aReplacedWidth->marginLeft
: os.mComputedMargin.left);
leftOffset = NS_MAX(leftOffset, 0); // in case of negative margin
nscoord rightFloatXOffset =
mContentArea.width - aFloatAvailableSpace.XMost();
mContentArea.XMost() - aFloatAvailableSpace.XMost();
rightOffset = NS_MAX(rightFloatXOffset, os.mComputedMargin.right) -
(aReplacedWidth ? aReplacedWidth->marginRight
: os.mComputedMargin.right);
@ -248,8 +236,6 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
// it off the page/column. Negative available height can confuse other code
// and is nonsense in principle.
const nsMargin& borderPadding = BorderPadding();
// XXX Do we really want this condition to be this restrictive (i.e.,
// more restrictive than it used to be)? The |else| here is allowed
// by the CSS spec, but only out of desperation given implementations,
@ -275,14 +261,14 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floats
// The child block will flow around the float. Therefore
// give it all of the available space.
aResult.x = borderPadding.left;
aResult.x = mContentArea.x;
aResult.width = mContentArea.width;
break;
case NS_STYLE_FLOAT_EDGE_MARGIN:
{
// The child block's margins should be placed adjacent to,
// but not overlap the float.
aResult.x = aFloatAvailableSpace.mRect.x + borderPadding.left;
aResult.x = aFloatAvailableSpace.mRect.x;
aResult.width = aFloatAvailableSpace.mRect.width;
}
break;
@ -292,7 +278,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
// Since there are no floats present the float-edge property
// doesn't matter therefore give the block element all of the
// available space since it will flow around the float itself.
aResult.x = borderPadding.left;
aResult.x = mContentArea.x;
aResult.width = mContentArea.width;
}
}
@ -310,7 +296,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect,
leftOffset, rightOffset,
replacedWidth);
aResult.x = borderPadding.left + leftOffset;
aResult.x = mContentArea.x + leftOffset;
aResult.width = mContentArea.width - leftOffset - rightOffset;
}
@ -332,12 +318,11 @@ nsBlockReflowState::GetFloatAvailableSpaceWithState(
"bad coord system");
#endif
nscoord y = aY - BorderPadding().top;
nscoord height = (mContentArea.height == nscoord_MAX)
? nscoord_MAX : NS_MAX(mContentArea.height - y, 0);
? nscoord_MAX : NS_MAX(mContentArea.YMost() - aY, 0);
nsFlowAreaRect result =
mFloatManager->GetFlowArea(y, nsFloatManager::BAND_FROM_POINT,
height, mContentArea.width, aState);
mFloatManager->GetFlowArea(aY, nsFloatManager::BAND_FROM_POINT,
height, mContentArea, aState);
// Keep the width >= 0 for compatibility with nsSpaceManager.
if (result.mRect.width < 0)
result.mRect.width = 0;
@ -367,9 +352,8 @@ nsBlockReflowState::GetFloatAvailableSpaceForHeight(
#endif
nsFlowAreaRect result =
mFloatManager->GetFlowArea(aY - BorderPadding().top,
nsFloatManager::WIDTH_WITHIN_HEIGHT,
aHeight, mContentArea.width, aState);
mFloatManager->GetFlowArea(aY, nsFloatManager::WIDTH_WITHIN_HEIGHT,
aHeight, mContentArea, aState);
// Keep the width >= 0 for compatibility with nsSpaceManager.
if (result.mRect.width < 0)
result.mRect.width = 0;
@ -510,12 +494,6 @@ nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
// Place floats for this line into the float manager
if (aLine->HasFloats() || aLine->IsBlock()) {
// Undo border/padding translation since the nsFloatCache's
// coordinates are relative to the frame not relative to the
// border/padding.
const nsMargin& bp = BorderPadding();
mFloatManager->Translate(-bp.left, -bp.top);
RecoverFloats(aLine, aDeltaY);
#ifdef DEBUG
@ -523,8 +501,6 @@ nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
mFloatManager->List(stdout);
}
#endif
// And then put the translation back again
mFloatManager->Translate(bp.left, bp.top);
}
}
@ -600,8 +576,7 @@ nsBlockReflowState::AddFloat(nsLineLayout* aLineLayout,
if (placed) {
// Pass on updated available space to the current inline reflow engine
nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mY);
nsRect availSpace(nsPoint(floatAvailSpace.mRect.x + BorderPadding().left,
mY),
nsRect availSpace(nsPoint(floatAvailSpace.mRect.x, mY),
floatAvailSpace.mRect.Size());
aLineLayout->UpdateBand(availSpace, aFloat);
// Record this float in the current-line list
@ -681,7 +656,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
// Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
// ``above'' another float that preceded it in the flow.
mY = NS_MAX(mFloatManager->GetLowestFloatTop() + BorderPadding().top, mY);
mY = NS_MAX(mFloatManager->GetLowestFloatTop(), mY);
// See if the float should clear any preceding floats...
// XXX We need to mark this float somehow so that it gets reflowed
@ -791,10 +766,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
// We don't worry about the geometry of the prev in flow, let the continuation
// place and size itself as required.
// Assign an x and y coordinate to the float. Note that the x,y
// coordinates are computed <b>relative to the translation in the
// spacemanager</b> which means that the impacted region will be
// <b>inside</b> the border/padding area.
// Assign an x and y coordinate to the float.
nscoord floatX, floatY;
if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
floatX = floatAvailableSpace.mRect.x;
@ -810,16 +782,12 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
floatX = floatAvailableSpace.mRect.x;
}
}
const nsMargin& borderPadding = BorderPadding();
floatY = mY - borderPadding.top;
if (floatY < 0) {
// CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
// be higher than the top of its containing block." (Since the
// containing block is the content edge of the block box, this
// means the margin edge of the float can't be higher than the
// content edge of the block that contains it.)
floatY = 0;
}
// CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
// be higher than the top of its containing block." (Since the
// containing block is the content edge of the block box, this
// means the margin edge of the float can't be higher than the
// content edge of the block that contains it.)
floatY = NS_MAX(mY, mContentArea.y);
// Reflow the float after computing its vertical position so it knows
// where to break.
@ -845,7 +813,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
(!mReflowState.mFlags.mIsTopOfPage || !IsAdjacentWithTop() ||
pushedDown) &&
aFloat->GetSize().height + floatMargin.TopBottom() >
mContentArea.height - floatY) ||
mContentArea.YMost() - floatY) ||
NS_FRAME_IS_TRUNCATED(reflowStatus)) {
PushFloatPastBreak(aFloat);
@ -853,11 +821,10 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
}
// Calculate the actual origin of the float frame's border rect
// relative to the parent block; floatX/Y must be converted from space-manager
// coordinates to parent coordinates, and the margin must be added in
// relative to the parent block; the margin must be added in
// to get the border rect
nsPoint origin(borderPadding.left + floatMargin.left + floatX,
borderPadding.top + floatMargin.top + floatY);
nsPoint origin(floatMargin.left + floatX,
floatMargin.top + floatY);
// If float is relatively positioned, factor that in as well
origin += aFloat->GetRelativeOffset(floatDisplay);
@ -884,9 +851,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
region.height = NS_MAX(region.height, mContentArea.height - floatY);
}
nsresult rv =
// spacemanager translation is inset by the border+padding.
mFloatManager->AddFloat(aFloat,
region - nsPoint(borderPadding.left, borderPadding.top));
mFloatManager->AddFloat(aFloat, region);
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement");
// store region
rv = nsFloatManager::StoreRegionFor(aFloat, region);
@ -899,8 +864,8 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
// less damage; e.g., if only height has changed, then only note the
// area into which the float has grown or from which the float has
// shrunk.
nscoord top = NS_MIN(region.y, oldRegion.y) - borderPadding.top;
nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost()) - borderPadding.top;
nscoord top = NS_MIN(region.y, oldRegion.y);
nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost());
mFloatManager->IncludeInDamage(top, bottom);
}
@ -993,8 +958,7 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("clear floats: in: aY=%d(%d)\n",
aY, aY - BorderPadding().top);
printf("clear floats: in: aY=%d\n", aY);
}
#endif
@ -1004,12 +968,10 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
mFloatManager->List(stdout);
#endif
const nsMargin& bp = BorderPadding();
nscoord newY = aY;
if (aBreakType != NS_STYLE_CLEAR_NONE) {
newY = bp.top +
mFloatManager->ClearFloats(newY - bp.top, aBreakType, aFlags);
newY = mFloatManager->ClearFloats(newY, aBreakType, aFlags);
}
if (aReplacedBlock) {
@ -1019,11 +981,10 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
aReplacedBlock);
if (!floatAvailableSpace.mHasFloats ||
NS_MAX(floatAvailableSpace.mRect.x, replacedWidth.marginLeft) +
NS_MAX(floatAvailableSpace.mRect.x - mContentArea.x,
replacedWidth.marginLeft) +
replacedWidth.borderBoxWidth +
NS_MAX(mContentArea.width -
NS_MIN(mContentArea.width,
floatAvailableSpace.mRect.XMost()),
NS_MAX(mContentArea.XMost() - floatAvailableSpace.mRect.XMost(),
replacedWidth.marginRight) <=
mContentArea.width) {
break;
@ -1047,7 +1008,7 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("clear floats: out: y=%d(%d)\n", newY, newY - bp.top);
printf("clear floats: out: y=%d\n", newY);
}
#endif

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

@ -75,8 +75,6 @@ public:
PRBool aTopMarginRoot, PRBool aBottomMarginRoot,
PRBool aBlockNeedsFloatManager);
~nsBlockReflowState();
/**
* Get the available reflow space (the area not occupied by floats)
* for the current y coordinate. The available space is relative to
@ -220,12 +218,15 @@ public:
nscoord mBottomEdge;
// The content area to reflow child frames within. The x/y
// coordinates are known to be mBorderPadding.left and
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
// if the container reflowing this frame has given the frame an
// unconstrained area.
nsSize mContentArea;
// The content area to reflow child frames within. This is within
// this frame's coordinate system, which means mContentArea.x ==
// BorderPadding().left and mContentArea.y == BorderPadding().top.
// The height may be NS_UNCONSTRAINEDSIZE, which indicates that there
// is no page/column boundary below (the common case).
// mContentArea.YMost() should only be called after checking that
// mContentArea.height is not NS_UNCONSTRAINEDSIZE; otherwise
// coordinate overflow may occur.
nsRect mContentArea;
// Continuation out-of-flow float frames that need to move to our
// next in flow are placed here during reflow. It's a pointer to

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

@ -144,11 +144,11 @@ void nsFloatManager::Shutdown()
nsFlowAreaRect
nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
nscoord aHeight, nscoord aContentAreaWidth,
nscoord aHeight, nsRect aContentArea,
SavedState* aState) const
{
NS_ASSERTION(aHeight >= 0, "unexpected max height");
NS_ASSERTION(aContentAreaWidth >= 0, "unexpected content area width");
NS_ASSERTION(aContentArea.width >= 0, "unexpected content area width");
nscoord top = aYOffset + mY;
if (top < nscoord_MIN) {
@ -172,7 +172,8 @@ nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
if (floatCount == 0 ||
(mFloats[floatCount-1].mLeftYMost <= top &&
mFloats[floatCount-1].mRightYMost <= top)) {
return nsFlowAreaRect(0, aYOffset, aContentAreaWidth, aHeight, PR_FALSE);
return nsFlowAreaRect(aContentArea.x, aYOffset, aContentArea.width,
aHeight, PR_FALSE);
}
nscoord bottom;
@ -189,8 +190,8 @@ nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
bottom = nscoord_MAX;
}
}
nscoord left = mX;
nscoord right = aContentAreaWidth + mX;
nscoord left = mX + aContentArea.x;
nscoord right = mX + aContentArea.XMost();
if (right < left) {
NS_WARNING("bad value");
right = left;

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

@ -156,14 +156,13 @@ public:
* @param aY [in] vertical coordinate for top of available space
* desired
* @param aHeight [in] see above
* @param aContentAreaWidth [in] the width of the content area (whose left
* edge must be zero in the current translation)
* @param aContentArea [in] an nsRect representing the content area
* @param aState [in] If null, use the current state, otherwise, do
* computation based only on floats present in the given
* saved state.
* @return An nsFlowAreaRect whose:
* mRect is the resulting rectangle for line boxes. It will not go
* left of 0, nor right of aContentAreaWidth, but will be
* mRect is the resulting rectangle for line boxes. It will not
* extend beyond aContentArea's horizontal bounds, but may be
* narrower when floats are present.
* mBandHasFloats is whether there are floats at the sides of the
* return value including those that do not reduce the line box
@ -173,7 +172,7 @@ public:
*/
enum BandInfoType { BAND_FROM_POINT, WIDTH_WITHIN_HEIGHT };
nsFlowAreaRect GetFlowArea(nscoord aY, BandInfoType aInfoType,
nscoord aHeight, nscoord aContentAreaWidth,
nscoord aHeight, nsRect aContentArea,
SavedState* aState) const;
/**

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

@ -1157,29 +1157,6 @@ nsXULScrollFrame::GetMaxSize(nsBoxLayoutState& aState)
return maxSize;
}
#if 0 // XXXldb I don't think this is even needed
/* virtual */ nscoord
nsXULScrollFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
{
nsStyleUnit widthUnit = GetStylePosition()->mWidth.GetUnit();
if (widthUnit == eStyleUnit_Percent || widthUnit == eStyleUnit_Auto) {
nsMargin border = aReflowState.mComputedBorderPadding;
aDesiredSize.mMaxElementWidth = border.right + border.left;
mMaxElementWidth = aDesiredSize.mMaxElementWidth;
} else {
NS_NOTYETIMPLEMENTED("Use the info from the scrolled frame");
#if 0
// if not set then use the cached size. If set then set it.
if (aDesiredSize.mMaxElementWidth == -1)
aDesiredSize.mMaxElementWidth = mMaxElementWidth;
else
mMaxElementWidth = aDesiredSize.mMaxElementWidth;
#endif
}
return 0;
}
#endif
#ifdef NS_DEBUG
NS_IMETHODIMP
nsXULScrollFrame::GetFrameName(nsAString& aResult) const

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

@ -125,13 +125,8 @@ static PRBool HaveFixedSize(const nsStylePosition* aStylePosition)
// check the width and height values in the reflow state's style struct
// - if width and height are specified as either coord or percentage, then
// the size of the image frame is constrained
nsStyleUnit widthUnit = aStylePosition->mWidth.GetUnit();
nsStyleUnit heightUnit = aStylePosition->mHeight.GetUnit();
return ((widthUnit == eStyleUnit_Coord ||
widthUnit == eStyleUnit_Percent) &&
(heightUnit == eStyleUnit_Coord ||
heightUnit == eStyleUnit_Percent));
return aStylePosition->mWidth.IsCoordPercentCalcUnit() &&
aStylePosition->mHeight.IsCoordPercentCalcUnit();
}
// use the data in the reflow state to decide if the image has a constrained size
// (i.e. width and height that are based on the containing block size and not the image size)
@ -146,11 +141,15 @@ inline PRBool HaveFixedSize(const nsHTMLReflowState& aReflowState)
// during pass 1 reflow, ComputedWidth() is NS_UNCONSTRAINEDSIZE
// in pass 2 reflow, ComputedWidth() is 0, it also needs to return PR_FALSE
// see bug 156731
nsStyleUnit heightUnit = (*(aReflowState.mStylePosition)).mHeight.GetUnit();
nsStyleUnit widthUnit = (*(aReflowState.mStylePosition)).mWidth.GetUnit();
return ((eStyleUnit_Percent == heightUnit && NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight()) ||
(eStyleUnit_Percent == widthUnit && (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth() ||
0 == aReflowState.ComputedWidth())))
const nsStyleCoord &height = aReflowState.mStylePosition->mHeight;
const nsStyleCoord &width = aReflowState.mStylePosition->mWidth;
return (((eStyleUnit_Percent == height.GetUnit() ||
(height.IsCalcUnit() && height.CalcHasPercent())) &&
NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight()) ||
((eStyleUnit_Percent == width.GetUnit() ||
(width.IsCalcUnit() && width.CalcHasPercent())) &&
(NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth() ||
0 == aReflowState.ComputedWidth())))
? PR_FALSE
: HaveFixedSize(aReflowState.mStylePosition);
}

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

@ -653,16 +653,6 @@ HasPercentageUnitSide(const nsStyleSides& aSides)
return PR_FALSE;
}
inline PRBool
WidthDependsOnContainer(const nsStyleCoord& aCoord)
{
return aCoord.GetUnit() == eStyleUnit_Percent ||
(aCoord.GetUnit() == eStyleUnit_Enumerated &&
(aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE ||
aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT));
}
static PRBool
IsPercentageAware(const nsIFrame* aFrame)
{
@ -694,9 +684,10 @@ IsPercentageAware(const nsIFrame* aFrame)
const nsStylePosition* pos = aFrame->GetStylePosition();
if (WidthDependsOnContainer(pos->mWidth) ||
WidthDependsOnContainer(pos->mMaxWidth) ||
WidthDependsOnContainer(pos->mMinWidth) ||
if ((pos->WidthDependsOnContainer() &&
pos->mWidth.GetUnit() != eStyleUnit_Auto) ||
pos->MaxWidthDependsOnContainer() ||
pos->MinWidthDependsOnContainer() ||
eStyleUnit_Percent == pos->mOffset.GetRightUnit() ||
eStyleUnit_Percent == pos->mOffset.GetLeftUnit()) {
return PR_TRUE;
@ -822,25 +813,16 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
// Let frame know that are reflowing it. Note that we don't bother
// positioning the frame yet, because we're probably going to end up
// moving it when we do the vertical alignment
nscoord x = pfd->mBounds.x;
nscoord y = pfd->mBounds.y;
aFrame->WillReflow(mPresContext);
// Adjust spacemanager coordinate system for the frame. The
// spacemanager coordinates are <b>inside</b> the current spans
// border+padding, but the x/y coordinates are not (recall that
// frame coordinates are relative to the parents origin and that the
// parents border/padding is <b>inside</b> the parent
// frame. Therefore we have to subtract out the parents
// border+padding before translating.
// Adjust spacemanager coordinate system for the frame.
nsHTMLReflowMetrics metrics;
#ifdef DEBUG
metrics.width = nscoord(0xdeadbeef);
metrics.height = nscoord(0xdeadbeef);
#endif
nscoord tx = x - psd->mReflowState->mComputedBorderPadding.left;
nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
nscoord tx = pfd->mBounds.x;
nscoord ty = pfd->mBounds.y;
mFloatManager->Translate(tx, ty);
nsIAtom* frameType = aFrame->GetType();

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

@ -172,6 +172,7 @@ SpacerFrame::GetDesiredSize(nsHTMLReflowMetrics& aMetrics, nsSize aPercentBase)
float factor = position->mWidth.GetPercentValue();
aMetrics.width = NSToCoordRound(factor * aPercentBase.width);
}
// else treat enumerated values and calc() like 'auto'
// height
unit = position->mHeight.GetUnit();

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

@ -0,0 +1,4 @@
== width-block-1.html width-block-1-ref.html
== width-block-intrinsic-1.html width-block-intrinsic-1-ref.html
== width-table-auto-1.html width-table-auto-1-ref.html
== width-table-fixed-1.html width-table-fixed-1-ref.html

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

@ -0,0 +1,31 @@
<!DOCTYPE HTML>
<title>width: calc() on blocks</title>
<style>
body { width: 500px }
p { background: green; color: white; margin: 1px 0; font-size: 10px }
</style>
<p style="width: 247px">50% - 3px</p>
<p style="width: 247px">25% - 3px + 25%</p>
<p style="width: 247px">25% - 3px + 12.5% * 2</p>
<p style="width: 247px">25% - 3px + 12.5%*2</p>
<p style="width: 247px">25% - 3px + 2*12.5%</p>
<p style="width: 247px">25% - 3px + 2 * 12.5%</p>
<p style="width: 125px">min(25%, 150px)</p>
<p style="width: 100px">min(25%, 100px)</p>
<p style="width: 150px">max(25%, 150px)</p>
<p style="width: 125px">max(25%, 100px)</p>
<p style="width: 150px">min(25%, 150px) + 5%</p>
<p style="width: 125px">min(25%, 100px) + 5%</p>
<p style="width: 175px">max(25%, 150px) + 5%</p>
<p style="width: 150px">max(25%, 100px) + 5%</p>
<p style="width: 105px">min(25%, 150px) - 2em</p>
<p style="width: 80px">min(25%, 100px) - 2em</p>
<p style="width: 130px">max(25%, 150px) - 2em</p>
<p style="width: 105px">max(25%, 100px) - 2em</p>
<p style="width: 250px">30% + 20%</p>
<p style="width: 250px">30% + max(20%, 1px)</p>
<p style="width: 250px">max(25%, 50%)</p>
<p style="width: 125px">max(25%, 50%)</p>

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

@ -0,0 +1,31 @@
<!DOCTYPE HTML>
<title>width: calc() on blocks</title>
<style>
body { width: 500px }
p { background: green; color: white; margin: 1px 0; font-size: 10px }
</style>
<p style="width: -moz-calc(50% - 3px)">50% - 3px</p>
<p style="width: -moz-calc(25% - 3px + 25%)">25% - 3px + 25%</p>
<p style="width: -moz-calc(25% - 3px + 12.5% * 2)">25% - 3px + 12.5% * 2</p>
<p style="width: -moz-calc(25% - 3px + 12.5%*2)">25% - 3px + 12.5%*2</p>
<p style="width: -moz-calc(25% - 3px + 2*12.5%)">25% - 3px + 2*12.5%</p>
<p style="width: -moz-calc(25% - 3px + 2 * 12.5%)">25% - 3px + 2 * 12.5%</p>
<p style="width: -moz-min(25%, 150px)">min(25%, 150px)</p>
<p style="width: -moz-calc(min(25%, 100px))">min(25%, 100px)</p>
<p style="width: -moz-calc(max(25%, 150px))">max(25%, 150px)</p>
<p style="width: -moz-max(25%, 100px)">max(25%, 100px)</p>
<p style="width: -moz-calc(min(25%, 150px) + 5%)">min(25%, 150px) + 5%</p>
<p style="width: -moz-calc(min(25%, 100px) + 5%)">min(25%, 100px) + 5%</p>
<p style="width: -moz-calc(max(25%, 150px) + 5%)">max(25%, 150px) + 5%</p>
<p style="width: -moz-calc(max(25%, 100px) + 5%)">max(25%, 100px) + 5%</p>
<p style="width: -moz-calc(min(25%, 150px) - 2em)">min(25%, 150px) - 2em</p>
<p style="width: -moz-calc(min(25%, 100px) - 2em)">min(25%, 100px) - 2em</p>
<p style="width: -moz-calc(max(25%, 150px) - 2em)">max(25%, 150px) - 2em</p>
<p style="width: -moz-calc(max(25%, 100px) - 2em)">max(25%, 100px) - 2em</p>
<p style="width: -moz-calc(30% + 20%)">30% + 20%</p>
<p style="width: -moz-calc(30% + max(20%, 1px))">30% + max(20%, 1px)</p>
<p style="width: -moz-calc(max(25%, 50%))">max(25%, 50%)</p>
<p style="width: -moz-calc(min(25%, 50%))">max(25%, 50%)</p>

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

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<title>intrinsic width of width: calc() on blocks</title>
<style>
body > div { margin: 0 0 1px 0; background: blue; color: white; height: 5px }
</style>
<div style="width: 200px"></div>
<div style="width: 47px"></div>
<div style="width: 47px"></div>
<div style="width: 200px"></div>
<div style="width: 200px"></div>
<div style="width: 50px"></div>
<div style="width: 200px"></div>
<div style="width: 200px"></div>
<div style="width: 50px"></div>
<div style="width: 200px"></div>
<div style="width: 200px"></div>
<div style="width: 200px"></div>
<div style="width: 200px"></div>
<div style="width: 200px"></div>

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

@ -0,0 +1,25 @@
<!DOCTYPE HTML>
<title>intrinsic width of width: calc() on blocks</title>
<style>
body { font-size: 10px }
body > div { float: left; clear: left;
margin: 0 0 1px 0; background: blue; color: white; height: 5px }
body > div > div > div { width: 200px }
</style>
<div><div style="width: -moz-calc(50% - 3px)"><div></div></div></div>
<div><div style="width: -moz-calc(5em - 3px)"><div></div></div></div>
<div><div style="width: -moz-calc(max(5em, 0) - 3px)"><div></div></div></div>
<div><div style="width: -moz-calc(max(5em, 0%) - 3px)"><div></div></div></div>
<div><div style="width: -moz-calc(5em - min(3px, 0%))"><div></div></div></div>
<div><div style="width: -moz-calc(5em - min(3px, 0))"><div></div></div></div>
<div><div style="width: -moz-calc(5em - 0%)"><div></div></div></div>
<div><div style="width: -moz-calc(50%)"><div></div></div></div>
<div><div style="width: -moz-calc(50px)"><div></div></div></div>
<div><div style="width: -moz-calc(25% + 25%)"><div></div></div></div>
<div><div style="width: -moz-calc(min(25%, 50%))"><div></div></div></div>
<div><div style="width: -moz-calc(max(25%, 50%))"><div></div></div></div>
<div><div style="width: -moz-calc(min(25%, 100px))"><div></div></div></div>
<div><div style="width: -moz-calc(max(25%, 100px))"><div></div></div></div>

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

@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<title>width: calc() on table-layout: auto tables</title>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>

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

@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<title>width: calc() on table-layout: auto tables</title>
<table border>
<tr>
<td style="width: -moz-calc(500px)">x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td style="width: -moz-calc(50%)">x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td style="width: -moz-calc(min(50%, 500px))">x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td style="width: -moz-calc(max(50%, 500px))">x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td style="width: -moz-calc(2 * 10% + 0.5 * 500px)">x</td>
<td style="width: 100px">y</td>
</table>

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

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<title>width: calc() on table-layout: auto tables</title>
<style>
table { table-layout: fixed; width: 500px; border-spacing: 0 }
</style>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td>x</td>
<td style="width: 100px">y</td>
</table>

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

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<title>width: calc() on table-layout: auto tables</title>
<style>
table { table-layout: fixed; width: 500px; border-spacing: 0 }
</style>
<table border>
<tr>
<td style="width: -moz-calc(500px)">x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td style="width: -moz-calc(50%)">x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td style="width: -moz-calc(min(50%, 500px))">x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td style="width: -moz-calc(max(50%, 500px))">x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td style="width: -moz-calc(2 * 10% + 0.5 * 500px)">x</td>
<td style="width: 100px">y</td>
</table>

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

@ -41,15 +41,18 @@ include bugs/reftest.list
# canvas 2D
include canvas/reftest.list
# css calc() tests
include css-calc/reftest.list
# css character encoding tests
include css-charset/reftest.list
# css default pseudo class tests
include css-default/reftest.list
# css @import tests
include css-import/reftest.list
# css character encoding tests
include css-charset/reftest.list
# css gradients
include css-gradients/reftest.list

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

@ -38,6 +38,7 @@
#define CSSCalc_h_
#include "nsCSSValue.h"
#include "nsStyleCoord.h"
#include <math.h>
namespace mozilla {
@ -152,6 +153,38 @@ ComputeCalc(const typename CalcOps::input_type& aValue, CalcOps &aOps)
}
}
#define CHECK_UNIT(u_) \
PR_STATIC_ASSERT(int(eCSSUnit_##u_) + 14 == int(eStyleUnit_##u_)); \
PR_STATIC_ASSERT(eCSSUnit_##u_ >= eCSSUnit_Calc); \
PR_STATIC_ASSERT(eCSSUnit_##u_ <= eCSSUnit_Calc_Maximum);
CHECK_UNIT(Calc)
CHECK_UNIT(Calc_Plus)
CHECK_UNIT(Calc_Minus)
CHECK_UNIT(Calc_Times_L)
CHECK_UNIT(Calc_Times_R)
CHECK_UNIT(Calc_Divided)
CHECK_UNIT(Calc_Minimum)
CHECK_UNIT(Calc_Maximum)
#undef CHECK_UNIT
inline nsStyleUnit
ConvertCalcUnit(nsCSSUnit aUnit)
{
NS_ABORT_IF_FALSE(eCSSUnit_Calc <= aUnit &&
aUnit <= eCSSUnit_Calc_Maximum, "out of range");
return nsStyleUnit(aUnit + 14);
}
inline nsCSSUnit
ConvertCalcUnit(nsStyleUnit aUnit)
{
NS_ABORT_IF_FALSE(eStyleUnit_Calc <= aUnit &&
aUnit <= eStyleUnit_Calc_Maximum, "out of range");
return nsCSSUnit(aUnit - 14);
}
/**
* The input unit operation for input_type being nsCSSValue.
*/
@ -167,6 +200,30 @@ struct CSSValueInputCalcOps
};
/**
* The input unit operation for input_type being nsStyleCoord
*/
struct StyleCoordInputCalcOps
{
typedef nsStyleCoord input_type;
typedef nsStyleCoord::Array input_array_type;
static nsCSSUnit GetUnit(const nsStyleCoord& aValue)
{
if (aValue.IsCalcUnit()) {
return css::ConvertCalcUnit(aValue.GetUnit());
}
return eCSSUnit_Null;
}
float ComputeNumber(const nsStyleCoord& aValue)
{
NS_ABORT_IF_FALSE(PR_FALSE, "SpecifiedToComputedCalcOps should not "
"leave numbers in structure");
return 0.0f;
}
};
/**
* Basic*CalcOps provide a partial implementation of the CalcOps
* template parameter to ComputeCalc, for those callers whose merging
@ -275,37 +332,6 @@ struct NumbersAlreadyNormalizedOps : public CSSValueInputCalcOps
}
};
#define CHECK_UNIT(u_) \
PR_STATIC_ASSERT(int(eCSSUnit_Calc_##u_) + 14 == int(eStyleUnit_Calc_##u_));\
PR_STATIC_ASSERT(eCSSUnit_Calc_##u_ >= eCSSUnit_Calc_Plus); \
PR_STATIC_ASSERT(eCSSUnit_Calc_##u_ <= eCSSUnit_Calc_Maximum);
CHECK_UNIT(Plus)
CHECK_UNIT(Minus)
CHECK_UNIT(Times_L)
CHECK_UNIT(Times_R)
CHECK_UNIT(Divided)
CHECK_UNIT(Minimum)
CHECK_UNIT(Maximum)
#undef CHECK_UNIT
inline nsStyleUnit
ConvertCalcUnit(nsCSSUnit aUnit)
{
NS_ABORT_IF_FALSE(eCSSUnit_Calc_Plus <= aUnit &&
aUnit <= eCSSUnit_Calc_Maximum, "out of range");
return nsStyleUnit(aUnit + 14);
}
inline nsCSSUnit
ConvertCalcUnit(nsStyleUnit aUnit)
{
NS_ABORT_IF_FALSE(eStyleUnit_Calc_Plus <= aUnit &&
aUnit <= eStyleUnit_Calc_Maximum, "out of range");
return nsCSSUnit(aUnit - 14);
}
/**
* SerializeCalc appends the serialization of aValue to a string.
*

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

@ -512,7 +512,9 @@ protected:
PRBool ParseTransition();
PRBool ParseTransitionTimingFunction();
PRBool ParseTransitionTimingFunctionValues(nsCSSValue& aValue);
PRBool ParseTransitionTimingFunctionValueComponent(float& aComponent, char aStop);
PRBool ParseTransitionTimingFunctionValueComponent(float& aComponent,
char aStop,
PRBool aCheckRange);
PRBool AppendValueToList(nsCSSValueList**& aListTail,
const nsCSSValue& aValue);
@ -1307,6 +1309,7 @@ CSSParserImpl::GetURLInParens(nsString& aURL)
NS_ASSERTION(!mHavePushBack, "mustn't have pushback at this point");
do {
if (! mScanner.NextURL(mToken)) {
// EOF
return PR_FALSE;
}
} while (eCSSToken_WhiteSpace == mToken.mType);
@ -3613,7 +3616,8 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
aValue.SetColorValue(NS_RGB(r,g,b));
return PR_TRUE;
}
return PR_FALSE; // already pushed back
SkipUntil(')');
return PR_FALSE;
}
else if (mToken.mIdent.LowerCaseEqualsLiteral("-moz-rgba") ||
mToken.mIdent.LowerCaseEqualsLiteral("rgba")) {
@ -3627,7 +3631,8 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
aValue.SetColorValue(NS_RGBA(r, g, b, a));
return PR_TRUE;
}
return PR_FALSE; // already pushed back
SkipUntil(')');
return PR_FALSE;
}
else if (mToken.mIdent.LowerCaseEqualsLiteral("hsl")) {
// hsl ( hue , saturation , lightness )
@ -3636,6 +3641,7 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
aValue.SetColorValue(rgba);
return PR_TRUE;
}
SkipUntil(')');
return PR_FALSE;
}
else if (mToken.mIdent.LowerCaseEqualsLiteral("-moz-hsla") ||
@ -3650,6 +3656,7 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
NS_GET_B(rgba), a));
return PR_TRUE;
}
SkipUntil(')');
return PR_FALSE;
}
break;
@ -4472,12 +4479,20 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
if (((aVariantMask & VARIANT_ATTR) != 0) &&
(eCSSToken_Function == tk->mType) &&
tk->mIdent.LowerCaseEqualsLiteral("attr")) {
return ParseAttr(aValue);
if (!ParseAttr(aValue)) {
SkipUntil(')');
return PR_FALSE;
}
return PR_TRUE;
}
if (((aVariantMask & VARIANT_CUBIC_BEZIER) != 0) &&
(eCSSToken_Function == tk->mType)) {
if (tk->mIdent.LowerCaseEqualsLiteral("cubic-bezier")) {
return ParseTransitionTimingFunctionValues(aValue);
if (!ParseTransitionTimingFunctionValues(aValue)) {
SkipUntil(')');
return PR_FALSE;
}
return PR_TRUE;
}
}
if ((aVariantMask & VARIANT_CALC) &&
@ -5729,7 +5744,7 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
case eCSSProperty_height:
return ParseNonNegativeVariant(aValue, VARIANT_AHLP, nsnull);
case eCSSProperty_width:
return ParseNonNegativeVariant(aValue, VARIANT_AHKLP,
return ParseNonNegativeVariant(aValue, VARIANT_AHKLP | VARIANT_CALC,
nsCSSProps::kWidthKTable);
case eCSSProperty_force_broken_image_icon:
return ParseNonNegativeVariant(aValue, VARIANT_HI, nsnull);
@ -8859,10 +8874,10 @@ CSSParserImpl::ParseTransitionTimingFunctionValues(nsCSSValue& aValue)
}
float x1, x2, y1, y2;
if (!ParseTransitionTimingFunctionValueComponent(x1, ',') ||
!ParseTransitionTimingFunctionValueComponent(y1, ',') ||
!ParseTransitionTimingFunctionValueComponent(x2, ',') ||
!ParseTransitionTimingFunctionValueComponent(y2, ')')) {
if (!ParseTransitionTimingFunctionValueComponent(x1, ',', PR_TRUE) ||
!ParseTransitionTimingFunctionValueComponent(y1, ',', PR_FALSE) ||
!ParseTransitionTimingFunctionValueComponent(x2, ',', PR_TRUE) ||
!ParseTransitionTimingFunctionValueComponent(y2, ')', PR_FALSE)) {
return PR_FALSE;
}
@ -8878,14 +8893,19 @@ CSSParserImpl::ParseTransitionTimingFunctionValues(nsCSSValue& aValue)
PRBool
CSSParserImpl::ParseTransitionTimingFunctionValueComponent(float& aComponent,
char aStop)
char aStop,
PRBool aCheckRange)
{
if (!GetToken(PR_TRUE)) {
return PR_FALSE;
}
nsCSSToken* tk = &mToken;
if (tk->mType == eCSSToken_Number) {
aComponent = tk->mNumber;
float num = tk->mNumber;
if (aCheckRange && (num < 0.0 || num > 1.0)) {
return PR_FALSE;
}
aComponent = num;
if (ExpectSymbol(aStop, PR_TRUE)) {
return PR_TRUE;
}

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

@ -510,21 +510,19 @@ SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord,
SpecifiedToComputedCalcOps ops(aStyleContext, aStyleContext->PresContext(),
aCanStoreInRuleTree);
aCoord = ComputeCalc(aValue, ops);
if (!aCoord.IsCalcUnit()) {
// Some callers distinguish between calc(50%) and 50%, or calc(50px)
// and 50px.
nsStyleCoord::Array *array =
nsStyleCoord::Array::Create(aStyleContext, aCanStoreInRuleTree, 1);
array->Item(0) = aCoord;
aCoord.SetArrayValue(array, eStyleUnit_Calc);
}
}
struct ComputeComputedCalcCalcOps : public css::BasicCoordCalcOps
struct ComputeComputedCalcCalcOps : public css::StyleCoordInputCalcOps,
public css::BasicCoordCalcOps
{
typedef nsStyleCoord input_type;
typedef nsStyleCoord::Array input_array_type;
static nsCSSUnit GetUnit(const nsStyleCoord& aValue)
{
if (aValue.IsCalcUnit()) {
return css::ConvertCalcUnit(aValue.GetUnit());
}
return eCSSUnit_Null;
}
const nscoord mPercentageBasis;
ComputeComputedCalcCalcOps(nscoord aPercentageBasis)
@ -543,13 +541,6 @@ struct ComputeComputedCalcCalcOps : public css::BasicCoordCalcOps
}
return result;
}
float ComputeNumber(const nsStyleCoord& aValue)
{
NS_ABORT_IF_FALSE(PR_FALSE, "SpecifiedToComputedCalcOps should not "
"leave numbers in structure");
return 0.0f;
}
};
// This is our public API for handling calc() expressions that involve
@ -562,22 +553,6 @@ nsRuleNode::ComputeComputedCalc(const nsStyleCoord& aValue,
return css::ComputeCalc(aValue, ops);
}
/* static */ nscoord
nsRuleNode::ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
nscoord aPercentageBasis)
{
switch (aCoord.GetUnit()) {
case eStyleUnit_Coord:
return aCoord.GetCoordValue();
case eStyleUnit_Percent:
return NSCoordSaturatingMultiply(aPercentageBasis,
aCoord.GetPercentValue());
default:
NS_ABORT_IF_FALSE(aCoord.IsCalcUnit(), "unexpected unit");
return nsRuleNode::ComputeComputedCalc(aCoord, aPercentageBasis);
}
}
#define SETCOORD_NORMAL 0x01 // N
#define SETCOORD_AUTO 0x02 // A
#define SETCOORD_INHERIT 0x04 // H
@ -5556,8 +5531,8 @@ nsRuleNode::ComputePositionData(void* aStartStruct,
}
SetCoord(posData.mWidth, pos->mWidth, parentPos->mWidth,
SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO, aContext,
mPresContext, canStoreInRuleTree);
SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC,
aContext, mPresContext, canStoreInRuleTree);
SetCoord(posData.mMinWidth, pos->mMinWidth, parentPos->mMinWidth,
SETCOORD_LPEH | SETCOORD_INITIAL_ZERO, aContext,
mPresContext, canStoreInRuleTree);

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

@ -767,7 +767,11 @@ public:
// Compute the value of an nsStyleCoord that is either a coord, a
// percent, or a calc expression.
static nscoord ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
nscoord aPercentageBasis);
nscoord aPercentageBasis)
{
// ComputeComputedCalc will handle coords and percents correctly
return ComputeComputedCalc(aCoord, aPercentageBasis);
}
// Return whether the rule tree for which this node is the root has
// cached data such that we need to do dynamic change handling for

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

@ -128,7 +128,6 @@ public:
const Value& aEndValue,
double aPortion,
Value& aResultValue) {
NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range");
return AddWeighted(aProperty, 1.0 - aPortion, aStartValue,
aPortion, aEndValue, aResultValue);
}

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

@ -211,6 +211,24 @@ nsStyleCoord::GetAngleValueInRadians() const
}
}
PRBool
nsStyleCoord::CalcHasPercent() const
{
NS_ABORT_IF_FALSE(IsCalcUnit(), "caller should check IsCalcUnit()");
nsStyleCoord::Array *a = GetArrayValue();
for (size_t i = 0, i_end = a->Count(); i < i_end; ++i) {
const nsStyleCoord &v = a->Item(i);
if (v.GetUnit() == eStyleUnit_Percent) {
return PR_TRUE;
}
if (v.IsCalcUnit() && v.CalcHasPercent()) {
return PR_TRUE;
}
}
return PR_FALSE;
}
inline void*
nsStyleCoord::Array::operator new(size_t aSelfSize,
nsStyleContext *aAllocationContext,

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

@ -60,12 +60,12 @@ enum nsStyleUnit {
eStyleUnit_Coord = 20, // (nscoord) value is twips
eStyleUnit_Integer = 30, // (int) value is simple integer
eStyleUnit_Enumerated = 32, // (int) value has enumerated meaning
// The following are all of the eCSSUnit_Calc_* types (but not
// eCSSUnit_Calc itself, since we don't need to distinguish
// calc(min()) from min() in compute dstyle). They are all weak
// The following are all of the eCSSUnit_Calc_* types. They are weak
// pointers to a calc tree allocated by nsStyleContext::Alloc.
// NOTE: They are in the same order as the eCSSUnit_Calc_* values so
// that converting between the two sets is just addition/subtraction.
eStyleUnit_Calc = 39, // (Array*) calc() toplevel, to
// distinguish 50% from calc(50%), etc.
eStyleUnit_Calc_Plus = 40, // (Array*) + node within calc()
eStyleUnit_Calc_Minus = 41, // (Array*) - within calc
eStyleUnit_Calc_Times_L = 42, // (Array*) num * val within calc
@ -121,9 +121,19 @@ public:
}
PRBool IsCalcUnit() const {
return eStyleUnit_Calc_Plus <= mUnit && mUnit <= eStyleUnit_Calc_Maximum;
return eStyleUnit_Calc <= mUnit && mUnit <= eStyleUnit_Calc_Maximum;
}
PRBool IsCoordPercentCalcUnit() const {
return mUnit == eStyleUnit_Coord ||
mUnit == eStyleUnit_Percent ||
IsCalcUnit();
}
// Does this calc() expression have any percentages inside it? Can be
// called only when IsCalcUnit() is true.
PRBool CalcHasPercent() const;
PRBool IsArrayValue() const {
return IsCalcUnit();
}

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

@ -1146,6 +1146,17 @@ nsChangeHint nsStylePosition::MaxDifference()
}
#endif
/* static */ PRBool
nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord)
{
return aCoord.GetUnit() == eStyleUnit_Auto ||
aCoord.GetUnit() == eStyleUnit_Percent ||
(aCoord.IsCalcUnit() && aCoord.CalcHasPercent()) ||
(aCoord.GetUnit() == eStyleUnit_Enumerated &&
(aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT ||
aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE));
}
// --------------------
// nsStyleTable
//

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

@ -1052,14 +1052,35 @@ struct nsStylePosition {
static PRBool ForceCompare() { return PR_TRUE; }
nsStyleSides mOffset; // [reset] coord, percent, auto
nsStyleCoord mWidth; // [reset] coord, percent, auto, enum
nsStyleCoord mWidth; // [reset] coord, percent, enum, auto
nsStyleCoord mMinWidth; // [reset] coord, percent, enum
nsStyleCoord mMaxWidth; // [reset] coord, percent, null, enum
nsStyleCoord mMaxWidth; // [reset] coord, percent, enum, none
nsStyleCoord mHeight; // [reset] coord, percent, auto
nsStyleCoord mMinHeight; // [reset] coord, percent
nsStyleCoord mMaxHeight; // [reset] coord, percent, null
nsStyleCoord mMaxHeight; // [reset] coord, percent, none
PRUint8 mBoxSizing; // [reset] see nsStyleConsts.h
nsStyleCoord mZIndex; // [reset] integer, auto
PRBool WidthDependsOnContainer() const
{ return WidthCoordDependsOnContainer(mWidth); }
PRBool MinWidthDependsOnContainer() const
{ return WidthCoordDependsOnContainer(mMinWidth); }
PRBool MaxWidthDependsOnContainer() const
{ return WidthCoordDependsOnContainer(mMaxWidth); }
PRBool HeightDependsOnContainer() const
{ return HeightCoordDependsOnContainer(mHeight); }
PRBool MinHeightDependsOnContainer() const
{ return HeightCoordDependsOnContainer(mMinHeight); }
PRBool MaxHeightDependsOnContainer() const
{ return HeightCoordDependsOnContainer(mMaxHeight); }
private:
static PRBool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
static PRBool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
{
return aCoord.GetUnit() == eStyleUnit_Auto || // CSS 2.1, 10.6.4, item (5)
aCoord.GetUnit() == eStyleUnit_Percent;
}
};
struct nsStyleTextReset {

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

@ -175,6 +175,7 @@ _TEST_FILES = test_acid3_test46.html \
test_transitions_per_property.html \
test_transitions_dynamic_changes.html \
test_transitions_bug537151.html \
test_unclosed_parentheses.html \
test_units_angle.html \
test_units_frequency.html \
test_units_length.html \

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

@ -1031,7 +1031,10 @@ var gCSSProperties = {
"-moz-repeating-radial-gradient(top left 99deg, cover, red, blue)",
"-moz-repeating-radial-gradient(15% 20% -1.2345rad, circle, red, blue)",
"-moz-repeating-radial-gradient(45px 399grad, ellipse closest-corner, red, blue)",
"-moz-repeating-radial-gradient(45px 399grad, farthest-side circle, red, blue)"
"-moz-repeating-radial-gradient(45px 399grad, farthest-side circle, red, blue)",
"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 2, 10, 10, 2)",
"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 10%, 50%, 30%, 0%)",
"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 10, 50%, 30%, 0)",
],
invalid_values: [
/* Old syntax */
@ -2138,8 +2141,8 @@ var gCSSProperties = {
domProp: "textShadow",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
prerequisites: { "color": "blue" },
initial_values: [ "none" ],
other_values: [ "2px 2px", "2px 2px 1px", "2px 2px green", "2px 2px 1px green", "green 2px 2px", "green 2px 2px 1px", "green 2px 2px, blue 1px 3px 4px", "currentColor 3px 3px", "blue 2px 2px, currentColor 1px 2px",
/* calc() values */
"2px 2px -moz-calc(-5px)", /* clamped */
@ -2211,8 +2214,8 @@ var gCSSProperties = {
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "ease", "cubic-bezier(0.25, 0.1, 0.25, 1.0)" ],
other_values: [ "linear", "ease-in", "ease-out", "ease-in-out", "linear, ease-in, cubic-bezier(0.1, 0.2, 0.8, 0.9)" ],
invalid_values: [ "none", "auto" ]
other_values: [ "linear", "ease-in", "ease-out", "ease-in-out", "linear, ease-in, cubic-bezier(0.1, 0.2, 0.8, 0.9)", "cubic-bezier(0.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.25, 1.5, 0.75, -0.5)" ],
invalid_values: [ "none", "auto", "cubic-bezier(0.25, 0.1, 0.25)", "cubic-bezier(0.25, 0.1, 0.25, 0.25, 1.0)", "cubic-bezier(-0.5, 0.5, 0.5, 0.5)", "cubic-bezier(1.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.5, 0.5, -0.5, 0.5)", "cubic-bezier(0.5, 0.5, 1.5, 0.5)" ]
},
"unicode-bidi": {
domProp: "unicodeBidi",
@ -2278,10 +2281,67 @@ var gCSSProperties = {
domProp: "width",
inherited: false,
type: CSS_TYPE_LONGHAND,
/* computed value tests for width test more with display:block */
prerequisites: { "display": "block" },
initial_values: [ " auto" ],
/* XXX these have prerequisites */
other_values: [ "15px", "3em", "15%", "-moz-max-content", "-moz-min-content", "-moz-fit-content", "-moz-available" ],
invalid_values: [ "none", "-2px" ]
other_values: [ "15px", "3em", "15%", "-moz-max-content", "-moz-min-content", "-moz-fit-content", "-moz-available",
/* valid calc() values */
"-moz-calc(-2px)",
"-moz-calc(2px)",
"-moz-calc(50%)",
"-moz-calc(50% + 2px)",
"-moz-calc( 50% + 2px)",
"-moz-calc(50% + 2px )",
"-moz-calc( 50% + 2px )",
"-moz-calc(50% - -2px)",
"-moz-calc(2px - -50%)",
"-moz-calc(3*25px)",
"-moz-calc(3 *25px)",
"-moz-calc(3 * 25px)",
"-moz-calc(3* 25px)",
"-moz-calc(25px*3)",
"-moz-calc(25px *3)",
"-moz-calc(25px* 3)",
"-moz-calc(25px * 3)",
"-moz-calc(3*25px + 50%)",
"-moz-calc(50% - 3em + 2px)",
"-moz-calc(50% - (3em + 2px))",
"-moz-calc((50% - 3em) + 2px)",
"-moz-min(50%, 30em)",
"-moz-calc(min(50%, 30em))",
"-moz-max(30em, 2px + 50%)",
"-moz-calc(max(30em, 2px + 50%))",
"-moz-min(30%, 30em,200px, min(500px ,40em))",
"-moz-calc(min(30%, 30em,200px, min(500px ,40em)))",
"-moz-min(50%)",
"-moz-max(20px)",
"-moz-calc(min(2em))",
"-moz-calc(max(50%))",
"-moz-calc(50px/2)",
"-moz-calc(50px/(2 - 1))"
],
invalid_values: [ "none", "-2px",
/* invalid calc() values */
"-moz-calc(50%+ 2px)",
"-moz-calc(50% +2px)",
"-moz-calc(50%+2px)",
"-moz-min()",
"-moz-calc(min())",
"-moz-max()",
"-moz-calc(max())",
"-moz-calc(50px/(2 - 2))",
/* If we ever support division by values, which is
* complicated for the reasons described in
* http://lists.w3.org/Archives/Public/www-style/2010Jan/0007.html
* , we should support all 4 of these as described in
* http://lists.w3.org/Archives/Public/www-style/2009Dec/0296.html
*/
"-moz-calc((3em / 100%) * 3em)",
"-moz-calc(3em / 100% * 3em)",
"-moz-calc(3em * (3em / 100%))",
"-moz-calc(3em * 3em / 100%)"
]
},
"word-spacing": {
domProp: "wordSpacing",

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

@ -8,6 +8,10 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="property_database.js"></script>
<style type="text/css" id="stylesheet"></style>
<style type="text/css">
/* For 'width', 'height', etc., need a constant size container. */
#display { width: 500px; height: 200px }
</style>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
@ -58,6 +62,9 @@ function setup_initial_values(id, ivalprop, prereqprop) {
window[ivalprop] = iframe.contentWindow.getComputedStyle(
iframe.contentDocument.documentElement.firstChild, "");
var sheet = iframe.contentDocument.styleSheets[0];
// For 'width', 'height', etc., need a constant size container.
sheet.insertRule(":root { height: 200px; width: 500px }", sheet.cssRules.length);
window[prereqprop] = sheet.cssRules[sheet.insertRule(":root > * {}", sheet.cssRules.length)];
}

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

@ -0,0 +1,158 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=575672
-->
<head>
<title>Test for Bug 575672</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<style type="text/css" id="style"></style>
<style type="text/css">
#display { position: relative }
</style>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=575672">Mozilla Bug 575672</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for unclosed parentheses in CSS values. **/
// Each of the following declarations should have a single missing ')'
// in the value.
var declarations = [
"content: url(",
"content: url( ",
"content: url(http://www.foo.com",
"content: url('http://www.foo.com'",
"background-image: -moz-linear-gradient(",
"background-image: -moz-linear-gradient( ",
"background-image: -moz-linear-gradient(red, blue",
"background-image: -moz-linear-gradient(red, yellow, blue",
"background-image: -moz-linear-gradient(red 1px, yellow 5px, blue 10px",
"background-image: -moz-linear-gradient(red, yellow, rgb(0, 0, 255)",
"background-image: -moz-repeating-linear-gradient(top left, red, blue",
"background-image: -moz-linear-gradient(top left, red, yellow, blue",
"background-image: -moz-linear-gradient(top left, red 1px, yellow 5px, blue 10px",
"background-image: -moz-linear-gradient(top left, red, yellow, rgb(0, 0, 255)",
"background-image: -moz-radial-gradient(",
"background-image: -moz-radial-gradient( ",
"background-image: -moz-radial-gradient(top left 45deg, red, blue",
"background-image: -moz-radial-gradient(cover, red, blue",
"background-image: -moz-repeating-radial-gradient(circle, red, blue",
"background-image: -moz-radial-gradient(ellipse closest-corner, red, hsl(240, 50%, 50%)",
"background-image: -moz-radial-gradient(farthest-side circle, red, blue",
"background-image: -moz-image-rect(",
"background-image: -moz-image-rect( ",
"background-image: -moz-image-rect(url(foo.jpg)",
"background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10",
"background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10 ",
"background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10,",
"background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, ",
"background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10",
"background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10 ",
"background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10,",
"background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10, ",
"color: rgb(",
"color: rgb( ",
"color: rgb(128, 0",
"color: rgb(128, 0, 128",
"color: rgb(128, 0, 128, 128",
"color: rgba(",
"color: rgba( ",
"color: rgba(128, 0",
"color: rgba(128, 0, 128",
"color: rgba(128, 0, 128, 1",
"color: rgba(128, 0, 128, 1, 1",
"color: hsl(",
"color: hsl( ",
"color: hsl(240, 50%",
"color: hsl(240, 50%, 50%",
"color: hsl(240, 50%, 50%, 50%",
"color: hsla(",
"color: hsla( ",
"color: hsla(240, 50%",
"color: hsla(240, 50%, 50%",
"color: hsla(240, 50%, 50%, 1",
"color: hsla(240, 50%, 50%, 1, 1",
"content: counter(",
"content: counter( ",
"content: counter(foo",
"content: counter(foo ",
"content: counter(foo,",
"content: counter(foo, ",
"content: counter(foo, upper-roman",
"content: counter(foo, upper-roman ",
"content: counter(foo, upper-roman,",
"content: counter(foo, upper-roman, ",
"content: counters(",
"content: counters( ",
"content: counters(foo, ','",
"content: counters(foo, ',' ",
"content: counters(foo, ',',",
"content: counters(foo, ',', ",
"content: counters(foo, ',', upper-roman",
"content: counters(foo, ',', upper-roman ",
"content: counters(foo, ',', upper-roman,",
"content: counters(foo, ',', upper-roman, ",
"content: attr(",
"content: attr( ",
"content: attr(href",
"content: attr(href ",
"content: attr(html",
"content: attr(html ",
"content: attr(html|",
"content: attr(html| ",
"content: attr(html|href",
"content: attr(html|href ",
"content: attr(|",
"content: attr(| ",
"content: attr(|href",
"content: attr(|href ",
"-moz-transition-timing-function: cubic-bezier(",
"-moz-transition-timing-function: cubic-bezier( ",
"-moz-transition-timing-function: cubic-bezier(0, 0, 1",
"-moz-transition-timing-function: cubic-bezier(0, 0, 1 ",
"-moz-transition-timing-function: cubic-bezier(0, 0, 1,",
"-moz-transition-timing-function: cubic-bezier(0, 0, 1, ",
"-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1",
"-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1 ",
"-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1,",
"-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1, ",
"border-top-width: -moz-calc(",
"border-top-width: -moz-calc( ",
"border-top-width: -moz-calc(2em",
"border-top-width: -moz-calc(2em ",
"border-top-width: -moz-calc(2em +",
"border-top-width: -moz-calc(2em + ",
"border-top-width: -moz-calc(2em *",
"border-top-width: -moz-calc(2em * ",
"border-top-width: -moz-calc((2em)",
"border-top-width: -moz-calc((2em) ",
];
var textNode = document.createTextNode("");
document.getElementById("style").appendChild(textNode);
var cs = getComputedStyle(document.getElementById("display"), "");
for (var i = 0; i < declarations.length; ++i) {
var sheet = "@namespace html url(http://www.w3.org/1999/xhtml);\n" +
"#display { color: green; " + declarations[i] +
" x x x x x x x ; color: red; ) ; z-index: " + (i + 1) + " }";
textNode.data = sheet;
is(cs.color, "rgb(0, 128, 0)",
"color for declaration '" + declarations[i] + "'");
is(cs.zIndex, i+1,
"z-index for declaration '" + declarations[i] + "'");
}
</script>
</pre>
</body>
</html>

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

@ -8,6 +8,10 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="property_database.js"></script>
<style type="text/css" id="stylesheet"></style>
<style type="text/css">
/* For 'width', 'height', etc., need a constant size container. */
#display { width: 500px; height: 200px }
</style>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
@ -79,6 +83,17 @@ function xfail_value(property, value, is_initial, has_frame) {
return false;
}
var gSwapInitialWhenHaveFrame = {
// When there's a frame, '-moz-available' works out to the same as
// 'auto' given the prerequisites of only 'display: block'.
"width": [ "-moz-available" ],
};
function swap_when_frame(property, value) {
return (property in gSwapInitialWhenHaveFrame) &&
gSwapInitialWhenHaveFrame[property].indexOf(value) != -1;
}
var gElementN = document.getElementById("elementn");
var gElementF = document.getElementById("elementf");
var gStyleSheet = document.getElementById("stylesheet").sheet;
@ -95,6 +110,9 @@ function setup_initial_values(id, ivalprop, prereqprop) {
window[ivalprop] = iframe.contentWindow.getComputedStyle(
iframe.contentDocument.documentElement.firstChild, "");
var sheet = iframe.contentDocument.styleSheets[0];
// For 'width', 'height', etc., need a constant size container.
sheet.insertRule(":root { height: 200px; width: 500px }", sheet.cssRules.length);
window[prereqprop] = sheet.cssRules[sheet.insertRule(":root > * {}", sheet.cssRules.length)];
}
@ -157,9 +175,11 @@ function test_value(property, val, is_initial)
(xfail_value(property, val, is_initial, false) ? todo_isnot : isnot)(
val_computed_n, initial_computed_n,
"should not get initial value for '" + property + ":" + val + "' on elementn.");
(xfail_value(property, val, is_initial, true) ? todo_isnot : isnot)(
var swap = swap_when_frame(property, val);
(xfail_value(property, val, is_initial, true) ? todo_isnot : (swap ? is : isnot))(
val_computed_f, initial_computed_f,
"should not get initial value for '" + property + ":" + val + "' on elementf.");
"should " + (swap ? "" : "not ") +
"get initial value for '" + property + ":" + val + "' on elementf.");
}
if (is_initial)
gRule1.style.removeProperty(property);

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

@ -470,13 +470,16 @@ static inline PRBool
DependsOnIntrinsicSize(const nsIFrame* aEmbeddingFrame)
{
const nsStylePosition *pos = aEmbeddingFrame->GetStylePosition();
nsStyleUnit widthUnit = pos->mWidth.GetUnit();
nsStyleUnit heightUnit = pos->mHeight.GetUnit();
const nsStyleCoord &width = pos->mWidth;
const nsStyleCoord &height = pos->mHeight;
// XXX it would be nice to know if the size of aEmbeddingFrame's containing
// block depends on aEmbeddingFrame, then we'd know if we can return false
// for eStyleUnit_Percent too.
return (widthUnit != eStyleUnit_Coord) || (heightUnit != eStyleUnit_Coord);
return (width.GetUnit() != eStyleUnit_Coord &&
(!width.IsCalcUnit() || width.CalcHasPercent())) ||
(height.GetUnit() != eStyleUnit_Coord &&
(!height.IsCalcUnit() || height.CalcHasPercent()));
}
NS_IMETHODIMP

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

@ -48,6 +48,8 @@
#include "nsGkAtoms.h"
#include "SpanningCellSorter.h"
namespace css = mozilla::css;
#undef DEBUG_TABLE_STRATEGY
BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aTableFrame)
@ -120,11 +122,15 @@ GetWidthInfo(nsIRenderingContext *aRenderingContext,
// XXXldb Should we consider -moz-box-sizing?
const nsStylePosition *stylePos = aFrame->GetStylePosition();
nsStyleUnit unit = stylePos->mWidth.GetUnit();
const nsStyleCoord &width = stylePos->mWidth;
nsStyleUnit unit = width.GetUnit();
// NOTE: We're ignoring calc() units here, for lack of a sensible
// idea for what to do with them. This means calc() is basically
// handled like 'auto' for table cells and columns.
if (unit == eStyleUnit_Coord) {
hasSpecifiedWidth = PR_TRUE;
nscoord w = nsLayoutUtils::ComputeWidthValue(aRenderingContext,
aFrame, 0, 0, 0, stylePos->mWidth);
aFrame, 0, 0, 0, width);
// Quirk: A cell with "nowrap" set and a coord value for the
// width which is bigger than the intrinsic minimum width uses
// that coord value as the minimum width.
@ -139,9 +145,9 @@ GetWidthInfo(nsIRenderingContext *aRenderingContext,
}
prefCoord = NS_MAX(w, minCoord);
} else if (unit == eStyleUnit_Percent) {
prefPercent = stylePos->mWidth.GetPercentValue();
prefPercent = width.GetPercentValue();
} else if (unit == eStyleUnit_Enumerated && aIsCell) {
switch (stylePos->mWidth.GetIntValue()) {
switch (width.GetIntValue()) {
case NS_STYLE_WIDTH_MAX_CONTENT:
// 'width' only affects pref width, not min
// width, so don't change anything

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

@ -105,7 +105,8 @@ FixedTableLayoutStrategy::GetMinWidth(nsIRenderingContext* aRenderingContext)
// do nothing
} else {
NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto ||
styleWidth->GetUnit() == eStyleUnit_Enumerated,
styleWidth->GetUnit() == eStyleUnit_Enumerated ||
styleWidth->IsCalcUnit(),
"bad width");
// The 'table-layout: fixed' algorithm considers only cells
@ -137,8 +138,8 @@ FixedTableLayoutStrategy::GetMinWidth(nsIRenderingContext* aRenderingContext)
result -= spacing * (colSpan - 1);
}
}
// else, for 'auto', '-moz-available', and '-moz-fit-content'
// do nothing
// else, for 'auto', '-moz-available', '-moz-fit-content',
// and 'calc()', do nothing
}
}
}
@ -251,7 +252,8 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
pctTotal += pct;
} else {
NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto ||
styleWidth->GetUnit() == eStyleUnit_Enumerated,
styleWidth->GetUnit() == eStyleUnit_Enumerated ||
styleWidth->IsCalcUnit(),
"bad width");
// The 'table-layout: fixed' algorithm considers only cells
@ -286,7 +288,8 @@ FixedTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt
colFrame->AddPrefPercent(pct);
pctTotal += pct;
} else {
// 'auto', '-moz-available', and '-moz-fit-content'
// 'auto', '-moz-available', '-moz-fit-content', and
// 'calc()'
colWidth = unassignedMarker;
}
if (colWidth != unassignedMarker) {

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

@ -679,9 +679,16 @@ nsIBox::AddCSSPrefSize(nsIBox* aBox, nsSize& aSize, PRBool &aWidthSet, PRBool &a
// (Handling the eStyleUnit_Enumerated types requires
// GetPrefSize/GetMinSize methods that don't consider
// (min-/max-/)(width/height) properties.)
if (position->mWidth.GetUnit() == eStyleUnit_Coord) {
aSize.width = position->mWidth.GetCoordValue();
const nsStyleCoord &width = position->mWidth;
if (width.GetUnit() == eStyleUnit_Coord) {
aSize.width = width.GetCoordValue();
aWidthSet = PR_TRUE;
} else if (width.IsCalcUnit()) {
if (!width.CalcHasPercent()) {
// pass 0 for percentage basis since we know there are no %s
aSize.width = nsRuleNode::ComputeComputedCalc(width, 0);
aWidthSet = PR_TRUE;
}
}
if (position->mHeight.GetUnit() == eStyleUnit_Coord) {

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

@ -2,27 +2,27 @@
# Images of various sizes.
== jpg-size-1x1.jpg jpg-size-1x1.png
fails-if(winWidget) == jpg-size-2x2.jpg jpg-size-2x2.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-2x2.jpg jpg-size-2x2.png
== jpg-size-3x3.jpg jpg-size-3x3.png
== jpg-size-4x4.jpg jpg-size-4x4.png
fails-if(winWidget) == jpg-size-5x5.jpg jpg-size-5x5.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-5x5.jpg jpg-size-5x5.png
== jpg-size-6x6.jpg jpg-size-6x6.png
fails-if(winWidget) == jpg-size-7x7.jpg jpg-size-7x7.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-7x7.jpg jpg-size-7x7.png
== jpg-size-8x8.jpg jpg-size-8x8.png
fails-if(winWidget) == jpg-size-9x9.jpg jpg-size-9x9.png
fails-if(winWidget) == jpg-size-15x15.jpg jpg-size-15x15.png
fails-if(winWidget) == jpg-size-16x16.jpg jpg-size-16x16.png
fails-if(winWidget) == jpg-size-17x17.jpg jpg-size-17x17.png
fails-if(winWidget) == jpg-size-31x31.jpg jpg-size-31x31.png
fails-if(winWidget) == jpg-size-32x32.jpg jpg-size-32x32.png
fails-if(winWidget) == jpg-size-33x33.jpg jpg-size-33x33.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-9x9.jpg jpg-size-9x9.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-15x15.jpg jpg-size-15x15.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-16x16.jpg jpg-size-16x16.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-17x17.jpg jpg-size-17x17.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-31x31.jpg jpg-size-31x31.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-32x32.jpg jpg-size-32x32.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-size-33x33.jpg jpg-size-33x33.png
# Progressive encoding
fails-if(winWidget) == jpg-progressive.jpg jpg-progressive.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-progressive.jpg jpg-progressive.png
# Grayscale colorspace
fails-if(winWidget) == jpg-gray.jpg jpg-gray.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-gray.jpg jpg-gray.png
# CMYK colorspace
fails-if(winWidget) == jpg-cmyk-1.jpg jpg-cmyk-1.png
fails-if(winWidget) == jpg-cmyk-2.jpg jpg-cmyk-2.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-cmyk-1.jpg jpg-cmyk-1.png
fails-if(xulRuntime.XPCOMABI=="x86-msvc") == jpg-cmyk-2.jpg jpg-cmyk-2.png
== jpg-srgb-icc.jpg jpg-srgb-icc.png
# webcam-simulacrum.mjpg is a hand-edited file containing red.jpg and blue.jpg,

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

@ -83,10 +83,6 @@ Tester.prototype = {
let msg = baseMsg.replace("{elt}", "tab") +
": " + lastTab.linkedBrowser.currentURI.spec;
this.currentTest.addResult(new testResult(false, msg, "", false));
if (gBrowser._removingTabs && gBrowser._removingTabs.indexOf(lastTab) > -1) {
gBrowser._endRemoveTab(lastTab);
continue;
}
gBrowser.removeTab(lastTab);
}
}

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

@ -14,8 +14,7 @@
*
* The Original Code is Mozilla Mobile Browser.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
@ -23,6 +22,7 @@
* Roy Frostig <rfrostig@mozilla.com>
* Ben Combee <bcombee@mozilla.com>
* Matt Brubeck <mbrubeck@mozilla.com>
* Benjamin Stover <bstover@mozilla.com>
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
*
* Alternatively, the contents of this file may be used under the terms of
@ -39,7 +39,7 @@
*
* ***** END LICENSE BLOCK ***** */
var EXPORTED_SYMBOLS = ["Point","Rect"];
let EXPORTED_SYMBOLS = ["Point", "Rect"];
/**
* Simple Point class.
@ -60,7 +60,7 @@ Point.prototype = {
this.y = y;
return this;
},
equals: function equals(x, y) {
return this.x == x && this.y == y;
},

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

@ -83,9 +83,9 @@ DIRS += tests
endif
EXTRA_JS_MODULES = \
Geometry.jsm \
InlineSpellChecker.jsm \
PopupNotifications.jsm \
Geometry.jsm \
$(NULL)
EXTRA_PP_JS_MODULES = \

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

@ -53,9 +53,9 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
$(warning browser_keyevents_during_autoscrolling.js disabled due to frequent timeouts (bug 567950)) \
browser_bug295977_autoscroll_overflow.js \
browser_Geometry.js \
browser_save_resend_postdata.js \
browser_Services.js \
browser_Geometry.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

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

@ -5692,8 +5692,11 @@ DirectoryInstallLocation.prototype = {
delete this._DirToIDMap[dir.path];
delete this._IDToDirMap[aId];
if (!dir.exists())
throw new Error("Attempt to uninstall unknown add-on " + aId);
if (!dir.exists()) {
WARN("Attempted to remove the directory for " + aId + " from " +
this._name + " but it was already gone");
return;
}
dir.remove(true);
},

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

@ -133,6 +133,7 @@ function notifyInitialized() {
}
function shutdown() {
gCategories.shutdown();
gSearchView.shutdown();
gEventManager.shutdown();
gViewController.shutdown();
@ -793,6 +794,7 @@ function getAddonsAndInstalls(aType, aCallback) {
var gCategories = {
node: null,
_search: null,
_maybeHidden: null,
initialize: function() {
this.node = document.getElementById("categories");
@ -820,13 +822,21 @@ var gCategories = {
}
}, false);
var maybeHidden = ["addons://list/locale", "addons://list/searchengine"];
gPendingInitializations += maybeHidden.length;
maybeHidden.forEach(function(aId) {
this._maybeHidden = ["addons://list/locale", "addons://list/searchengine"];
gPendingInitializations += this._maybeHidden.length;
this._maybeHidden.forEach(function(aId) {
var type = gViewController.parseViewId(aId).param;
getAddonsAndInstalls(type, function(aAddonsList, aInstallsList) {
var hidden = (aAddonsList.length == 0 && aInstallsList.length == 0);
var item = self.get(aId);
// Don't load view that is becoming hidden
if (hidden && aId == gViewController.currentViewId)
gViewController.loadView(VIEW_DEFAULT);
item.hidden = hidden;
if (aAddonsList.length > 0 || aInstallsList.length > 0) {
self.get(aId).hidden = false;
notifyInitialized();
return;
}
@ -861,6 +871,15 @@ var gCategories = {
});
},
shutdown: function() {
// Force persist of hidden state. See bug 15232
var self = this;
this._maybeHidden.forEach(function(aId) {
var item = self.get(aId);
item.setAttribute("hidden", !!item.hidden);
});
},
select: function(aId) {
if (this.node.selectedItem &&
this.node.selectedItem.value == aId)

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

@ -114,11 +114,13 @@
name="&view.discover.label;"/>
<richlistitem id="category-languages" value="addons://list/locale"
class="category"
name="&view.locales.label;" hidden="true"/>
name="&view.locales.label;"
hidden="true" persist="hidden"/>
<richlistitem id="category-searchengines"
value="addons://list/searchengine"
class="category"
name="&view.searchengines.label;" hidden="true"/>
name="&view.searchengines.label;"
hidden="true" persist="hidden"/>
<richlistitem id="category-extensions" value="addons://list/extension"
class="category"
name="&view.features.label;"/>

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

@ -53,6 +53,7 @@ _TEST_FILES = \
browser_bug562992.js \
browser_bug567137.js \
browser_bug572561.js \
browser_bug577990.js \
browser_dragdrop.js \
browser_searching.js \
browser_searching.xml \

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

@ -0,0 +1,127 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that the visible delay in showing the "Language" category occurs
// very minimally
var gManagerWindow;
var gCategoryUtilities;
var gProvider;
var gInstall;
var gInstallProperties = [{
name: "Locale Category Test",
type: "locale"
}];
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
open_manager(null, function(aWindow) {
gManagerWindow = aWindow;
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, finish);
}
function install_locale(aCallback) {
gInstall = gProvider.createInstalls(gInstallProperties)[0];
gInstall.addTestListener({
onInstallEnded: function(aInstall) {
gInstall.removeTestListener(this);
aCallback();
}
});
gInstall.install();
}
function check_hidden(aExpectedHidden) {
var hidden = !gCategoryUtilities.isTypeVisible("locale");
is(hidden, !!aExpectedHidden, "Should have correct hidden state");
}
function run_open_test(aTestSetup, aLoadHidden, aInitializedHidden, aSelected) {
function loadCallback(aManagerWindow) {
gManagerWindow = aManagerWindow;
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
check_hidden(aLoadHidden);
}
function run() {
open_manager(null, function() {
check_hidden(aInitializedHidden);
var selected = (gCategoryUtilities.selectedCategory == "locale");
is(selected, !!aSelected, "Should have correct selected state");
run_next_test();
}, loadCallback);
}
close_manager(gManagerWindow, function() {
// Allow for asynchronous functions to run before the manager opens
aTestSetup ? aTestSetup(run) : run();
});
}
// Tests that the locale category is hidden when there are no locales installed
add_test(function() {
run_open_test(null, true, true);
});
// Tests that installing a locale while the Add-on Manager is open shows the
// locale category
add_test(function() {
check_hidden(true);
install_locale(function() {
check_hidden(false);
run_next_test();
});
});
// Tests that the locale category is shown with no delay when restarting
// Add-on Manager
add_test(function() {
run_open_test(null, false, false);
});
// Tests that cancelling the locale install and restarting the Add-on Manager
// causes the locale category to be hidden with an acceptable delay
add_test(function() {
gInstall.cancel();
run_open_test(null, false, true)
});
// Tests that the locale category is hidden with no delay when restarting
// Add-on Manager
add_test(function() {
run_open_test(null, true, true);
});
// Tests that installing a locale when the Add-on Manager is closed, and then
// opening the Add-on Manager causes the locale category to be shown with an
// acceptable delay
add_test(function() {
run_open_test(install_locale, true, false);
});
// Tests that selection of the locale category persists
add_test(function() {
gCategoryUtilities.openType("locale", function() {
run_open_test(null, false, false, true);
});
});
// Tests that cancelling the locale install and restarting the Add-on Manager
// causes the locale category to be hidden and not selected
add_test(function() {
gInstall.cancel();
run_open_test(null, false, true);
});

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

@ -80,8 +80,11 @@ function wait_for_manager_load(aManagerWindow, aCallback) {
}, false);
}
function open_manager(aView, aCallback) {
function open_manager(aView, aCallback, aLoadCallback) {
function setup_manager(aManagerWindow) {
if (aLoadCallback)
aLoadCallback(aManagerWindow);
if (aView)
aManagerWindow.loadView(aView);
@ -119,8 +122,15 @@ function close_manager(aManagerWindow, aCallback) {
aManagerWindow.close();
}
function restart_manager(aManagerWindow, aView, aCallback) {
close_manager(aManagerWindow, function() { open_manager(aView, aCallback); });
function restart_manager(aManagerWindow, aView, aCallback, aLoadCallback) {
if (!aManagerWindow) {
open_manager(aView, aCallback, aLoadCallback);
return;
}
close_manager(aManagerWindow, function() {
open_manager(aView, aCallback, aLoadCallback);
});
}
function is_element_visible(aWindow, aElement, aExpected, aMsg) {

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

@ -0,0 +1,70 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that we recover gracefully from an extension directory disappearing
// when we were expecting to uninstall it.
var addon1 = {
id: "addon1@tests.mozilla.org",
version: "1.0",
name: "Test 1",
targetApplications: [{
id: "xpcshell@tests.mozilla.org",
minVersion: "1",
maxVersion: "1"
}]
};
var addon2 = {
id: "addon2@tests.mozilla.org",
version: "2.0",
name: "Test 2",
targetApplications: [{
id: "toolkit@mozilla.org",
minVersion: "1",
maxVersion: "1"
}]
};
const profileDir = gProfD.clone();
profileDir.append("extensions");
function run_test() {
do_test_pending();
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2");
var dest = profileDir.clone();
dest.append("addon1@tests.mozilla.org");
writeInstallRDFToDir(addon1, dest);
startupManager();
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
a1.uninstall();
shutdownManager();
var dest = profileDir.clone();
dest.append("addon1@tests.mozilla.org");
dest.remove(true);
dest = profileDir.clone();
dest.append("addon2@tests.mozilla.org");
writeInstallRDFToDir(addon2, dest);
startupManager();
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org"],
function([a1, a2]) {
// Addon1 should no longer be installed
do_check_eq(a1, null);
// Addon2 should have been detected
do_check_neq(a2, null);
do_test_finished();
});
});
}

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

@ -96,13 +96,13 @@ protected:
};
#define SET_FORMATETC(fe, cf, td, asp, li, med) \
{\
(fe).cfFormat=cf;\
(fe).ptd=td;\
(fe).dwAspect=asp;\
(fe).lindex=li;\
(fe).tymed=med;\
}
{\
(fe).cfFormat=cf;\
(fe).ptd=td;\
(fe).dwAspect=asp;\
(fe).lindex=li;\
(fe).tymed=med;\
}
#endif // nsClipboard_h__

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

@ -79,6 +79,9 @@
#include "nsTString.h"
#include "string-template-undef.h"
PR_STATIC_ASSERT(sizeof(PRUnichar) == 2);
PR_STATIC_ASSERT(sizeof(nsString::char_type) == 2);
PR_STATIC_ASSERT(sizeof(nsCString::char_type) == 1);
/**
* A helper class that converts a UTF-16 string to ASCII in a lossy manner