Merge mc->Maple

This commit is contained in:
Benoit Girard 2012-03-09 11:13:30 -05:00
commit fb79343e79
222 changed files with 4443 additions and 2077 deletions

1
aclocal.m4 vendored
View File

@ -18,6 +18,7 @@ builtin(include, build/autoconf/lto.m4)dnl
builtin(include, build/autoconf/gcc-pr49911.m4)dnl
builtin(include, build/autoconf/frameptr.m4)dnl
builtin(include, build/autoconf/compiler-opts.m4)dnl
builtin(include, build/autoconf/expandlibs.m4)dnl
MOZ_PROG_CHECKMSYS()

View File

@ -850,7 +850,7 @@ nsContextMenu.prototype = {
let uri = makeURI(this.mediaURL);
let url = uri.QueryInterface(Ci.nsIURL);
if (url.fileBaseName)
name = url.fileBaseName + ".jpg";
name = decodeURI(url.fileBaseName) + ".jpg";
} catch (e) { }
if (!name)
name = "snapshot.jpg";

View File

@ -20,6 +20,7 @@ _BROWSER_FILES = \
browser_newtab_reset.js \
browser_newtab_tabsync.js \
browser_newtab_unpin.js \
browser_newtab_bug722273.js \
browser_newtab_bug723102.js \
browser_newtab_bug723121.js \
head.js \

View File

@ -0,0 +1,62 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const NOW = Date.now() * 1000;
const URL = "http://fake-site.com/";
let tmp = {};
Cu.import("resource:///modules/NewTabUtils.jsm", tmp);
Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js", tmp);
let {NewTabUtils, Sanitizer} = tmp;
let bhist = Cc["@mozilla.org/browser/global-history;2"]
.getService(Ci.nsIBrowserHistory);
function runTests() {
clearHistory();
fillHistory();
yield addNewTabPageTab();
is(cells[0].site.url, URL, "first site is our fake site");
let page = {
update: function () {
executeSoon(TestRunner.next);
},
observe: function () {}
};
NewTabUtils.allPages.register(page);
yield clearHistory();
NewTabUtils.allPages.unregister(page);
ok(!cells[0].site, "the fake site is gone");
}
function fillHistory() {
let uri = makeURI(URL);
for (let i = 59; i > 0; i--)
bhist.addPageWithDetails(uri, "fake site", NOW - i * 60 * 1000000);
}
function clearHistory() {
let s = new Sanitizer();
s.prefDomain = "privacy.cpd.";
let prefs = gPrefService.getBranch(s.prefDomain);
prefs.setBoolPref("history", true);
prefs.setBoolPref("downloads", false);
prefs.setBoolPref("cache", false);
prefs.setBoolPref("cookies", false);
prefs.setBoolPref("formdata", false);
prefs.setBoolPref("offlineApps", false);
prefs.setBoolPref("passwords", false);
prefs.setBoolPref("sessions", false);
prefs.setBoolPref("siteSettings", false);
s.sanitize();
}

View File

@ -129,10 +129,11 @@ function addNewTabPageTab() {
cw = browser.contentWindow;
if (NewTabUtils.allPages.enabled) {
cells = cw.gGrid.cells;
// Continue when the link cache has been populated.
NewTabUtils.links.populateCache(TestRunner.next);
NewTabUtils.links.populateCache(function () {
cells = cw.gGrid.cells;
executeSoon(TestRunner.next);
});
} else {
TestRunner.next();
}
@ -246,6 +247,8 @@ function unpinCell(aCell) {
*/
function simulateDrop(aDropTarget, aDragSource) {
let event = {
clientX: 0,
clientY: 0,
dataTransfer: {
mozUserCancelled: false,
setData: function () null,

View File

@ -47,20 +47,6 @@
white-space: pre-wrap;
}
#technicalContent > h2, #expertContent > h2 {
cursor: pointer;
-moz-padding-start: 20px;
position: relative;
left: -20px;
}
body[dir="rtl"] #technicalContent > h2,
body[dir="rtl"] #expertContent > h2 {
left: auto;
right: -20px;
}
div[collapsed] > p,
div[collapsed] > div {
.expander[collapsed] + * {
display: none;
}

View File

@ -260,18 +260,18 @@
<!-- The following sections can be unhidden by default by setting the
"browser.xul.error_pages.expert_bad_cert" pref to true -->
<div id="technicalContent" collapsed="true">
<h2 onclick="toggle('technicalContent');" id="technicalContentHeading">&certerror.technical.heading;</h2>
<p id="technicalContentText"/>
</div>
<h2 id="technicalContent" class="expander" collapsed="true">
<button onclick="toggle('technicalContent');">&certerror.technical.heading;</button>
</h2>
<p id="technicalContentText"/>
<div id="expertContent" collapsed="true">
<h2 onclick="toggle('expertContent');" id="expertContentHeading">&certerror.expert.heading;</h2>
<div>
<p>&certerror.expert.content;</p>
<p>&certerror.expert.contentPara2;</p>
<button id='exceptionDialogButton'>&certerror.addException.label;</button>
</div>
<h2 id="expertContent" class="expander" collapsed="true">
<button onclick="toggle('expertContent');">&certerror.expert.heading;</button>
</h2>
<div>
<p>&certerror.expert.content;</p>
<p>&certerror.expert.contentPara2;</p>
<button id='exceptionDialogButton'>&certerror.addException.label;</button>
</div>
</div>
</div>

View File

@ -56,6 +56,7 @@
#include "nsServiceManagerUtils.h"
#include "nsStringAPI.h"
#include "nsXULAppAPI.h"
#include "nsIPrefLocalizedString.h"
namespace mozilla {
namespace browser {
@ -200,7 +201,18 @@ AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array)
localePlugins->AppendNative(NS_LITERAL_CSTRING("locale"));
nsCString locale;
rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale));
nsCOMPtr<nsIPrefLocalizedString> prefString;
rv = prefs->GetComplexValue("general.useragent.locale",
NS_GET_IID(nsIPrefLocalizedString),
getter_AddRefs(prefString));
if (NS_SUCCEEDED(rv)) {
nsAutoString wLocale;
prefString->GetData(getter_Copies(wLocale));
CopyUTF16toUTF8(wLocale, locale);
} else {
rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale));
}
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIFile> curLocalePlugins;

View File

@ -657,7 +657,9 @@ PlacesViewBase.prototype = {
aPlacesNode._siteURI = aLivemark.siteURI;
if (aNewState == Ci.nsINavHistoryContainerResultNode.STATE_OPENED) {
aLivemark.registerForUpdates(aPlacesNode, this);
// Prioritize the current livemark.
aLivemark.reload();
PlacesUtils.livemarks.reloadLivemarks();
if (shouldInvalidate)
this.invalidateContainer(aPlacesNode);
}
@ -900,11 +902,6 @@ PlacesToolbar.prototype = {
__proto__: PlacesViewBase.prototype,
_cbEvents: ["dragstart", "dragover", "dragexit", "dragend", "drop",
#ifdef XP_UNIX
#ifndef XP_MACOSX
"mousedown", "mouseup",
#endif
#endif
"mousemove", "mouseover", "mouseout"],
QueryInterface: function PT_QueryInterface(aIID) {
@ -1101,16 +1098,6 @@ PlacesToolbar.prototype = {
case "mouseout":
this._onMouseOut(aEvent);
break;
#ifdef XP_UNIX
#ifndef XP_MACOSX
case "mouseup":
this._onMouseUp(aEvent);
break;
case "mousedown":
this._onMouseDown(aEvent);
break;
#endif
#endif
case "popupshowing":
this._onPopupShowing(aEvent);
break;
@ -1538,14 +1525,6 @@ PlacesToolbar.prototype = {
draggedElt.getAttribute("type") == "menu") {
// If the drag gesture on a container is toward down we open instead
// of dragging.
#ifdef XP_UNIX
#ifndef XP_MACOSX
if (this._mouseDownTimer) {
this._mouseDownTimer.cancel();
this._mouseDownTimer = null;
}
#endif
#endif
let translateY = this._cachedMouseMoveEvent.clientY - aEvent.clientY;
let translateX = this._cachedMouseMoveEvent.clientX - aEvent.clientX;
if ((translateY) >= Math.abs(translateX/2)) {
@ -1718,47 +1697,6 @@ PlacesToolbar.prototype = {
}
},
#ifdef XP_UNIX
#ifndef XP_MACOSX
_onMouseDown: function PT__onMouseDown(aEvent) {
let target = aEvent.target;
if (aEvent.button == 0 &&
target.localName == "toolbarbutton" &&
target.getAttribute("type") == "menu") {
this._allowPopupShowing = false;
// On Linux we can open the popup only after a delay.
// Indeed as soon as the menupopup opens we are unable to start a
// drag aEvent. See bug 500081 for details.
this._mouseDownTimer = Cc["@mozilla.org/timer;1"].
createInstance(Ci.nsITimer);
let callback = {
_self: this,
_target: target,
notify: function(timer) {
this._target.open = true;
this._mouseDownTimer = null;
}
};
this._mouseDownTimer.initWithCallback(callback, 300,
Ci.nsITimer.TYPE_ONE_SHOT);
}
},
_onMouseUp: function PT__onMouseUp(aEvent) {
if (aEvent.button != 0)
return;
if (this._mouseDownTimer) {
// On a click (down/up), we should open the menu popup.
this._mouseDownTimer.cancel();
this._mouseDownTimer = null;
aEvent.target.open = true;
}
},
#endif
#endif
_onMouseMove: function PT__onMouseMove(aEvent) {
// Used in dragStart to prevent dragging folders when dragging down.
this._cachedMouseMoveEvent = aEvent;

View File

@ -90,7 +90,6 @@
observes="paneElementsBroadcaster"/>
<textbox id="editBMPanel_feedLocationField"
class="uri-element"
onblur="gEditItemOverlay.onFeedLocationFieldBlur();"
observes="paneElementsBroadcaster"/>
</row>
@ -102,7 +101,6 @@
observes="paneElementsBroadcaster"/>
<textbox id="editBMPanel_siteLocationField"
class="uri-element"
onblur="gEditItemOverlay.onSiteLocationFieldBlur();"
observes="paneElementsBroadcaster"/>
</row>

View File

@ -896,7 +896,9 @@ PlacesTreeView.prototype = {
aNode._feedURI = aLivemark.feedURI;
if (aNewState == Components.interfaces.nsINavHistoryContainerResultNode.STATE_OPENED) {
aLivemark.registerForUpdates(aNode, this);
// Prioritize the current livemark.
aLivemark.reload();
PlacesUtils.livemarks.reloadLivemarks();
if (shouldInvalidate)
this.invalidateContainer(aNode);
}

View File

@ -732,8 +732,26 @@ CssRuleView.prototype = {
}.bind(this);
this._createEditors();
// When creating a new property, we fake the normal property
// editor behavior (focusing a property's value after entering its
// name) by responding to the name's blur event, creating the
// value editor, and grabbing focus to the value editor. But if
// focus has already moved to another document, we won't be able
// to move focus to the new editor.
// Create a focusable item at the end of the editors to catch these
// cases.
this._focusBackstop = createChild(this.element, "div", {
tabindex: 0,
});
this._backstopHandler = function() {
// If this item is actually focused long enough to get the focus
// event, allow focus to move on out of this document.
moveFocus(this.doc.defaultView, FOCUS_FORWARD);
}.bind(this);
this._focusBackstop.addEventListener("focus", this._backstopHandler, false);
},
/**
* Update the rules for the currently highlighted element.
*/
@ -762,6 +780,12 @@ CssRuleView.prototype = {
this._clearRules();
this._viewedElement = null;
this._elementStyle = null;
if (this._focusBackstop) {
this._focusBackstop.removeEventListener("focus", this._backstopHandler, false);
this._backstopHandler = null;
this._focusBackstop = null;
}
},
/**
@ -845,7 +869,6 @@ RuleEditor.prototype = {
this.openBrace = createChild(header, "span", {
class: "ruleview-ruleopen",
tabindex: "0",
textContent: " {"
});

View File

@ -60,6 +60,7 @@ _BROWSER_TEST_FILES = \
browser_ruleview_manipulation.js \
browser_ruleview_override.js \
browser_ruleview_ui.js \
browser_ruleview_focus.js \
browser_bug705707_is_content_stylesheet.js \
browser_bug722196_property_view_media_queries.js \
browser_bug722196_rule_view_media_queries.js \

View File

@ -0,0 +1,106 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that focus doesn't leave the style editor when adding a property
// (bug 719916)
let doc;
let stylePanel;
function waitForRuleView(aCallback)
{
if (InspectorUI.ruleView) {
aCallback();
return;
}
let ruleViewFrame = InspectorUI.getToolIframe(InspectorUI.ruleViewObject);
ruleViewFrame.addEventListener("load", function(evt) {
ruleViewFrame.removeEventListener(evt.type, arguments.callee, true);
executeSoon(function() {
aCallback();
});
}, true);
}
function waitForEditorFocus(aParent, aCallback)
{
aParent.addEventListener("focus", function onFocus(evt) {
if (evt.target.inplaceEditor) {
aParent.removeEventListener("focus", onFocus, true);
let editor = evt.target.inplaceEditor;
executeSoon(function() {
aCallback(editor);
});
}
}, true);
}
function openRuleView()
{
Services.obs.addObserver(function onOpened() {
Services.obs.removeObserver(onOpened,
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
// Highlight a node.
let node = content.document.getElementsByTagName("h1")[0];
InspectorUI.inspectNode(node);
InspectorUI.stopInspecting();
// Open the rule view sidebar.
waitForRuleView(testFocus);
InspectorUI.showSidebar();
InspectorUI.ruleButton.click();
testFocus();
}, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
InspectorUI.openInspectorUI();
}
function testFocus()
{
let ruleViewFrame = InspectorUI.getToolIframe(InspectorUI.ruleViewObject);
let brace = ruleViewFrame.contentDocument.querySelectorAll(".ruleview-ruleclose")[0];
waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
aEditor.input.value = "color";
waitForEditorFocus(brace.parentNode, function onEditingValue(aEditor) {
// If we actually get this focus we're ok.
ok(true, "We got focus.");
aEditor.input.value = "green";
// If we've retained focus, pressing return will start a new editor.
// If not, we'll wait here until we time out.
waitForEditorFocus(brace.parentNode, function onNewEditor(aEditor) {
aEditor.input.blur();
finishTest();
});
EventUtils.sendKey("return");
});
EventUtils.sendKey("return");
});
brace.focus();
}
function finishUp()
{
doc = stylePanel = null;
gBrowser.removeCurrentTab();
finish();
}
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
doc = content.document;
doc.title = "Rule View Test";
waitForFocus(openRuleView, content);
}, true);
content.location = "data:text/html,<h1>Some header text</h1>";
}

View File

@ -121,8 +121,6 @@ let Storage = {
// want any data from private browsing to show up.
PinnedLinks.resetCache();
BlockedLinks.resetCache();
Pages.update();
}
},
@ -187,11 +185,6 @@ let AllPages = {
*/
_pages: [],
/**
* Tells whether we already added a preference observer.
*/
_observing: false,
/**
* Cached value that tells whether the New Tab Page feature is enabled.
*/
@ -203,12 +196,7 @@ let AllPages = {
*/
register: function AllPages_register(aPage) {
this._pages.push(aPage);
// Add the preference observer if we haven't already.
if (!this._observing) {
this._observing = true;
Services.prefs.addObserver(PREF_NEWTAB_ENABLED, this, true);
}
this._addObserver();
},
/**
@ -238,6 +226,14 @@ let AllPages = {
Services.prefs.setBoolPref(PREF_NEWTAB_ENABLED, !!aEnabled);
},
/**
* Returns the number of registered New Tab Pages (i.e. the number of open
* about:newtab instances).
*/
get length() {
return this._pages.length;
},
/**
* Updates all currently active pages but the given one.
* @param aExceptPage The page to exclude from updating.
@ -264,6 +260,15 @@ let AllPages = {
}, this);
},
/**
* Adds a preference observer and turns itself into a no-op after the first
* invokation.
*/
_addObserver: function AllPages_addObserver() {
Services.prefs.addObserver(PREF_NEWTAB_ENABLED, this, true);
this._addObserver = function () {};
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference])
};
@ -512,6 +517,8 @@ let Links = {
this._links = aLinks;
executeCallbacks();
}.bind(this));
this._addObserver();
}
},
@ -544,7 +551,32 @@ let Links = {
*/
resetCache: function Links_resetCache() {
this._links = [];
}
},
/**
* Implements the nsIObserver interface to get notified about browser history
* sanitization.
*/
observe: function Links_observe(aSubject, aTopic, aData) {
// Make sure to update open about:newtab instances. If there are no opened
// pages we can just wait for the next new tab to populate the cache again.
if (AllPages.length && AllPages.enabled)
this.populateCache(function () { AllPages.update() }, true);
else
this._links = null;
},
/**
* Adds a sanitization observer and turns itself into a no-op after the first
* invokation.
*/
_addObserver: function Links_addObserver() {
Services.obs.addObserver(this, "browser:purge-session-history", true);
this._addObserver = function () {};
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference])
};
/**

View File

@ -86,21 +86,24 @@ body[dir="rtl"] #errorPageContainer {
-moz-margin-start: 80px;
}
#technicalContent > h2, #expertContent > h2 {
background : url("chrome://browser/skin/section_expanded.png") left 0 no-repeat;
.expander > button {
-moz-padding-start: 20px;
-moz-margin-start: -20px;
background: url("chrome://browser/skin/aboutCertError_sectionExpanded.png") left center no-repeat;
border: none;
font: inherit;
color: inherit;
cursor: pointer;
}
body[dir="rtl"] #technicalContent > h2,
body[dir="rtl"] #expertContent > h2 {
background-position: right 0;
body[dir="rtl"] .expander > button {
background-position: right center;
}
#technicalContent[collapsed] > h2,
#expertContent[collapsed] > h2{
background-image: url("chrome://browser/skin/section_collapsed.png");
.expander[collapsed] > button {
background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed.png");
}
body[dir="rtl"] #technicalContent[collapsed] > h2,
body[dir="rtl"] #expertContent[collapsed] > h2 {
background-image: url("chrome://browser/skin/section_collapsed-rtl.png");
body[dir="rtl"] .expander[collapsed] > button {
background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed-rtl.png");
}

View File

Before

Width:  |  Height:  |  Size: 791 B

After

Width:  |  Height:  |  Size: 791 B

View File

Before

Width:  |  Height:  |  Size: 776 B

After

Width:  |  Height:  |  Size: 776 B

View File

Before

Width:  |  Height:  |  Size: 767 B

After

Width:  |  Height:  |  Size: 767 B

View File

@ -1,8 +0,0 @@
#close {
position: absolute;
top: 0;
right: 0;
width: 32px;
height: 32px;
background: url(KUI-close.png) center center no-repeat;
}

View File

@ -5,14 +5,16 @@ browser.jar:
* skin/classic/browser/aboutPrivateBrowsing.css (aboutPrivateBrowsing.css)
* skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css)
skin/classic/browser/aboutSessionRestore-window-icon.png
skin/classic/browser/aboutCertError.css (aboutCertError.css)
skin/classic/browser/aboutCertError.css
skin/classic/browser/aboutCertError_sectionCollapsed.png
skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png
skin/classic/browser/aboutCertError_sectionExpanded.png
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/aboutSyncTabs.css
#endif
skin/classic/browser/actionicon-tab.png
* skin/classic/browser/browser.css (browser.css)
* skin/classic/browser/engineManager.css (engineManager.css)
skin/classic/browser/fullscreen-video.css
skin/classic/browser/Geolocation-16.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/Go-arrow.png
@ -27,9 +29,6 @@ browser.jar:
skin/classic/browser/Privacy-16.png
skin/classic/browser/Privacy-48.png
skin/classic/browser/searchbar.css (searchbar.css)
skin/classic/browser/section_collapsed.png
skin/classic/browser/section_collapsed-rtl.png
skin/classic/browser/section_expanded.png
skin/classic/browser/Secure.png
skin/classic/browser/Security-broken.png
skin/classic/browser/setDesktopBackground.css

View File

@ -86,21 +86,24 @@ body[dir="rtl"] #errorPageContainer {
-moz-margin-start: 80px;
}
#technicalContent > h2, #expertContent > h2 {
background : url("chrome://browser/skin/section_expanded.png") left 0 no-repeat;
.expander > button {
-moz-padding-start: 20px;
-moz-margin-start: -20px;
background: url("chrome://browser/skin/aboutCertError_sectionExpanded.png") left center no-repeat;
border: none;
font: inherit;
color: inherit;
cursor: pointer;
}
body[dir="rtl"] #technicalContent > h2,
body[dir="rtl"] #expertContent > h2 {
background-position: right 0;
body[dir="rtl"] .expander > button {
background-position: right center;
}
#technicalContent[collapsed] > h2,
#expertContent[collapsed] > h2{
background-image: url("chrome://browser/skin/section_collapsed.png");
.expander[collapsed] > button {
background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed.png");
}
body[dir="rtl"] #technicalContent[collapsed] > h2,
body[dir="rtl"] #expertContent[collapsed] > h2 {
background-image: url("chrome://browser/skin/section_collapsed-rtl.png");
body[dir="rtl"] .expander[collapsed] > button {
background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed-rtl.png");
}

View File

Before

Width:  |  Height:  |  Size: 791 B

After

Width:  |  Height:  |  Size: 791 B

View File

Before

Width:  |  Height:  |  Size: 776 B

After

Width:  |  Height:  |  Size: 776 B

View File

Before

Width:  |  Height:  |  Size: 767 B

After

Width:  |  Height:  |  Size: 767 B

View File

@ -1,8 +0,0 @@
#close {
position: absolute;
top: 0;
left: 0;
width: 32px;
height: 32px;
background: url(KUI-close.png) center center no-repeat;
}

View File

@ -4,14 +4,16 @@ browser.jar:
* skin/classic/browser/aboutPrivateBrowsing.css (aboutPrivateBrowsing.css)
* skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css)
skin/classic/browser/aboutSessionRestore-window-icon.png
skin/classic/browser/aboutCertError.css (aboutCertError.css)
skin/classic/browser/aboutCertError.css
skin/classic/browser/aboutCertError_sectionCollapsed.png
skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png
skin/classic/browser/aboutCertError_sectionExpanded.png
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/aboutSyncTabs.css
#endif
skin/classic/browser/actionicon-tab.png
* skin/classic/browser/browser.css (browser.css)
* skin/classic/browser/engineManager.css (engineManager.css)
skin/classic/browser/fullscreen-video.css
skin/classic/browser/Geolocation-16.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/home.png
@ -36,9 +38,6 @@ browser.jar:
skin/classic/browser/searchbar-dropmarker.png
skin/classic/browser/searchbar.css
skin/classic/browser/Search.png
skin/classic/browser/section_collapsed.png
skin/classic/browser/section_collapsed-rtl.png
skin/classic/browser/section_expanded.png
skin/classic/browser/Secure-Glyph-White.png
skin/classic/browser/keyhole-circle.png
skin/classic/browser/Toolbar.png

View File

@ -86,21 +86,24 @@ body[dir="rtl"] #errorPageContainer {
-moz-margin-start: 80px;
}
#technicalContent > h2, #expertContent > h2 {
background : url("chrome://browser/skin/section_expanded.png") left center no-repeat;
.expander > button {
-moz-padding-start: 20px;
-moz-margin-start: -20px;
background: url("chrome://browser/skin/aboutCertError_sectionExpanded.png") left center no-repeat;
border: none;
font: inherit;
color: inherit;
cursor: pointer;
}
body[dir="rtl"] #technicalContent > h2,
body[dir="rtl"] #expertContent > h2 {
body[dir="rtl"] .expander > button {
background-position: right center;
}
#technicalContent[collapsed] > h2,
#expertContent[collapsed] > h2{
background-image: url("chrome://browser/skin/section_collapsed.png");
.expander[collapsed] > button {
background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed.png");
}
body[dir="rtl"] #technicalContent[collapsed] > h2,
body[dir="rtl"] #expertContent[collapsed] > h2 {
background-image: url("chrome://browser/skin/section_collapsed-rtl.png");
body[dir="rtl"] .expander[collapsed] > button {
background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed-rtl.png");
}

View File

Before

Width:  |  Height:  |  Size: 791 B

After

Width:  |  Height:  |  Size: 791 B

View File

Before

Width:  |  Height:  |  Size: 776 B

After

Width:  |  Height:  |  Size: 776 B

View File

Before

Width:  |  Height:  |  Size: 767 B

After

Width:  |  Height:  |  Size: 767 B

View File

@ -1,8 +0,0 @@
#close {
position: absolute;
top: 0;
right: 0;
width: 32px;
height: 32px;
background: url(KUI-close.png) center center no-repeat;
}

View File

@ -7,7 +7,10 @@ browser.jar:
* skin/classic/browser/aboutPrivateBrowsing.css (aboutPrivateBrowsing.css)
* skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css)
skin/classic/browser/aboutSessionRestore-window-icon.png (preferences/application.png)
skin/classic/browser/aboutCertError.css (aboutCertError.css)
skin/classic/browser/aboutCertError.css
skin/classic/browser/aboutCertError_sectionCollapsed.png
skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png
skin/classic/browser/aboutCertError_sectionExpanded.png
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/aboutSyncTabs.css
#endif
@ -16,7 +19,6 @@ browser.jar:
skin/classic/browser/appmenu-dropmarker.png
* skin/classic/browser/browser.css (browser.css)
* skin/classic/browser/engineManager.css (engineManager.css)
skin/classic/browser/fullscreen-video.css
skin/classic/browser/Geolocation-16.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/Info.png (Info.png)
@ -38,9 +40,6 @@ browser.jar:
skin/classic/browser/toolbarbutton-dropdown-arrow-inverted.png
* skin/classic/browser/searchbar.css (searchbar.css)
skin/classic/browser/searchbar-dropdown-arrow.png
skin/classic/browser/section_collapsed.png
skin/classic/browser/section_collapsed-rtl.png
skin/classic/browser/section_expanded.png
skin/classic/browser/setDesktopBackground.css
skin/classic/browser/menu-back.png (menu-back.png)
skin/classic/browser/menu-forward.png (menu-forward.png)
@ -177,7 +176,10 @@ browser.jar:
* skin/classic/aero/browser/aboutPrivateBrowsing.css (aboutPrivateBrowsing.css)
* skin/classic/aero/browser/aboutSessionRestore.css (aboutSessionRestore.css)
skin/classic/aero/browser/aboutSessionRestore-window-icon.png (aboutSessionRestore-window-icon-aero.png)
skin/classic/aero/browser/aboutCertError.css (aboutCertError.css)
skin/classic/aero/browser/aboutCertError.css
skin/classic/aero/browser/aboutCertError_sectionCollapsed.png
skin/classic/aero/browser/aboutCertError_sectionCollapsed-rtl.png
skin/classic/aero/browser/aboutCertError_sectionExpanded.png
#ifdef MOZ_SERVICES_SYNC
skin/classic/aero/browser/aboutSyncTabs.css
#endif
@ -186,7 +188,6 @@ browser.jar:
skin/classic/aero/browser/appmenu-icons.png
* skin/classic/aero/browser/browser.css (browser-aero.css)
* skin/classic/aero/browser/engineManager.css (engineManager.css)
skin/classic/aero/browser/fullscreen-video.css
skin/classic/aero/browser/Geolocation-16.png
skin/classic/aero/browser/Geolocation-64.png
skin/classic/aero/browser/Info.png (Info-aero.png)
@ -208,9 +209,6 @@ browser.jar:
skin/classic/aero/browser/toolbarbutton-dropdown-arrow-inverted.png
* skin/classic/aero/browser/searchbar.css (searchbar.css)
skin/classic/aero/browser/searchbar-dropdown-arrow.png (searchbar-dropdown-arrow-aero.png)
skin/classic/aero/browser/section_collapsed.png
skin/classic/aero/browser/section_collapsed-rtl.png
skin/classic/aero/browser/section_expanded.png
skin/classic/aero/browser/setDesktopBackground.css
skin/classic/aero/browser/menu-back.png (menu-back-aero.png)
skin/classic/aero/browser/menu-forward.png (menu-forward-aero.png)

View File

@ -9,5 +9,76 @@ if test "$CLANG_CXX"; then
## from C.
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage"
fi
])
if test "$GNU_CC"; then
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
fi
dnl ========================================================
dnl = Identical Code Folding
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(icf,
[ --disable-icf Disable Identical Code Folding],
MOZ_DISABLE_ICF=1,
MOZ_DISABLE_ICF= )
if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$MOZ_DISABLE_ICF"; then
AC_CACHE_CHECK([whether the linker supports Identical Code Folding],
LD_SUPPORTS_ICF,
[echo 'int foo() {return 42;}' \
'int bar() {return 42;}' \
'int main() {return foo() - bar();}' > conftest.${ac_ext}
# If the linker supports ICF, foo and bar symbols will have
# the same address
if AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS -Wl,--icf=safe -ffunction-sections conftest.${ac_ext} $LIBS 1>&2]) &&
test -s conftest${ac_exeext} &&
objdump -t conftest${ac_exeext} | awk changequote(<<, >>)'{a[<<$>>6] = <<$>>1} END {if (a["foo"] && (a["foo"] != a["bar"])) { exit 1 }}'changequote([, ]); then
LD_SUPPORTS_ICF=yes
else
LD_SUPPORTS_ICF=no
fi
rm -rf conftest*])
if test "$LD_SUPPORTS_ICF" = yes; then
_SAVE_LDFLAGS="$LDFLAGS -Wl,--icf=safe"
LDFLAGS="$LDFLAGS -Wl,--icf=safe -Wl,--print-icf-sections"
AC_TRY_LINK([], [],
[LD_PRINT_ICF_SECTIONS=-Wl,--print-icf-sections],
[LD_PRINT_ICF_SECTIONS=])
AC_SUBST([LD_PRINT_ICF_SECTIONS])
LDFLAGS="$_SAVE_LDFLAGS"
fi
fi
dnl ========================================================
dnl = Automatically remove dead symbols
dnl ========================================================
if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -n "$MOZ_DEBUG_FLAGS"; then
dnl See bug 670659
AC_CACHE_CHECK([whether removing dead symbols breaks debugging],
GC_SECTIONS_BREAKS_DEBUG_RANGES,
[echo 'int foo() {return 42;}' \
'int bar() {return 1;}' \
'int main() {return foo();}' > conftest.${ac_ext}
if AC_TRY_COMMAND([${CC-cc} -o conftest.${ac_objext} $CFLAGS $MOZ_DEBUG_FLAGS -c conftest.${ac_ext} 1>&2]) &&
AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS $MOZ_DEBUG_FLAGS -Wl,--gc-sections conftest.${ac_objext} $LIBS 1>&2]) &&
test -s conftest${ac_exeext} -a -s conftest.${ac_objext}; then
if test "`$PYTHON "$_topsrcdir"/build/autoconf/check_debug_ranges.py conftest.${ac_objext} conftest.${ac_ext}`" = \
"`$PYTHON "$_topsrcdir"/build/autoconf/check_debug_ranges.py conftest${ac_exeext} conftest.${ac_ext}`"; then
GC_SECTIONS_BREAKS_DEBUG_RANGES=no
else
GC_SECTIONS_BREAKS_DEBUG_RANGES=yes
fi
else
dnl We really don't expect to get here, but just in case
GC_SECTIONS_BREAKS_DEBUG_RANGES="no, but it's broken in some other way"
fi
rm -rf conftest*])
if test "$GC_SECTIONS_BREAKS_DEBUG_RANGES" = no; then
DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections"
fi
fi
])

View File

@ -0,0 +1,56 @@
AC_DEFUN([MOZ_EXPAND_LIBS],
[
dnl ========================================================
dnl =
dnl = Check what kind of list files are supported by the
dnl = linker
dnl =
dnl ========================================================
AC_CACHE_CHECK(what kind of list files are supported by the linker,
EXPAND_LIBS_LIST_STYLE,
[echo "int main() {return 0;}" > conftest.${ac_ext}
if AC_TRY_COMMAND(${CC-cc} -o conftest.${OBJ_SUFFIX} -c $CFLAGS $CPPFLAGS conftest.${ac_ext} 1>&5) && test -s conftest.${OBJ_SUFFIX}; then
echo "INPUT(conftest.${OBJ_SUFFIX})" > conftest.list
if AC_TRY_COMMAND(${CC-cc} -o conftest${ac_exeext} $LDFLAGS conftest.list $LIBS 1>&5) && test -s conftest${ac_exeext}; then
EXPAND_LIBS_LIST_STYLE=linkerscript
else
echo "conftest.${OBJ_SUFFIX}" > conftest.list
if AC_TRY_COMMAND(${CC-cc} -o conftest${ac_exeext} $LDFLAGS @conftest.list $LIBS 1>&5) && test -s conftest${ac_exeext}; then
EXPAND_LIBS_LIST_STYLE=list
else
EXPAND_LIBS_LIST_STYLE=none
fi
fi
else
dnl We really don't expect to get here, but just in case
AC_ERROR([couldn't compile a simple C file])
fi
rm -rf conftest*])
LIBS_DESC_SUFFIX=desc
AC_SUBST(LIBS_DESC_SUFFIX)
AC_SUBST(EXPAND_LIBS_LIST_STYLE)
if test "$GCC_USE_GNU_LD"; then
AC_CACHE_CHECK(what kind of ordering can be done with the linker,
EXPAND_LIBS_ORDER_STYLE,
[> conftest.order
_SAVE_LDFLAGS="$LDFLAGS"
LDFLAGS="${LDFLAGS} -Wl,--section-ordering-file,conftest.order"
AC_TRY_LINK([], [],
EXPAND_LIBS_ORDER_STYLE=section-ordering-file,
EXPAND_LIBS_ORDER_STYLE=)
LDFLAGS="$_SAVE_LDFLAGS"
if test -z "$EXPAND_LIBS_ORDER_STYLE"; then
if AC_TRY_COMMAND(${CC-cc} ${DSO_LDOPTS} ${LDFLAGS} -o ${DLL_PREFIX}conftest${DLL_SUFFIX} -Wl,--verbose 2> /dev/null | sed -n '/^===/,/^===/p' | grep '\.text'); then
EXPAND_LIBS_ORDER_STYLE=linkerscript
else
EXPAND_LIBS_ORDER_STYLE=none
fi
rm -f ${DLL_PREFIX}conftest${DLL_SUFFIX}
fi])
fi
AC_SUBST(EXPAND_LIBS_ORDER_STYLE)
])

View File

@ -459,7 +459,7 @@ class ShutdownLeakLogger(object):
DOM windows (that are still around after test suite shutdown, despite running
the GC) to the tests that created them and prints leak statistics.
"""
MAX_LEAK_COUNT = 123
MAX_LEAK_COUNT = 120
def __init__(self, logger):
self.logger = logger

View File

@ -789,8 +789,12 @@ EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config
EXPAND_AR = $(EXPAND_LIBS_EXEC) --extract -- $(AR)
EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselist -- $(CC)
EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist $(if $(REORDER),--reorder $(REORDER))-- $(LD)
EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) --uselist $(if $(REORDER),--reorder $(REORDER))-- $(MKSHLIB)
EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
EXPAND_MKSHLIB_ARGS = --uselist
ifdef SYMBOL_ORDER
EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
endif
EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB)
ifdef STDCXX_COMPAT
ifneq ($(OS_ARCH),Darwin)

View File

@ -54,3 +54,5 @@ DLL_SUFFIX = normalize_suffix("@DLL_SUFFIX@")
IMPORT_LIB_SUFFIX = normalize_suffix("@IMPORT_LIB_SUFFIX@")
LIBS_DESC_SUFFIX = normalize_suffix("@LIBS_DESC_SUFFIX@")
EXPAND_LIBS_LIST_STYLE = "@EXPAND_LIBS_LIST_STYLE@"
EXPAND_LIBS_ORDER_STYLE = "@EXPAND_LIBS_ORDER_STYLE@"
LD_PRINT_ICF_SECTIONS = "@LD_PRINT_ICF_SECTIONS@"

View File

@ -49,9 +49,9 @@ EXPAND_LIBS_LIST_STYLE variable: 'list' for MSVC style lists (@file.list)
or 'linkerscript' for GNU ld linker scripts.
See https://bugzilla.mozilla.org/show_bug.cgi?id=584474#c59 for more details.
With the --reorder argument, followed by a file name, it will reorder the
object files from the command line according to the order given in the file.
Implies --extract.
With the --symbol-order argument, followed by a file name, it will add the
relevant linker options to change the order in which the linker puts the
symbols appear in the resulting binary. Only works for ELF targets.
'''
from __future__ import with_statement
import sys
@ -62,6 +62,18 @@ from optparse import OptionParser
import subprocess
import tempfile
import shutil
import subprocess
import re
# The are the insert points for a GNU ld linker script, assuming a more
# or less "standard" default linker script. This is not a dict because
# order is important.
SECTION_INSERT_BEFORE = [
('.text', '.fini'),
('.rodata', '.rodata1'),
('.data.rel.ro', '.dynamic'),
('.data', '.data1'),
]
class ExpandArgsMore(ExpandArgs):
''' Meant to be used as 'with ExpandArgsMore(args) as ...: '''
@ -119,6 +131,7 @@ class ExpandArgsMore(ExpandArgs):
content = ["%s\n" % obj for obj in objs]
ref = "@" + tmp
else:
os.close(fd)
os.remove(tmp)
return
self.tmp.append(tmp)
@ -129,21 +142,163 @@ class ExpandArgsMore(ExpandArgs):
newlist = self[0:idx] + [ref] + [item for item in self[idx:] if item not in objs]
self[0:] = newlist
def reorder(self, order_list):
'''Given a list of file names without OBJ_SUFFIX, rearrange self
so that the object file names it contains are ordered according to
that list.
'''
objs = [o for o in self if isObject(o)]
if not objs: return
idx = self.index(objs[0])
# Keep everything before the first object, then the ordered objects,
# then any other objects, then any non-objects after the first object
objnames = dict([(os.path.splitext(os.path.basename(o))[0], o) for o in objs])
self[0:] = self[0:idx] + [objnames[o] for o in order_list if o in objnames] + \
[o for o in objs if os.path.splitext(os.path.basename(o))[0] not in order_list] + \
[x for x in self[idx:] if not isObject(x)]
def _getFoldedSections(self):
'''Returns a dict about folded sections.
When section A and B are folded into section C, the dict contains:
{ 'A': 'C',
'B': 'C',
'C': ['A', 'B'] }'''
if not conf.LD_PRINT_ICF_SECTIONS:
return {}
proc = subprocess.Popen(self + [conf.LD_PRINT_ICF_SECTIONS], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
(stdout, stderr) = proc.communicate()
result = {}
# gold's --print-icf-sections output looks like the following:
# ld: ICF folding section '.section' in file 'file.o'into '.section' in file 'file.o'
# In terms of words, chances are this will change in the future,
# especially considering "into" is misplaced. Splitting on quotes
# seems safer.
for l in stderr.split('\n'):
quoted = l.split("'")
if len(quoted) > 5 and quoted[1] != quoted[5]:
result[quoted[1]] = quoted[5]
if quoted[5] in result:
result[quoted[5]].append(quoted[1])
else:
result[quoted[5]] = [quoted[1]]
return result
def _getOrderedSections(self, ordered_symbols):
'''Given an ordered list of symbols, returns the corresponding list
of sections following the order.'''
if not conf.EXPAND_LIBS_ORDER_STYLE in ['linkerscript', 'section-ordering-file']:
raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
finder = SectionFinder([arg for arg in self if isObject(arg) or os.path.splitext(arg)[1] == conf.LIB_SUFFIX])
folded = self._getFoldedSections()
sections = set()
ordered_sections = []
for symbol in ordered_symbols:
symbol_sections = finder.getSections(symbol)
all_symbol_sections = []
for section in symbol_sections:
if section in folded:
if isinstance(folded[section], str):
section = folded[section]
all_symbol_sections.append(section)
all_symbol_sections.extend(folded[section])
else:
all_symbol_sections.append(section)
for section in all_symbol_sections:
if not section in sections:
ordered_sections.append(section)
sections.add(section)
return ordered_sections
def orderSymbols(self, order):
'''Given a file containing a list of symbols, adds the appropriate
argument to make the linker put the symbols in that order.'''
with open(order) as file:
sections = self._getOrderedSections([l.strip() for l in file.readlines() if l.strip()])
split_sections = {}
linked_sections = [s[0] for s in SECTION_INSERT_BEFORE]
for s in sections:
for linked_section in linked_sections:
if s.startswith(linked_section):
if linked_section in split_sections:
split_sections[linked_section].append(s)
else:
split_sections[linked_section] = [s]
break
content = []
# Order is important
linked_sections = [s for s in linked_sections if s in split_sections]
if conf.EXPAND_LIBS_ORDER_STYLE == 'section-ordering-file':
option = '-Wl,--section-ordering-file,%s'
content = sections
for linked_section in linked_sections:
content.extend(split_sections[linked_section])
content.append('%s.*' % linked_section)
content.append(linked_section)
elif conf.EXPAND_LIBS_ORDER_STYLE == 'linkerscript':
option = '-Wl,-T,%s'
section_insert_before = dict(SECTION_INSERT_BEFORE)
for linked_section in linked_sections:
content.append('SECTIONS {')
content.append(' %s : {' % linked_section)
content.extend(' *(%s)' % s for s in split_sections[linked_section])
content.append(' }')
content.append('}')
content.append('INSERT BEFORE %s' % section_insert_before[linked_section])
else:
raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
fd, tmp = tempfile.mkstemp(dir=os.curdir)
f = os.fdopen(fd, "w")
f.write('\n'.join(content)+'\n')
f.close()
self.tmp.append(tmp)
self.append(option % tmp)
class SectionFinder(object):
'''Instances of this class allow to map symbol names to sections in
object files.'''
def __init__(self, objs):
'''Creates an instance, given a list of object files.'''
if not conf.EXPAND_LIBS_ORDER_STYLE in ['linkerscript', 'section-ordering-file']:
raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
self.mapping = {}
for obj in objs:
if not isObject(obj) and os.path.splitext(obj)[1] != conf.LIB_SUFFIX:
raise Exception('%s is not an object nor a static library' % obj)
for symbol, section in SectionFinder._getSymbols(obj):
sym = SectionFinder._normalize(symbol)
if sym in self.mapping:
if not section in self.mapping[sym]:
self.mapping[sym].append(section)
else:
self.mapping[sym] = [section]
def getSections(self, symbol):
'''Given a symbol, returns a list of sections containing it or the
corresponding thunks. When the given symbol is a thunk, returns the
list of sections containing its corresponding normal symbol and the
other thunks for that symbol.'''
sym = SectionFinder._normalize(symbol)
if sym in self.mapping:
return self.mapping[sym]
return []
@staticmethod
def _normalize(symbol):
'''For normal symbols, return the given symbol. For thunks, return
the corresponding normal symbol.'''
if re.match('^_ZThn[0-9]+_', symbol):
return re.sub('^_ZThn[0-9]+_', '_Z', symbol)
return symbol
@staticmethod
def _getSymbols(obj):
'''Returns a list of (symbol, section) contained in the given object
file.'''
proc = subprocess.Popen(['objdump', '-t', obj], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
(stdout, stderr) = proc.communicate()
syms = []
for line in stdout.splitlines():
# Each line has the following format:
# <addr> [lgu!][w ][C ][W ][Ii ][dD ][FfO ] <section>\t<length> <symbol>
tmp = line.split(' ',1)
# This gives us ["<addr>", "[lgu!][w ][C ][W ][Ii ][dD ][FfO ] <section>\t<length> <symbol>"]
# We only need to consider cases where "<section>\t<length> <symbol>" is present,
# and where the [FfO] flag is either F (function) or O (object).
if len(tmp) > 1 and len(tmp[1]) > 6 and tmp[1][6] in ['O', 'F']:
tmp = tmp[1][8:].split()
# That gives us ["<section>","<length>", "<symbol>"]
syms.append((tmp[-1], tmp[0]))
return syms
def main():
parser = OptionParser()
@ -153,17 +308,16 @@ def main():
help="use a list file for objects when executing a command")
parser.add_option("--verbose", action="store_true", dest="verbose",
help="display executed command and temporary files content")
parser.add_option("--reorder", dest="reorder",
help="reorder the objects according to the given list", metavar="FILE")
parser.add_option("--symbol-order", dest="symbol_order", metavar="FILE",
help="use the given list of symbols to order symbols in the resulting binary when using with a linker")
(options, args) = parser.parse_args()
with ExpandArgsMore(args) as args:
if options.extract or options.reorder:
if options.extract:
args.extract()
if options.reorder:
with open(options.reorder) as file:
args.reorder([l.strip() for l in file.readlines()])
if options.symbol_order:
args.orderSymbols(options.symbol_order)
if options.uselist:
args.makelist()

View File

@ -38,7 +38,7 @@ config = sys.modules['expandlibs_config'] = imp.new_module('expandlibs_config')
from expandlibs import LibDescriptor, ExpandArgs, relativize
from expandlibs_gen import generate
from expandlibs_exec import ExpandArgsMore
from expandlibs_exec import ExpandArgsMore, SectionFinder
def Lib(name):
return config.LIB_PREFIX + name + config.LIB_SUFFIX
@ -267,28 +267,101 @@ class TestExpandArgsMore(TestExpandInit):
# Restore subprocess.call
subprocess.call = subprocess_call
def test_reorder(self):
'''Test object reordering'''
# We don't care about AR_EXTRACT testing, which is done in test_extract
config.AR_EXTRACT = ''
class FakeProcess(object):
def __init__(self, out, err = ''):
self.out = out
self.err = err
# ExpandArgsMore does the same as ExpandArgs
with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
def communicate(self):
return (self.out, self.err)
# Use an order containing object files from libraries
order_files = [self.libx_files[1], self.libx_files[0], self.liby_files[2], self.files[1]]
order = [os.path.splitext(os.path.basename(f))[0] for f in order_files]
args.reorder(order[:2] + ['unknown'] + order[2:])
OBJDUMPS = {
'foo.o': '''
00000000 g F .text\t00000001 foo
00000000 g F .text._Z6foobarv\t00000001 _Z6foobarv
00000000 g F .text.hello\t00000001 hello
00000000 g F .text._ZThn4_6foobarv\t00000001 _ZThn4_6foobarv
''',
'bar.o': '''
00000000 g F .text.hi\t00000001 hi
00000000 g F .text.hot._Z6barbazv\t00000001 .hidden _Z6barbazv
''',
}
PRINT_ICF = '''
ld: ICF folding section '.text.hello' in file 'foo.o'into '.text.hi' in file 'bar.o'
ld: ICF folding section '.foo' in file 'foo.o'into '.foo' in file 'bar.o'
'''
class SubprocessPopen(object):
def __init__(self, test):
self.test = test
def __call__(self, args, stdout = None, stderr = None):
self.test.assertEqual(stdout, subprocess.PIPE)
self.test.assertEqual(stderr, subprocess.PIPE)
if args[0] == 'objdump':
self.test.assertEqual(args[1], '-t')
self.test.assertTrue(args[2] in OBJDUMPS)
return FakeProcess(OBJDUMPS[args[2]])
else:
return FakeProcess('', PRINT_ICF)
class TestSectionFinder(unittest.TestCase):
def test_getSections(self):
'''Test SectionFinder'''
# Divert subprocess.Popen
subprocess_popen = subprocess.Popen
subprocess.Popen = SubprocessPopen(self)
config.EXPAND_LIBS_ORDER_STYLE = 'linkerscript'
config.OBJ_SUFFIX = '.o'
config.LIB_SUFFIX = '.a'
finder = SectionFinder(['foo.o', 'bar.o'])
self.assertEqual(finder.getSections('foobar'), [])
self.assertEqual(finder.getSections('_Z6barbazv'), ['.text.hot._Z6barbazv'])
self.assertEqual(finder.getSections('_Z6foobarv'), ['.text._Z6foobarv', '.text._ZThn4_6foobarv'])
self.assertEqual(finder.getSections('_ZThn4_6foobarv'), ['.text._Z6foobarv', '.text._ZThn4_6foobarv'])
subprocess.Popen = subprocess_popen
class TestSymbolOrder(unittest.TestCase):
def test_getOrderedSections(self):
'''Test ExpandMoreArgs' _getOrderedSections'''
# Divert subprocess.Popen
subprocess_popen = subprocess.Popen
subprocess.Popen = SubprocessPopen(self)
config.EXPAND_LIBS_ORDER_STYLE = 'linkerscript'
config.OBJ_SUFFIX = '.o'
config.LIB_SUFFIX = '.a'
config.LD_PRINT_ICF_SECTIONS = ''
args = ExpandArgsMore(['foo', '-bar', 'bar.o', 'foo.o'])
self.assertEqual(args._getOrderedSections(['_Z6foobarv', '_Z6barbazv']), ['.text._Z6foobarv', '.text._ZThn4_6foobarv', '.text.hot._Z6barbazv'])
self.assertEqual(args._getOrderedSections(['_ZThn4_6foobarv', '_Z6barbazv']), ['.text._Z6foobarv', '.text._ZThn4_6foobarv', '.text.hot._Z6barbazv'])
subprocess.Popen = subprocess_popen
def test_getFoldedSections(self):
'''Test ExpandMoreArgs' _getFoldedSections'''
# Divert subprocess.Popen
subprocess_popen = subprocess.Popen
subprocess.Popen = SubprocessPopen(self)
config.LD_PRINT_ICF_SECTIONS = '-Wl,--print-icf-sections'
args = ExpandArgsMore(['foo', '-bar', 'bar.o', 'foo.o'])
self.assertEqual(args._getFoldedSections(), {'.text.hello': '.text.hi', '.text.hi': ['.text.hello']})
subprocess.Popen = subprocess_popen
def test_getOrderedSectionsWithICF(self):
'''Test ExpandMoreArgs' _getOrderedSections, with ICF'''
# Divert subprocess.Popen
subprocess_popen = subprocess.Popen
subprocess.Popen = SubprocessPopen(self)
config.EXPAND_LIBS_ORDER_STYLE = 'linkerscript'
config.OBJ_SUFFIX = '.o'
config.LIB_SUFFIX = '.a'
config.LD_PRINT_ICF_SECTIONS = '-Wl,--print-icf-sections'
args = ExpandArgsMore(['foo', '-bar', 'bar.o', 'foo.o'])
self.assertEqual(args._getOrderedSections(['hello', '_Z6barbazv']), ['.text.hi', '.text.hello', '.text.hot._Z6barbazv'])
self.assertEqual(args._getOrderedSections(['_ZThn4_6foobarv', 'hi', '_Z6barbazv']), ['.text._Z6foobarv', '.text._ZThn4_6foobarv', '.text.hi', '.text.hello', '.text.hot._Z6barbazv'])
subprocess.Popen = subprocess_popen
# self.files has objects at #1, #2, #4
self.assertRelEqual(args[:3], ['foo', '-bar'] + self.files[:1])
self.assertRelEqual(args[3:7], order_files)
self.assertRelEqual(args[7:9], [self.files[2], self.files[4]])
self.assertRelEqual(args[9:11], self.liby_files[:2])
self.assertRelEqual(args[11:12], [self.libx_files[2]])
self.assertRelEqual(args[12:14], [self.files[3], self.files[5]])
self.assertRelEqual(args[14:], [self.liby_files[3]])
if __name__ == '__main__':
unittest.main(testRunner=MozTestRunner())

View File

@ -2524,6 +2524,8 @@ ia64*-hpux*)
no_x=yes
if test -n "$gonkdir"; then
_PLATFORM_DEFAULT_TOOLKIT=cairo-gonk
MOZ_B2G_RIL=1
MOZ_B2G_BT=1
else
_PLATFORM_DEFAULT_TOOLKIT=cairo-android
MOZ_LINKER=1
@ -5038,7 +5040,6 @@ cairo-gonk)
TK_LIBS='$(MOZ_CAIRO_LIBS)'
MOZ_WEBGL=1
MOZ_PDF_PRINTING=1
MOZ_B2G_RIL=1
MOZ_TOUCH=1
;;
@ -7179,78 +7180,6 @@ if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBUG_SYMBOLS"; then
export MOZ_DEBUG_SYMBOLS
fi
dnl ========================================================
dnl = Identical Code Folding
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(icf,
[ --disable-icf Disable Identical Code Folding],
MOZ_DISABLE_ICF=1,
MOZ_DISABLE_ICF= )
if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$MOZ_DISABLE_ICF"; then
AC_CACHE_CHECK([whether the linker supports Identical Code Folding],
LD_SUPPORTS_ICF,
[echo 'int foo() {return 42;}' \
'int bar() {return 42;}' \
'int main() {return foo() - bar();}' > conftest.${ac_ext}
# If the linker supports ICF, foo and bar symbols will have
# the same address
if AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS -Wl,--icf=safe -ffunction-sections conftest.${ac_ext} $LIBS 1>&2]) &&
test -s conftest${ac_exeext} &&
objdump -t conftest${ac_exeext} | awk '{a[[$6]] = $1} END {if (a[["foo"]] && (a[["foo"]] != a[["bar"]])) { exit 1 }}'; then
LD_SUPPORTS_ICF=yes
else
LD_SUPPORTS_ICF=no
fi
rm -rf conftest*])
if test "$LD_SUPPORTS_ICF" = yes; then
LDFLAGS="$LDFLAGS -Wl,--icf=safe"
CFLAGS="$CFLAGS -ffunction-sections"
CXXFLAGS="$CXXFLAGS -ffunction-sections"
fi
fi
dnl ========================================================
dnl = Automatically remove dead symbols
dnl ========================================================
if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -n "$MOZ_DEBUG_FLAGS"; then
dnl See bug 670659
AC_CACHE_CHECK([whether removing dead symbols breaks debugging],
GC_SECTIONS_BREAKS_DEBUG_RANGES,
[echo 'int foo() {return 42;}' \
'int bar() {return 1;}' \
'int main() {return foo();}' > conftest.${ac_ext}
if AC_TRY_COMMAND([${CC-cc} -o conftest.${ac_objext} $CFLAGS $MOZ_DEBUG_FLAGS -ffunction-sections -c conftest.${ac_ext} 1>&2]) &&
AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS $MOZ_DEBUG_FLAGS -Wl,--gc-sections conftest.${ac_objext} $LIBS 1>&2]) &&
test -s conftest${ac_exeext} -a -s conftest.${ac_objext}; then
if test "`$PYTHON "$_topsrcdir"/build/unix/check_debug_ranges.py conftest.${ac_objext} conftest.${ac_ext}`" = \
"`$PYTHON "$_topsrcdir"/build/unix/check_debug_ranges.py conftest${ac_exeext} conftest.${ac_ext}`"; then
GC_SECTIONS_BREAKS_DEBUG_RANGES=no
else
GC_SECTIONS_BREAKS_DEBUG_RANGES=yes
fi
else
dnl We really don't expect to get here, but just in case
GC_SECTIONS_BREAKS_DEBUG_RANGES="no, but it's broken in some other way"
fi
rm -rf conftest*])
if test "$GC_SECTIONS_BREAKS_DEBUG_RANGES" = no; then
DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections"
case "$CFLAGS" in
*-ffunction-sections*)
CFLAGS="$CFLAGS -fdata-sections"
CXXFLAGS="$CXXFLAGS -fdata-sections"
;;
*)
CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
;;
esac
fi
fi
dnl ========================================================
dnl = Enable any treating of compile warnings as errors
dnl ========================================================
@ -8072,37 +8001,7 @@ fi # ! SKIP_COMPILER_CHECKS
AC_DEFINE(CPP_THROW_NEW, [throw()])
AC_LANG_C
dnl ========================================================
dnl =
dnl = Check what kind of list files are supported by the
dnl = linker
dnl =
dnl ========================================================
AC_CACHE_CHECK(what kind of list files are supported by the linker,
EXPAND_LIBS_LIST_STYLE,
[echo "int main() {return 0;}" > conftest.${ac_ext}
if AC_TRY_COMMAND(${CC-cc} -o conftest.${OBJ_SUFFIX} -c $CFLAGS $CPPFLAGS conftest.${ac_ext} 1>&2) && test -s conftest.${OBJ_SUFFIX}; then
echo "INPUT(conftest.${OBJ_SUFFIX})" > conftest.list
if AC_TRY_COMMAND(${CC-cc} -o conftest${ac_exeext} $LDFLAGS conftest.list $LIBS 1>&2) && test -s conftest${ac_exeext}; then
EXPAND_LIBS_LIST_STYLE=linkerscript
else
echo "conftest.${OBJ_SUFFIX}" > conftest.list
if AC_TRY_COMMAND(${CC-cc} -o conftest${ac_exeext} $LDFLAGS @conftest.list $LIBS 1>&2) && test -s conftest${ac_exeext}; then
EXPAND_LIBS_LIST_STYLE=list
else
EXPAND_LIBS_LIST_STYLE=none
fi
fi
else
dnl We really don't expect to get here, but just in case
AC_ERROR([couldn't compile a simple C file])
fi
rm -rf conftest*])
LIBS_DESC_SUFFIX=desc
AC_SUBST(LIBS_DESC_SUFFIX)
AC_SUBST(EXPAND_LIBS_LIST_STYLE)
MOZ_EXPAND_LIBS
dnl ========================================================
dnl =

View File

@ -65,7 +65,6 @@ nsINodeList.h \
nsIScriptElement.h \
nsIStyleSheetLinkingElement.h \
nsIContentSerializer.h \
nsIHTMLToTextSink.h \
nsIXPathEvaluatorInternal.h \
mozISanitizingSerializer.h \
nsCaseTreatment.h \

View File

@ -441,6 +441,16 @@ public:
*/
static bool IsHTMLWhitespace(PRUnichar aChar);
/**
* Is the HTML local name a block element?
*/
static bool IsHTMLBlock(nsIAtom* aLocalName);
/**
* Is the HTML local name a void element?
*/
static bool IsHTMLVoid(nsIAtom* aLocalName);
/**
* Parse a margin string of format 'top, right, bottom, left' into
* an nsIntMargin.
@ -838,11 +848,22 @@ public:
* Fill (with the parameters given) the localized string named |aKey| in
* properties file |aFile|.
*/
private:
static nsresult FormatLocalizedString(PropertiesFile aFile,
const char* aKey,
const PRUnichar **aParams,
const PRUnichar** aParams,
PRUint32 aParamsLength,
nsXPIDLString& aResult);
public:
template<PRUint32 N>
static nsresult FormatLocalizedString(PropertiesFile aFile,
const char* aKey,
const PRUnichar* (&aParams)[N],
nsXPIDLString& aResult)
{
return FormatLocalizedString(aFile, aKey, aParams, N, aResult);
}
/**
* Returns true if aDocument is a chrome document

View File

@ -1,66 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _nsIPlainTextSink_h__
#define _nsIPlainTextSink_h__
#include "nsISupports.h"
#include "nsStringGlue.h"
#define NS_PLAINTEXTSINK_CONTRACTID "@mozilla.org/layout/plaintextsink;1"
/* starting interface: nsIContentSerializer */
#define NS_IHTMLTOTEXTSINK_IID_STR "b12b5643-07cb-401e-aabb-64b2dcd2717f"
#define NS_IHTMLTOTEXTSINK_IID \
{0xb12b5643, 0x07cb, 0x401e, \
{ 0xaa, 0xbb, 0x64, 0xb2, 0xdc, 0xd2, 0x71, 0x7f }}
class nsIHTMLToTextSink : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTMLTOTEXTSINK_IID)
NS_IMETHOD Initialize(nsAString* aOutString,
PRUint32 aFlags, PRUint32 aWrapCol) = 0;
// This function violates string ownership rules, see impl.
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLToTextSink, NS_IHTMLTOTEXTSINK_IID)
#endif

View File

@ -1190,6 +1190,72 @@ nsContentUtils::IsHTMLWhitespace(PRUnichar aChar)
aChar == PRUnichar(0x0020);
}
/* static */
bool
nsContentUtils::IsHTMLBlock(nsIAtom* aLocalName)
{
return
(aLocalName == nsGkAtoms::address) ||
(aLocalName == nsGkAtoms::article) ||
(aLocalName == nsGkAtoms::aside) ||
(aLocalName == nsGkAtoms::blockquote) ||
(aLocalName == nsGkAtoms::center) ||
(aLocalName == nsGkAtoms::dir) ||
(aLocalName == nsGkAtoms::div) ||
(aLocalName == nsGkAtoms::dl) || // XXX why not dt and dd?
(aLocalName == nsGkAtoms::fieldset) ||
(aLocalName == nsGkAtoms::figure) || // XXX shouldn't figcaption be on this list
(aLocalName == nsGkAtoms::footer) ||
(aLocalName == nsGkAtoms::form) ||
(aLocalName == nsGkAtoms::h1) ||
(aLocalName == nsGkAtoms::h2) ||
(aLocalName == nsGkAtoms::h3) ||
(aLocalName == nsGkAtoms::h4) ||
(aLocalName == nsGkAtoms::h5) ||
(aLocalName == nsGkAtoms::h6) ||
(aLocalName == nsGkAtoms::header) ||
(aLocalName == nsGkAtoms::hgroup) ||
(aLocalName == nsGkAtoms::hr) ||
(aLocalName == nsGkAtoms::li) ||
(aLocalName == nsGkAtoms::listing) ||
(aLocalName == nsGkAtoms::menu) ||
(aLocalName == nsGkAtoms::multicol) || // XXX get rid of this one?
(aLocalName == nsGkAtoms::nav) ||
(aLocalName == nsGkAtoms::ol) ||
(aLocalName == nsGkAtoms::p) ||
(aLocalName == nsGkAtoms::pre) ||
(aLocalName == nsGkAtoms::section) ||
(aLocalName == nsGkAtoms::table) ||
(aLocalName == nsGkAtoms::ul) ||
(aLocalName == nsGkAtoms::xmp);
}
/* static */
bool
nsContentUtils::IsHTMLVoid(nsIAtom* aLocalName)
{
return
(aLocalName == nsGkAtoms::area) ||
(aLocalName == nsGkAtoms::base) ||
(aLocalName == nsGkAtoms::basefont) ||
(aLocalName == nsGkAtoms::bgsound) ||
(aLocalName == nsGkAtoms::br) ||
(aLocalName == nsGkAtoms::col) ||
(aLocalName == nsGkAtoms::command) ||
(aLocalName == nsGkAtoms::embed) ||
(aLocalName == nsGkAtoms::frame) ||
(aLocalName == nsGkAtoms::hr) ||
(aLocalName == nsGkAtoms::img) ||
(aLocalName == nsGkAtoms::input) ||
(aLocalName == nsGkAtoms::keygen) ||
(aLocalName == nsGkAtoms::link) ||
(aLocalName == nsGkAtoms::meta) ||
(aLocalName == nsGkAtoms::param) ||
(aLocalName == nsGkAtoms::source) ||
(aLocalName == nsGkAtoms::track) ||
(aLocalName == nsGkAtoms::wbr);
}
/* static */
bool
nsContentUtils::ParseIntMarginValue(const nsAString& aString, nsIntMargin& result)

View File

@ -2736,6 +2736,9 @@ nsGenericElement::RemoveAttribute(const nsAString& aName)
const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
if (!name) {
// If there is no canonical nsAttrName for this attribute name, then the
// attribute does not exist and we can't get its namespace ID and
// local name below, so we return early.
return NS_OK;
}
@ -2889,8 +2892,9 @@ nsGenericElement::RemoveAttributeNS(const nsAString& aNamespaceURI,
nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
if (nsid == kNameSpaceID_Unknown) {
// Unknown namespace means no attr...
// If the namespace ID is unknown, it means there can't possibly be an
// existing attribute. We would need a known namespace ID to pass into
// UnsetAttr, so we return early if we don't have one.
return NS_OK;
}

View File

@ -142,6 +142,7 @@ GK_ATOM(before_end, "before_end")
GK_ATOM(before_start, "before_start")
GK_ATOM(below, "below")
GK_ATOM(bgcolor, "bgcolor")
GK_ATOM(bgsound, "bgsound")
GK_ATOM(big, "big")
GK_ATOM(binding, "binding")
GK_ATOM(bindings, "bindings")
@ -493,6 +494,7 @@ GK_ATOM(keepcurrentinview, "keepcurrentinview")
GK_ATOM(key, "key")
GK_ATOM(keycode, "keycode")
GK_ATOM(keydown, "keydown")
GK_ATOM(keygen, "keygen")
GK_ATOM(keypress, "keypress")
GK_ATOM(keyset, "keyset")
GK_ATOM(keytext, "keytext")

View File

@ -65,6 +65,6 @@ static const nsStaticAtom GkAtoms_info[] = {
void nsGkAtoms::AddRefAtoms()
{
NS_RegisterStaticAtoms(GkAtoms_info, ArrayLength(GkAtoms_info));
NS_RegisterStaticAtoms(GkAtoms_info);
}

File diff suppressed because it is too large Load Diff

View File

@ -45,14 +45,11 @@
#define nsPlainTextSerializer_h__
#include "nsIContentSerializer.h"
#include "nsIHTMLContentSink.h"
#include "nsHTMLTags.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsILineBreaker.h"
#include "nsIContent.h"
#include "nsIAtom.h"
#include "nsIHTMLToTextSink.h"
#include "nsIDocumentEncoder.h"
#include "nsTArray.h"
@ -62,9 +59,7 @@ class Element;
} // namespace dom
} // namespace mozilla
class nsPlainTextSerializer : public nsIContentSerializer,
public nsIHTMLContentSink,
public nsIHTMLToTextSink
class nsPlainTextSerializer : public nsIContentSerializer
{
public:
nsPlainTextSerializer();
@ -100,35 +95,8 @@ public:
NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
nsAString& aStr);
// nsIContentSink
NS_IMETHOD WillParse(void) { return NS_OK; }
NS_IMETHOD WillInterrupt(void) { return NS_OK; }
NS_IMETHOD WillResume(void) { return NS_OK; }
NS_IMETHOD SetParser(nsParserBase* aParser) { return NS_OK; }
NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
NS_IMETHOD CloseContainer(const nsHTMLTag aTag);
NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
virtual void FlushPendingNotifications(mozFlushType aType) { }
NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; }
virtual nsISupports *GetTarget() { return nsnull; }
// nsIHTMLContentSink
NS_IMETHOD OpenHead();
NS_IMETHOD IsEnabled(PRInt32 aTag, bool* aReturn);
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
NS_IMETHOD BeginContext(PRInt32 aPosition) { return NS_OK; }
NS_IMETHOD EndContext(PRInt32 aPosition) { return NS_OK; }
NS_IMETHOD DidProcessTokens(void) { return NS_OK; }
NS_IMETHOD WillProcessAToken(void) { return NS_OK; }
NS_IMETHOD DidProcessAToken(void) { return NS_OK; }
// nsIHTMLToTextSink
NS_IMETHOD Initialize(nsAString* aOutString,
PRUint32 aFlags, PRUint32 aWrapCol);
protected:
nsresult GetAttributeValue(const nsIParserNode* node, nsIAtom* aName, nsString& aValueRet);
nsresult GetAttributeValue(nsIAtom* aName, nsString& aValueRet);
void AddToLine(const PRUnichar* aStringToAdd, PRInt32 aLength);
void EndLine(bool softlinebreak, bool aBreakBySpace = false);
void EnsureVerticalSpace(PRInt32 noOfRows);
@ -136,17 +104,20 @@ protected:
void OutputQuotesAndIndent(bool stripTrailingSpaces=false);
void Output(nsString& aString);
void Write(const nsAString& aString);
bool IsBlockLevel(PRInt32 aId);
bool IsContainer(PRInt32 aId);
bool IsInPre();
bool IsInOL();
bool IsCurrentNodeConverted(const nsIParserNode* aNode);
static PRInt32 GetIdForContent(nsIContent* aContent);
nsresult DoOpenContainer(const nsIParserNode* aNode, PRInt32 aTag);
nsresult DoCloseContainer(PRInt32 aTag);
nsresult DoAddLeaf(const nsIParserNode* aNode,
PRInt32 aTag,
const nsAString& aText);
bool IsCurrentNodeConverted();
bool MustSuppressLeaf();
/**
* Returns the local name of the element as an atom if the element is an
* HTML element and the atom is a static atom. Otherwise, nsnull is returned.
*/
static nsIAtom* GetIdForContent(nsIContent* aContent);
nsresult DoOpenContainer(nsIAtom* aTag);
nsresult DoCloseContainer(nsIAtom* aTag);
nsresult DoAddLeaf(nsIAtom* aTag);
void DoAddText(bool aIsWhitespace, const nsAString& aText);
// Inlined functions
inline bool MayWrap()
@ -240,14 +211,15 @@ protected:
nsAutoTArray<bool, 8> mHasWrittenCellsForRow;
// Values gotten in OpenContainer that is (also) needed in CloseContainer
nsAutoTArray<bool, 8> mCurrentNodeIsConverted;
nsAutoTArray<bool, 8> mIsInCiteBlockquote;
// The output data
nsAString* mOutputString;
// The tag stack: the stack of tags we're operating on, so we can nest:
nsHTMLTag *mTagStack;
// The tag stack: the stack of tags we're operating on, so we can nest.
// The stack only ever points to static atoms, so they don't need to be
// refcounted.
nsIAtom** mTagStack;
PRUint32 mTagStackIndex;
// Content in the stack above this index should be ignored:

View File

@ -326,10 +326,48 @@ is(e.view, window, "view should be window");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
// UIEvent
// StorageEvent
try {
e = new UIEvent();
e = new StorageEvent();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new StorageEvent("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
is(e.key, "", "key should be ''");
is(e.oldValue, null, "oldValue should be null");
is(e.newValue, null, "newValue should be null");
is(e.url, "", "url should be ''");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new StorageEvent("hello",
{ bubbles: true, cancelable: true, key: "key",
oldValue: "oldValue", newValue: "newValue", url: "url",
storageArea: localStorage });
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.key, "key", "Wrong value");
is(e.oldValue, "oldValue", "Wrong value");
is(e.newValue, "newValue", "Wrong value");
is(e.url, "url", "Wrong value");
is(e.storageArea, localStorage, "Wrong value");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
// MouseEvent
try {
e = new MouseEvent();
} catch(exp) {
ex = true;
}

View File

@ -269,7 +269,6 @@ HandleMailtoSubject(nsCString& aPath) {
nsContentUtils::eFORMS_PROPERTIES,
"DefaultFormSubject",
formatStrings,
ArrayLength(formatStrings),
subjectStr);
if (NS_FAILED(rv))
return;

View File

@ -3830,7 +3830,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
const PRUnichar* params[] = { strMaxLength.get(), strTextLength.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"FormValidationTextTooLong",
params, 2, message);
params, message);
aValidationMessage = message;
break;
}
@ -3889,7 +3889,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
const PRUnichar* params[] = { title.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"FormValidationPatternMismatchWithTitle",
params, 1, message);
params, message);
}
aValidationMessage = message;
break;

View File

@ -1423,7 +1423,7 @@ nsHTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
const PRUnichar* params[] = { strMaxLength.get(), strTextLength.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"FormValidationTextTooLong",
params, 2, message);
params, message);
aValidationMessage = message;
}
break;

View File

@ -1466,10 +1466,14 @@ nsSVGElement::MaybeSerializeAttrBeforeRemoval(nsIAtom* aName, bool aNotify)
return;
}
const nsAttrValue* attrValue = mAttrsAndChildren.GetAttr(aName);
if (!attrValue)
return;
nsAutoString serializedValue;
mAttrsAndChildren.GetAttr(aName)->ToString(serializedValue);
nsAttrValue attrValue(serializedValue);
mAttrsAndChildren.SetAndTakeAttr(aName, attrValue);
attrValue->ToString(serializedValue);
nsAttrValue oldAttrValue(serializedValue);
mAttrsAndChildren.SetAndTakeAttr(aName, oldAttrValue);
}
/* static */

View File

@ -61,6 +61,13 @@ function run_tests()
lengths[0].valueAsString = "10";
lengths[0].convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_NUMBER);
lengths[0].newValueSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_NUMBER, 10);
// -- Attribute removal
eventChecker.expect("remove");
text.removeAttribute("x");
// -- Non-existent attribute removal
eventChecker.expect("");
text.removeAttribute("x");
text.removeAttributeNS(null, "x");
eventChecker.finish();
SimpleTest.finish();

View File

@ -50,6 +50,13 @@ function run_tests()
numbers[0].value = 17;
numbers[1].value = 20;
text.setAttribute("rotate", "17 20 30");
// -- Attribute removal
eventChecker.expect("remove");
text.removeAttribute("rotate");
// -- Non-existent attribute removal
eventChecker.expect("");
text.removeAttribute("rotate");
text.removeAttributeNS(null, "rotate");
eventChecker.finish();
SimpleTest.finish();

View File

@ -105,6 +105,15 @@ function run_tests()
list[0].x = 20;
list[1].y = 34;
path.setAttribute("d", "M20,5 L12,34");
// -- Attribute removal
eventChecker.expect("remove");
path.removeAttribute("d");
// -- Non-existent attribute removal
eventChecker.expect("");
path.removeAttribute("d");
path.removeAttributeNS(null, "d");
eventChecker.finish();
SimpleTest.finish();

View File

@ -50,6 +50,13 @@ function run_tests()
points[0].x = 30;
points[1].y = 380;
polyline.setAttribute("points", "30,375 150,380");
// -- Attribute removal
eventChecker.expect("remove");
polyline.removeAttribute("points");
// -- Non-existent attribute removal
eventChecker.expect("");
polyline.removeAttribute("points");
polyline.removeAttributeNS(null, "points");
eventChecker.finish();
SimpleTest.finish();

View File

@ -424,6 +424,16 @@ function testMutationEvents(g)
eventChecker.expect("");
g.setAttribute("transform", "matrix(1, 0, 0, 1, 0, 0)");
list[0].setMatrix(mx);
// Attribute removal
eventChecker.expect("remove");
g.removeAttribute("transform");
// Non-existent attribute removal
eventChecker.expect("");
g.removeAttribute("transform");
g.removeAttributeNS(null, "transform");
eventChecker.finish();
}

View File

@ -835,6 +835,7 @@ function run_baseVal_API_tests()
eventChecker.expect("remove add");
t.element.removeAttribute(t.attr_name);
t.element.removeAttributeNS(null, t.attr_name);
res = t.baseVal.appendItem(item);
eventChecker.finish();
}

View File

@ -38,6 +38,7 @@ function runTests()
filter.setAttribute("class", "foo");
filter.className.baseVal = "bar";
filter.removeAttribute("class");
filter.removeAttributeNS(null, "class");
filter.className.baseVal = "foo";
eventChecker.expect("");
@ -57,6 +58,7 @@ function runTests()
marker.markerWidth.baseVal.newValueSpecifiedUnits(
SVGLength.SVG_LENGTHTYPE_MM, 11);
marker.removeAttribute("markerWidth");
marker.removeAttributeNS(null, "markerWidth");
marker.markerWidth.baseVal.value = 8;
eventChecker.expect("remove add modify");
@ -84,6 +86,7 @@ function runTests()
convolve.setAttribute("divisor", "12.5");
convolve.divisor.baseVal = 6;
convolve.removeAttribute("divisor");
convolve.removeAttributeNS(null, "divisor");
convolve.divisor.baseVal = 8;
eventChecker.expect("");
@ -97,6 +100,7 @@ function runTests()
blur.setAttribute("stdDeviation", "5, 6");
blur.stdDeviationX.baseVal = 8;
blur.removeAttribute("stdDeviation");
blur.removeAttributeNS(null, "stdDeviation");
blur.setAttribute("stdDeviation", "2, 3");
eventChecker.expect("");
@ -111,6 +115,7 @@ function runTests()
convolve.setAttribute("targetX", "12");
convolve.targetX.baseVal = 6;
convolve.removeAttribute("targetX");
convolve.removeAttributeNS(null, "targetX");
convolve.targetX.baseVal = 8;
// Check redundant change when comparing typed value to attribute value
@ -129,6 +134,7 @@ function runTests()
filter.setAttribute("filterRes", "60, 70");
filter.filterResX.baseVal = 50;
filter.removeAttribute("filterRes");
filter.removeAttributeNS(null, "filterRes");
filter.setAttribute("filterRes", "50, 60");
eventChecker.expect("");
@ -149,6 +155,7 @@ function runTests()
marker.orientAngle.baseVal.newValueSpecifiedUnits(
SVGAngle.SVG_ANGLETYPE_GRAD, 45);
marker.removeAttribute("orient");
marker.removeAttributeNS(null, "orient");
marker.orientAngle.baseVal.value = 40;
eventChecker.expect("");
@ -167,6 +174,7 @@ function runTests()
convolve.setAttribute("preserveAlpha", "true");
convolve.preserveAlpha.baseVal = false;
convolve.removeAttribute("preserveAlpha");
convolve.removeAttributeNS(null, "preserveAlpha");
convolve.preserveAlpha.baseVal = true;
eventChecker.expect("");
@ -180,6 +188,7 @@ function runTests()
convolve.setAttribute("edgeMode", "none");
convolve.edgeMode.baseVal = SVGFEConvolveMatrixElement.SVG_EDGEMODE_WRAP;
convolve.removeAttribute("edgeMode");
convolve.removeAttributeNS(null, "edgeMode");
convolve.edgeMode.baseVal = SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE;
eventChecker.expect("");
@ -194,6 +203,7 @@ function runTests()
convolve.setAttribute("result", "bar");
convolve.result.baseVal = "foo";
convolve.removeAttribute("result");
convolve.removeAttributeNS(null, "result");
convolve.result.baseVal = "bar";
eventChecker.expect("");
@ -209,6 +219,7 @@ function runTests()
marker.preserveAspectRatio.baseVal.align =
SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMAX;
marker.removeAttribute("preserveAspectRatio");
marker.removeAttributeNS(null, "preserveAspectRatio");
marker.preserveAspectRatio.baseVal.align =
SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMIN;
@ -224,6 +235,7 @@ function runTests()
marker.setAttribute("viewBox", "1 2 3 4");
marker.viewBox.baseVal.height = 5;
marker.removeAttribute("viewBox");
marker.removeAttributeNS(null, "viewBox");
marker.viewBox.baseVal.height = 4;
eventChecker.ignoreEvents();

View File

@ -113,7 +113,7 @@ function report(testName, success) {
]]></script>
<script type="text/javascript"><![CDATA[
try {
let (x=1) (x);
eval("let (x=1) (x)");
var success = false;
}
catch (e) { success = true; }

View File

@ -1675,6 +1675,12 @@ NS_DEFINE_EVENT_CTOR(PageTransitionEvent)
NS_DEFINE_EVENT_CTOR(CloseEvent)
NS_DEFINE_EVENT_CTOR(UIEvent)
NS_DEFINE_EVENT_CTOR(MouseEvent)
nsresult
NS_DOMStorageEventCtor(nsISupports** aInstancePtrResult)
{
nsDOMStorageEvent* e = new nsDOMStorageEvent();
return CallQueryInterface(e, aInstancePtrResult);
}
struct nsConstructorFuncMapData
{
@ -1700,6 +1706,7 @@ static const nsConstructorFuncMapData kConstructorFuncMap[] =
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(CloseEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(UIEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MouseEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(StorageEvent)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozSmsFilter, sms::SmsFilter::NewSmsFilter)
};
@ -3895,6 +3902,7 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(StorageEvent, nsIDOMStorageEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageEvent)
DOM_CLASSINFO_EVENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(StorageEventObsolete, nsIDOMStorageEventObsolete)

View File

@ -1933,12 +1933,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
bool reUseInnerWindow = aForceReuseInnerWindow || wouldReuseInnerWindow;
// Remember the old document's principal.
nsIPrincipal *oldPrincipal = nsnull;
if (oldDoc) {
oldPrincipal = oldDoc->NodePrincipal();
}
nsresult rv = NS_OK;
// Set mDocument even if this is an outer window to avoid
@ -1956,6 +1950,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
nsRefPtr<nsGlobalWindow> newInnerWindow;
bool createdInnerWindow = false;
bool thisChrome = IsChromeWindow();
@ -2034,6 +2029,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
"Failed to get script global and holder");
mCreatingInnerWindow = false;
createdInnerWindow = true;
Thaw();
NS_ENSURE_SUCCESS(rv, rv);
@ -2114,6 +2110,19 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
}
}
// If we created a new inner window above, we need to do the last little bit
// of initialization now that the dust has settled.
if (createdInnerWindow) {
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
nsresult rv = xpc->GetWrappedNativeOfJSObject(cx, newInnerWindow->mJSObject,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
rv = wrapper->FinishInitForWrappedGlobal();
NS_ENSURE_SUCCESS(rv, rv);
}
JSAutoEnterCompartment ac;
if (!ac.enter(cx, mJSObject)) {
NS_ERROR("unable to enter a compartment");
@ -4693,7 +4702,7 @@ nsGlobalWindow::MakeScriptDialogTitle(nsAString &aOutTitle)
nsXPIDLString tempString;
nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
"ScriptDlgHeading",
formatStrings, ArrayLength(formatStrings),
formatStrings,
tempString);
aOutTitle = tempString;
}

View File

@ -147,6 +147,9 @@ static PRLogModuleInfo* gJSDiagnostics;
// Force a CC after this long if there's anything in the purple buffer.
#define NS_CC_FORCED (2 * 60 * PR_USEC_PER_SEC) // 2 min
// Don't allow an incremental GC to lock out the CC for too long.
#define NS_MAX_CC_LOCKEDOUT_TIME (5 * PR_USEC_PER_SEC) // 5 seconds
// Trigger a CC if the purple buffer exceeds this size when we check it.
#define NS_CC_PURPLE_LIMIT 250
@ -160,8 +163,8 @@ static nsITimer *sCCTimer;
static PRTime sLastCCEndTime;
static bool sGCHasRun;
static bool sCCLockedOut;
static PRTime sCCLockedOutTime;
static js::GCSliceCallback sPrevGCSliceCallback;
@ -812,7 +815,7 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
const PRUnichar *formatParams[] = { filenameUTF16.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"KillScriptLocation",
formatParams, 1,
formatParams,
scriptLocation);
if (NS_SUCCEEDED(rv) && scriptLocation) {
@ -2314,19 +2317,11 @@ nsresult
nsJSContext::SetOuterObject(JSObject* aOuterObject)
{
// Force our context's global object to be the outer.
// NB: JS_SetGlobalObject sets mContext->compartment.
JS_SetGlobalObject(mContext, aOuterObject);
// NB: JS_SetGlobalObject sets mContext->compartment.
// Set up the prototype for the outer object.
JSObject *inner = JS_GetParent(aOuterObject);
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
nsresult rv = xpc->GetWrappedNativeOfJSObject(mContext, inner,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
wrapper->FinishInitForWrappedGlobal();
JS_SetPrototype(mContext, aOuterObject, JS_GetPrototype(inner));
return NS_OK;
@ -3318,9 +3313,24 @@ TimerFireForgetSkippable(PRUint32 aSuspected, bool aRemoveChildless)
static void
CCTimerFired(nsITimer *aTimer, void *aClosure)
{
if (sDidShutdown || sCCLockedOut) {
if (sDidShutdown) {
return;
}
if (sCCLockedOut) {
PRTime now = PR_Now();
if (sCCLockedOutTime == 0) {
sCCLockedOutTime = now;
return;
}
if (now - sCCLockedOutTime < NS_MAX_CC_LOCKEDOUT_TIME) {
return;
}
// Finish the current incremental GC
nsJSContext::GarbageCollectNow(js::gcreason::CC_FORCED, nsGCNormal);
}
++sCCTimerFireCount;
// During early timer fires, we only run forgetSkippable. During the first
@ -3486,6 +3496,8 @@ nsJSContext::KillShrinkGCBuffersTimer()
void
nsJSContext::KillCCTimer()
{
sCCLockedOutTime = 0;
if (sCCTimer) {
sCCTimer->Cancel();
@ -3524,9 +3536,10 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip
}
}
// Prevent cycle collections during incremental GC.
// Prevent cycle collections and shrinking during incremental GC.
if (aProgress == js::GC_CYCLE_BEGIN) {
sCCLockedOut = true;
nsJSContext::KillShrinkGCBuffersTimer();
} else if (aProgress == js::GC_CYCLE_END) {
sCCLockedOut = false;
}
@ -3534,43 +3547,31 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip
// The GC has more work to do, so schedule another GC slice.
if (aProgress == js::GC_SLICE_END) {
nsJSContext::KillGCTimer();
nsJSContext::KillCCTimer();
nsJSContext::PokeGC(js::gcreason::INTER_SLICE_GC, NS_INTERSLICE_GC_DELAY);
}
if (aProgress == js::GC_CYCLE_END) {
// May need to kill the inter-slice GC timer
nsJSContext::KillGCTimer();
sCCollectedWaitingForGC = 0;
sCleanupSinceLastGC = false;
if (sGCTimer) {
// If we were waiting for a GC to happen, kill the timer.
nsJSContext::KillGCTimer();
if (aDesc.isCompartment) {
// If this is a compartment GC, restart it. We still want
// a full GC to happen. Compartment GCs usually happen as a
// result of last-ditch or MaybeGC. In both cases its
// result of last-ditch or MaybeGC. In both cases it is
// probably a time of heavy activity and we want to delay
// the full GC, but we do want it to happen eventually.
if (aDesc.isCompartment) {
nsJSContext::PokeGC(js::gcreason::POST_COMPARTMENT);
// We poked the GC, so we can kill any pending CC here.
nsJSContext::KillCCTimer();
}
} else {
// If this was a full GC, poke the CC to run soon.
if (!aDesc.isCompartment) {
sGCHasRun = true;
sNeedsFullCC = true;
nsJSContext::MaybePokeCC();
}
nsJSContext::PokeGC(js::gcreason::POST_COMPARTMENT);
}
// If we didn't end up scheduling a GC, make sure that we release GC buffers
// soon after canceling previous shrinking attempt.
nsJSContext::KillShrinkGCBuffersTimer();
if (!sGCTimer) {
sNeedsFullCC = true;
nsJSContext::MaybePokeCC();
if (!aDesc.isCompartment) {
// Avoid shrinking during heavy activity, which is suggested by
// compartment GC.
nsJSContext::PokeShrinkGCBuffers();
}
}
@ -3669,8 +3670,8 @@ nsJSRuntime::Startup()
{
// initialize all our statics, so that we can restart XPCOM
sGCTimer = sCCTimer = nsnull;
sGCHasRun = false;
sCCLockedOut = false;
sCCLockedOutTime = 0;
sLastCCEndTime = 0;
sPendingLoadCount = 0;
sLoadingInProgress = false;

View File

@ -9,15 +9,61 @@
#include "nsThreadUtils.h"
#include "nsXPCOMCIDInternal.h"
#include "mozilla/LazyIdleThread.h"
#include <dlfcn.h>
#include "BluetoothAdapter.h"
#if defined(MOZ_WIDGET_GONK)
#include <bluedroid/bluetooth.h>
#endif
USING_BLUETOOTH_NAMESPACE
static struct BluedroidFunctions {
bool initialized;
bool tried_initialization;
BluedroidFunctions() :
initialized(false),
tried_initialization(false)
{
}
int (* bt_enable)();
int (* bt_disable)();
int (* bt_is_enabled)();
} sBluedroidFunctions;
static bool EnsureBluetoothInit() {
if (sBluedroidFunctions.tried_initialization)
{
return sBluedroidFunctions.initialized;
}
sBluedroidFunctions.initialized = false;
sBluedroidFunctions.tried_initialization = true;
void* handle = dlopen("libbluedroid.so", RTLD_LAZY);
if(!handle) {
NS_ERROR("Failed to open libbluedroid.so, bluetooth cannot run");
return false;
}
sBluedroidFunctions.bt_enable = (int (*)())dlsym(handle, "bt_enable");
if(sBluedroidFunctions.bt_enable == NULL) {
NS_ERROR("Failed to attach bt_enable function");
return false;
}
sBluedroidFunctions.bt_disable = (int (*)())dlsym(handle, "bt_disable");
if(sBluedroidFunctions.bt_disable == NULL) {
NS_ERROR("Failed to attach bt_disable function");
return false;
}
sBluedroidFunctions.bt_is_enabled = (int (*)())dlsym(handle, "bt_is_enabled");
if(sBluedroidFunctions.bt_is_enabled == NULL) {
NS_ERROR("Failed to attach bt_is_enabled function");
return false;
}
sBluedroidFunctions.initialized = true;
return true;
}
class ToggleBtResultTask : public nsRunnable
{
public:
@ -54,7 +100,7 @@ class ToggleBtResultTask : public nsRunnable
class ToggleBtTask : public nsRunnable
{
public:
ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
: mOnOff(onOff),
mAdapterPtr(adapterPtr)
{
@ -65,18 +111,20 @@ class ToggleBtTask : public nsRunnable
{
MOZ_ASSERT(!NS_IsMainThread());
if(!EnsureBluetoothInit()) {
NS_ERROR("Failed to load bluedroid library.\n");
return NS_ERROR_FAILURE;
}
bool result;
//Toggle BT here
#if defined(MOZ_WIDGET_GONK)
if (mOnOff) {
result = bt_enable();
result = sBluedroidFunctions.bt_enable();
} else {
result = bt_disable();
result = sBluedroidFunctions.bt_disable();
}
#else
result = true;
#endif
// Create a result thread and pass it to Main Thread,
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, result);
@ -89,8 +137,8 @@ class ToggleBtTask : public nsRunnable
}
private:
nsRefPtr<BluetoothAdapter> mAdapterPtr;
bool mOnOff;
nsRefPtr<BluetoothAdapter> mAdapterPtr;
};
DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
@ -123,18 +171,37 @@ BluetoothAdapter::BluetoothAdapter()
NS_IMETHODIMP
BluetoothAdapter::GetPower(bool* aPower)
{
#ifdef MOZ_WIDGET_GONK
if(!EnsureBluetoothInit()) {
NS_ERROR("Failed to load bluedroid library.\n");
return NS_ERROR_FAILURE;
}
*aPower = sBluedroidFunctions.bt_is_enabled();
#else
*aPower = mPower;
#endif
return NS_OK;
}
NS_IMETHODIMP
BluetoothAdapter::SetPower(bool aPower)
{
#ifdef MOZ_WIDGET_GONK
// Platform specific check for gonk until object is divided in
// different implementations per platform. Linux doesn't require
// bluetooth firmware loading, but code should work otherwise.
if(!EnsureBluetoothInit()) {
NS_ERROR("Failed to load bluedroid library.\n");
return NS_ERROR_FAILURE;
}
#endif
if (mPower != aPower) {
mPower = aPower;
#ifdef MOZ_WIDGET_GONK
return ToggleBluetoothAsync();
#endif
}
return NS_OK;

View File

@ -94,3 +94,13 @@ interface nsIDOMStorageEvent : nsIDOMEvent
in DOMString urlArg,
in nsIDOMStorage storageAreaArg);
};
[scriptable, uuid(6335e5b5-13ce-4c8a-b452-5c5895f4e90e)]
interface nsIStorageEventInit : nsIEventInit
{
attribute DOMString key;
attribute DOMString oldValue;
attribute DOMString newValue;
attribute DOMString url;
attribute nsIDOMStorage storageArea;
};

View File

@ -487,7 +487,7 @@ SmsDatabaseService.prototype = {
// In first place, we retrieve the keys that match the filter.startDate
// and filter.endDate search criteria.
let timeKeyRange = null;
if (!filter.startDate != null && filter.endDate != null) {
if (filter.startDate != null && filter.endDate != null) {
timeKeyRange = IDBKeyRange.bound(filter.startDate.getTime(),
filter.endDate.getTime());
} else if (filter.startDate != null) {

View File

@ -74,6 +74,7 @@ using mozilla::dom::StorageChild;
#include "mozilla/Preferences.h"
#include "nsThreadUtils.h"
#include "mozilla/Telemetry.h"
#include "DictionaryHelpers.h"
// calls FlushAndDeleteTemporaryTables(false)
#define NS_DOMSTORAGE_FLUSH_TIMER_TOPIC "domstorage-flush-timer"
@ -2390,6 +2391,19 @@ NS_IMETHODIMP nsDOMStorageEvent::InitStorageEvent(const nsAString & typeArg,
return NS_OK;
}
nsresult
nsDOMStorageEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
mozilla::dom::StorageEventInit d;
d.oldValue.SetIsVoid(true);
d.newValue.SetIsVoid(true);
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
return InitStorageEvent(aType, d.bubbles, d.cancelable, d.key, d.oldValue,
d.newValue, d.url, d.storageArea);
}
// Obsolete globalStorage event
DOMCI_DATA(StorageEventObsolete, nsDOMStorageEventObsolete)

View File

@ -600,6 +600,8 @@ public:
NS_DECL_NSIDOMSTORAGEEVENT
NS_FORWARD_NSIDOMEVENT(nsDOMEvent::)
virtual nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
protected:
nsString mKey;
nsString mOldValue;

View File

@ -2612,10 +2612,12 @@ let GsmPDUHelper = {
* @param langShiftTable
* single shift table string.
*
* @return encoded length in septets.
*
* @note that the algorithm used in this function must match exactly with
* #writeStringAsSeptets.
*/
_calculateLangEncodedLength: function _calculateLangEncodedLength(message, langTable, langShiftTable) {
_calculateLangEncodedSeptets: function _calculateLangEncodedSeptets(message, langTable, langShiftTable) {
let length = 0;
for (let msgIndex = 0; msgIndex < message.length; msgIndex++) {
let septet = langTable.indexOf(message.charAt(msgIndex));
@ -2686,17 +2688,17 @@ let GsmPDUHelper = {
options.userDataHeaderLength = 0;
let needUCS2 = true;
let minUserDataLength = Number.MAX_VALUE;
let minUserDataSeptets = Number.MAX_VALUE;
for (let i = 0; i < this.enabledGsmTableTuples.length; i++) {
let [langIndex, langShiftIndex] = this.enabledGsmTableTuples[i];
const langTable = PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
let length = this._calculateLangEncodedLength(options.body,
langTable,
langShiftTable);
if (length < 0) {
let bodySeptets = this._calculateLangEncodedSeptets(options.body,
langTable,
langShiftTable);
if (bodySeptets < 0) {
continue;
}
@ -2709,23 +2711,19 @@ let GsmPDUHelper = {
}
// Calculate full user data length, note the extra byte is for header len
let userDataLength = length + (headerLen ? headerLen + 1 : 0);
if (userDataLength >= minUserDataLength) {
let headerSeptets = Math.ceil((headerLen ? headerLen + 1 : 0) * 8 / 7);
let userDataSeptets = bodySeptets + headerSeptets;
if (userDataSeptets >= minUserDataSeptets) {
continue;
}
needUCS2 = false;
minUserDataLength = userDataLength;
minUserDataSeptets = userDataSeptets;
options.encodedBodyLength = length;
options.encodedBodyLength = bodySeptets;
options.userDataHeaderLength = headerLen;
options.langIndex = langIndex;
options.langShiftIndex = langShiftIndex;
if (userDataLength <= options.body.length) {
// Found minimum user data length already
return;
}
}
if (needUCS2) {

View File

@ -55,10 +55,10 @@ add_test(function test_nl_single_shift_tables_validity() {
});
/**
* Verify GsmPDUHelper#_calculateLangEncodedLength() and
* Verify GsmPDUHelper#_calculateLangEncodedSeptets() and
* GsmPDUHelper#writeStringAsSeptets() algorithm match each other.
*/
add_test(function test_GsmPDUHelper__calculateLangEncodedLength() {
add_test(function test_GsmPDUHelper__calculateLangEncodedSeptets() {
let worker = newWorker({
postRILMessage: function fakePostRILMessage(data) {
// Do nothing
@ -78,9 +78,9 @@ add_test(function test_GsmPDUHelper__calculateLangEncodedLength() {
function do_check_calc(str, expectedCalcLen, lst, sst) {
do_check_eq(expectedCalcLen,
helper._calculateLangEncodedLength(str,
PDU_NL_LOCKING_SHIFT_TABLES[lst],
PDU_NL_SINGLE_SHIFT_TABLES[sst]));
helper._calculateLangEncodedSeptets(str,
PDU_NL_LOCKING_SHIFT_TABLES[lst],
PDU_NL_SINGLE_SHIFT_TABLES[sst]));
helper.resetOctetWritten();
helper.writeStringAsSeptets(str, 0, lst, sst);
@ -193,6 +193,21 @@ add_test(function test_GsmPDUHelper_calculateUserDataLength() {
test_calc("A", [PDU_DCS_MSG_CODING_7BITS_ALPHABET, 1, 3, 1, 0], [[1, 0], [2, 4]]);
test_calc("A", [PDU_DCS_MSG_CODING_7BITS_ALPHABET, 1, 3, 1, 0], [[2, 4], [1, 0]]);
// Test Bug 733981
// - Case 1, headerLen is in octets, not septets. "\\" is defined in default
// single shift table and Portuguese locking shift table. The original code
// will add headerLen 7(octets), which should be 8(septets), to calculated
// cost and gets 14, which should be 15 in total for the first run. As for
// the second run, it will be undoubtedly 14 in total. With correct fix,
// the best choice should be the second one.
test_calc("\\\\\\\\\\\\\\",
[PDU_DCS_MSG_CODING_7BITS_ALPHABET, 14, 0, 0, 0], [[3, 1], [0, 0]]);
// - Case 2, possible early return non-best choice. The original code will
// get total cost 6 in the first run and returns immediately. With correct
// fix, the best choice should be the second one.
test_calc(ESCAPE + ESCAPE + ESCAPE + ESCAPE + ESCAPE + "\\",
[PDU_DCS_MSG_CODING_7BITS_ALPHABET, 2, 0, 0, 0], [[3, 0], [0, 0]]);
run_next_test();
});
@ -390,8 +405,8 @@ function test_receiving_7bit_alphabets(lst, sst) {
for (let i = 0; i < text.length;) {
let len = Math.min(70, text.length - i);
let expected = text.substring(i, i + len);
let septets = helper._calculateLangEncodedLength(expected, langTable,
langShiftTable);
let septets = helper._calculateLangEncodedSeptets(expected, langTable,
langShiftTable);
let rawBytes = get7bitRawBytes(expected);
let pdu = compose7bitPdu(lst, sst, rawBytes, septets);
add_test_receiving_sms(expected, pdu);

View File

@ -1,26 +1,32 @@
<html>
<script>
function check(elt, expectProxy, message) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var result = ((utils.getClassName(elt) === 'Proxy') === expectProxy)
? "PASS"
: "FAIL";
function check(elt, expectAccess, prop) {
var access = false;
try {
elt[prop];
access = true;
}
catch (e) {}
return access === expectAccess;
}
function sendMessage(success, sameOrigin, prop) {
var result = success ? 'PASS' : 'FAIL';
var message;
if (sameOrigin)
message = 'Can access |' + prop + '| if same origin';
else
message = 'Cannot access |' + prop + '| if not same origin';
parent.postMessage(result + ',' + message, '*');
}
try {
// true if same origin, throws otherwise
var sameOrigin = parent.location.href !== '';
} catch (e) {
sameOrigin = false;
var sameOrigin = location.host !== 'example.org';
var pass = check(frameElement, sameOrigin, 'src');
if (!pass) {
sendMessage(false, sameOrigin, 'src');
} else {
pass = check(parent.location, sameOrigin, 'href');
sendMessage(pass, sameOrigin, 'href');
}
check(frameElement, !sameOrigin,
sameOrigin
? 'no wrapper needed if same origin'
: 'wrapper needed if not same origin');
</script>
</html>

View File

@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for location object behaviors</title>
<title>Test for same-origin and cross-origin wrapping of frameElement</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
@ -14,6 +14,14 @@
<pre id="test">
<script class="testbody" type="text/javascript">
//
// This test has sort of morphed over time to become less and less useful.
// In the past, we had special security policy for frameElement, but that's
// more or less gone away with compartment/proxy wrapping. So we just go
// through the motions to make sure that, indeed, frameElement is subject
// to the same-origin policy.
//
SimpleTest.waitForExplicitFinish();
var count = 0;

View File

@ -2925,7 +2925,7 @@ WorkerPrivate::Dispatch(WorkerRunnable* aEvent, EventQueue* aQueue)
}
if (aQueue == &mControlQueue && mJSContext) {
JS_TriggerOperationCallback(mJSContext);
JS_TriggerOperationCallback(JS_GetRuntime(mJSContext));
}
mCondVar.Notify();

View File

@ -85,5 +85,5 @@ nsEditProperty::RegisterAtoms()
#undef EDITOR_ATOM
};
NS_RegisterStaticAtoms(property_atoms, ArrayLength(property_atoms));
NS_RegisterStaticAtoms(property_atoms);
}

View File

@ -134,7 +134,7 @@ nsTextServicesDocument::RegisterAtoms()
#undef TS_ATOM
};
NS_RegisterStaticAtoms(ts_atoms, ArrayLength(ts_atoms));
NS_RegisterStaticAtoms(ts_atoms);
}
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTextServicesDocument)

View File

@ -1540,8 +1540,17 @@ PRUint32 nsWindowWatcher::CalculateChromeFlags(const char *aFeatures,
nsIWebBrowserChrome::CHROME_DEPENDENT : 0;
chromeFlags |= WinHasOption(aFeatures, "modal", 0, nsnull) ?
(nsIWebBrowserChrome::CHROME_MODAL | nsIWebBrowserChrome::CHROME_DEPENDENT) : 0;
chromeFlags |= WinHasOption(aFeatures, "dialog", 0, nsnull) ?
nsIWebBrowserChrome::CHROME_OPENAS_DIALOG : 0;
/* On mobile we want to ignore the dialog window feature, since the mobile UI
does not provide any affordance for dialog windows. This does not interfere
with dialog windows created through openDialog. */
bool disableDialogFeature = false;
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
branch->GetBoolPref("dom.disable_window_open_dialog_feature", &disableDialogFeature);
if (!disableDialogFeature) {
chromeFlags |= WinHasOption(aFeatures, "dialog", 0, nsnull) ?
nsIWebBrowserChrome::CHROME_OPENAS_DIALOG : 0;
}
/* and dialogs need to have the last word. assume dialogs are dialogs,
and opened as chrome, unless explicitly told otherwise. */

View File

@ -42,6 +42,9 @@
#include "mozilla/Preferences.h"
#include "mozilla/Util.h"
#include "nsIScreen.h"
#include "nsIScreenManager.h"
#if defined(XP_UNIX)
#ifdef MOZ_WIDGET_GTK2
@ -2190,13 +2193,6 @@ static const EGLint kEGLConfigAttribsRGBA32[] = {
LOCAL_EGL_NONE
};
// This struct is used only by CreateConfig below, but ISO C++98 forbids
// instantiating a template dependent on a locally-defined type. Boo-urns!
struct EGLAttribs {
gfxASurface::gfxImageFormat mFormat;
const EGLint* mAttribs;
};
// Return true if a suitable EGLConfig was found and pass it out
// through aConfig. Return false otherwise.
//
@ -2205,47 +2201,41 @@ struct EGLAttribs {
static bool
CreateConfig(EGLConfig* aConfig)
{
EGLAttribs attribsToTry[] = {
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
// Prefer r5g6b5 for potential savings in memory bandwidth.
// This needs to be reevaluated for newer devices.
{ gfxASurface::ImageFormatRGB16_565, kEGLConfigAttribsRGB16 },
#endif
{ gfxASurface::ImageFormatARGB32, kEGLConfigAttribsRGBA32 },
};
nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
nsCOMPtr<nsIScreen> screen;
screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
PRInt32 depth = 24;
screen->GetColorDepth(&depth);
EGLConfig configs[64];
for (unsigned i = 0; i < ArrayLength(attribsToTry); ++i) {
const EGLAttribs& attribs = attribsToTry[i];
EGLint ncfg = ArrayLength(configs);
gfxASurface::gfxImageFormat format;
const EGLint* attribs = depth == 16 ? kEGLConfigAttribsRGB16 :
kEGLConfigAttribsRGBA32;
EGLint ncfg = ArrayLength(configs);
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(), attribs.mAttribs,
configs, ncfg, &ncfg) ||
ncfg < 1)
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(), attribs,
configs, ncfg, &ncfg) ||
ncfg < 1) {
return false;
}
for (int j = 0; j < ncfg; ++j) {
EGLConfig config = configs[j];
EGLint r, g, b, a;
if (sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
LOCAL_EGL_RED_SIZE, &r) &&
sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
LOCAL_EGL_GREEN_SIZE, &g) &&
sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
LOCAL_EGL_BLUE_SIZE, &b) &&
sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
LOCAL_EGL_ALPHA_SIZE, &a) &&
((depth == 16 && r == 5 && g == 6 && b == 5) ||
(depth == 24 && r == 8 && g == 8 && b == 8 && a == 8)))
{
continue;
}
for (int j = 0; j < ncfg; ++j) {
EGLConfig config = configs[j];
EGLint r, g, b, a;
if (sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
LOCAL_EGL_RED_SIZE, &r) &&
sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
LOCAL_EGL_GREEN_SIZE, &g) &&
sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
LOCAL_EGL_BLUE_SIZE, &b) &&
sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
LOCAL_EGL_ALPHA_SIZE, &a) &&
((gfxASurface::ImageFormatRGB16_565 == attribs.mFormat &&
r == 5 && g == 6 && b == 5) ||
(gfxASurface::ImageFormatARGB32 == attribs.mFormat &&
r == 8 && g == 8 && b == 8 && a == 8)))
{
*aConfig = config;
return true;
}
*aConfig = config;
return true;
}
}
return false;

View File

@ -58,5 +58,5 @@ static const nsStaticAtom atoms[] = {
void gfxAtoms::RegisterAtoms()
{
NS_RegisterStaticAtoms(atoms, ArrayLength(atoms));
NS_RegisterStaticAtoms(atoms);
}

View File

@ -68,6 +68,10 @@ using namespace mozilla;
gfxPlatform::GetLog(eGfxLog_fontinit), \
PR_LOG_DEBUG)
#define LOG_CMAPDATA_ENABLED() PR_LOG_TEST( \
gfxPlatform::GetLog(eGfxLog_cmapdata), \
PR_LOG_DEBUG)
// font info loader constants
// avoid doing this during startup even on slow machines but try to start
@ -371,6 +375,16 @@ gfxDWriteFontEntry::ReadCMAP()
rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(),
mCharacterMap, mUVSOffset,
unicodeFont, symbolFont);
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
if (LOG_CMAPDATA_ENABLED()) {
char prefix[256];
sprintf(prefix, "(cmapdata) name: %.220s",
NS_ConvertUTF16toUTF8(mName).get());
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
}
#endif
mHasCmapTable = NS_SUCCEEDED(rv);
return rv;
}
@ -411,6 +425,12 @@ gfxDWriteFontEntry::ReadCMAP()
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
if (LOG_CMAPDATA_ENABLED()) {
char prefix[256];
sprintf(prefix, "(cmapdata) name: %.220s",
NS_ConvertUTF16toUTF8(mName).get());
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
}
#endif
mHasCmapTable = NS_SUCCEEDED(rv);
@ -1174,3 +1194,182 @@ gfxDWriteFontList::ResolveFontName(const nsAString& aFontName,
return gfxPlatformFontList::ResolveFontName(aFontName, aResolvedFontName);
}
static nsresult GetFamilyName(IDWriteFont *aFont, nsString& aFamilyName)
{
HRESULT hr;
nsRefPtr<IDWriteFontFamily> family;
// clean out previous value
aFamilyName.Truncate();
hr = aFont->GetFontFamily(getter_AddRefs(family));
if (FAILED(hr)) {
return hr;
}
nsRefPtr<IDWriteLocalizedStrings> familyNames;
hr = family->GetFamilyNames(getter_AddRefs(familyNames));
if (FAILED(hr)) {
return hr;
}
UINT32 index = 0;
BOOL exists = false;
hr = familyNames->FindLocaleName(L"en-us", &index, &exists);
if (FAILED(hr)) {
return hr;
}
// If the specified locale doesn't exist, select the first on the list.
if (!exists) {
index = 0;
}
nsAutoTArray<WCHAR, 32> name;
UINT32 length;
hr = familyNames->GetStringLength(index, &length);
if (FAILED(hr)) {
return hr;
}
if (!name.SetLength(length + 1)) {
return NS_ERROR_FAILURE;
}
hr = familyNames->GetString(index, name.Elements(), length + 1);
if (FAILED(hr)) {
return hr;
}
aFamilyName.Assign(name.Elements());
return NS_OK;
}
// bug 705594 - the method below doesn't actually do any "drawing", it's only
// used to invoke the DirectWrite layout engine to determine the fallback font
// for a given character.
IFACEMETHODIMP FontFallbackRenderer::DrawGlyphRun(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
__in DWRITE_GLYPH_RUN const* glyphRun,
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
__maybenull IUnknown* clientDrawingEffect
)
{
if (!mSystemFonts) {
return E_FAIL;
}
HRESULT hr = S_OK;
nsRefPtr<IDWriteFont> font;
hr = mSystemFonts->GetFontFromFontFace(glyphRun->fontFace,
getter_AddRefs(font));
if (FAILED(hr)) {
return hr;
}
// copy the family name
hr = GetFamilyName(font, mFamilyName);
if (FAILED(hr)) {
return hr;
}
// Arial is used as the default fallback font
// so if it matches ==> no font found
if (mFamilyName.EqualsLiteral("Arial")) {
mFamilyName.Truncate();
return E_FAIL;
}
return hr;
}
gfxFontEntry*
gfxDWriteFontList::GlobalFontFallback(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aMatchStyle,
PRUint32& aCmapCount)
{
bool useCmaps = gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
if (useCmaps) {
return gfxPlatformFontList::GlobalFontFallback(aCh,
aRunScript,
aMatchStyle,
aCmapCount);
}
HRESULT hr;
nsRefPtr<IDWriteFactory> dwFactory =
gfxWindowsPlatform::GetPlatform()->GetDWriteFactory();
if (!dwFactory) {
return nsnull;
}
// initialize fallback renderer
if (!mFallbackRenderer) {
mFallbackRenderer = new FontFallbackRenderer(dwFactory);
}
// initialize text format
if (!mFallbackFormat) {
hr = dwFactory->CreateTextFormat(L"Arial", NULL,
DWRITE_FONT_WEIGHT_REGULAR,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
72.0f, L"en-us",
getter_AddRefs(mFallbackFormat));
if (FAILED(hr)) {
return nsnull;
}
}
// set up string with fallback character
wchar_t str[16];
PRUint32 strLen;
if (IS_IN_BMP(aCh)) {
str[0] = static_cast<wchar_t> (aCh);
str[1] = 0;
strLen = 1;
} else {
str[0] = static_cast<wchar_t> (H_SURROGATE(aCh));
str[1] = static_cast<wchar_t> (L_SURROGATE(aCh));
str[2] = 0;
strLen = 2;
}
// set up layout
nsRefPtr<IDWriteTextLayout> fallbackLayout;
hr = dwFactory->CreateTextLayout(str, strLen, mFallbackFormat,
200.0f, 200.0f,
getter_AddRefs(fallbackLayout));
if (FAILED(hr)) {
return nsnull;
}
// call the draw method to invoke the DirectWrite layout functions
// which determine the fallback font
hr = fallbackLayout->Draw(NULL, mFallbackRenderer, 50.0f, 50.0f);
if (FAILED(hr)) {
return nsnull;
}
gfxFontEntry *fontEntry = nsnull;
bool needsBold; // ignored in the system fallback case
fontEntry = FindFontForFamily(mFallbackRenderer->FallbackFamilyName(),
aMatchStyle, needsBold);
if (fontEntry && !fontEntry->TestCharacterMap(aCh)) {
fontEntry = nsnull;
Telemetry::Accumulate(Telemetry::BAD_FALLBACK_FONT, true);
}
return fontEntry;
}

View File

@ -204,6 +204,145 @@ protected:
bool mForceGDIClassic;
};
// custom text renderer used to determine the fallback font for a given char
class FontFallbackRenderer : public IDWriteTextRenderer
{
public:
FontFallbackRenderer(IDWriteFactory *aFactory)
: mRefCount(0)
{
HRESULT hr = S_OK;
hr = aFactory->GetSystemFontCollection(getter_AddRefs(mSystemFonts));
NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!");
}
~FontFallbackRenderer()
{}
// IDWriteTextRenderer methods
IFACEMETHOD(DrawGlyphRun)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
__in DWRITE_GLYPH_RUN const* glyphRun,
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
__maybenull IUnknown* clientDrawingEffect
);
IFACEMETHOD(DrawUnderline)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
__in DWRITE_UNDERLINE const* underline,
__maybenull IUnknown* clientDrawingEffect
)
{
return E_NOTIMPL;
}
IFACEMETHOD(DrawStrikethrough)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
__in DWRITE_STRIKETHROUGH const* strikethrough,
__maybenull IUnknown* clientDrawingEffect
)
{
return E_NOTIMPL;
}
IFACEMETHOD(DrawInlineObject)(
__maybenull void* clientDrawingContext,
FLOAT originX,
FLOAT originY,
IDWriteInlineObject* inlineObject,
BOOL isSideways,
BOOL isRightToLeft,
__maybenull IUnknown* clientDrawingEffect
)
{
return E_NOTIMPL;
}
// IDWritePixelSnapping methods
IFACEMETHOD(IsPixelSnappingDisabled)(
__maybenull void* clientDrawingContext,
__out BOOL* isDisabled
)
{
*isDisabled = FALSE;
return S_OK;
}
IFACEMETHOD(GetCurrentTransform)(
__maybenull void* clientDrawingContext,
__out DWRITE_MATRIX* transform
)
{
const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
*transform = ident;
return S_OK;
}
IFACEMETHOD(GetPixelsPerDip)(
__maybenull void* clientDrawingContext,
__out FLOAT* pixelsPerDip
)
{
*pixelsPerDip = 1.0f;
return S_OK;
}
// IUnknown methods
IFACEMETHOD_(unsigned long, AddRef) ()
{
return InterlockedIncrement(&mRefCount);
}
IFACEMETHOD_(unsigned long, Release) ()
{
unsigned long newCount = InterlockedDecrement(&mRefCount);
if (newCount == 0)
{
delete this;
return 0;
}
return newCount;
}
IFACEMETHOD(QueryInterface) (IID const& riid, void** ppvObject)
{
if (__uuidof(IDWriteTextRenderer) == riid) {
*ppvObject = this;
} else if (__uuidof(IDWritePixelSnapping) == riid) {
*ppvObject = this;
} else if (__uuidof(IUnknown) == riid) {
*ppvObject = this;
} else {
*ppvObject = NULL;
return E_FAIL;
}
this->AddRef();
return S_OK;
}
const nsString& FallbackFamilyName() { return mFamilyName; }
protected:
unsigned long mRefCount;
nsRefPtr<IDWriteFontCollection> mSystemFonts;
nsString mFamilyName;
};
class gfxDWriteFontList : public gfxPlatformFontList {
public:
@ -248,6 +387,14 @@ private:
void GetDirectWriteSubstitutes();
// search fonts system-wide for a given character, null otherwise
virtual gfxFontEntry* GlobalFontFallback(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aMatchStyle,
PRUint32& aCmapCount);
virtual bool UsesSystemFallback() { return true; }
/**
* Fonts listed in the registry as substitutes but for which no actual
* font family is found.
@ -270,6 +417,9 @@ private:
// whether to use GDI font table access routines
bool mGDIFontTableAccess;
nsRefPtr<IDWriteGdiInterop> mGDIInterop;
nsRefPtr<FontFallbackRenderer> mFallbackRenderer;
nsRefPtr<IDWriteTextFormat> mFallbackFormat;
};

View File

@ -397,11 +397,12 @@ gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
}
already_AddRefed<gfxFont>
gfxFT2FontGroup::WhichSystemFontSupportsChar(PRUint32 aCh)
gfxFT2FontGroup::WhichSystemFontSupportsChar(PRUint32 aCh, PRInt32 aRunScript)
{
#if defined(XP_WIN) || defined(ANDROID)
FontEntry *fe = static_cast<FontEntry*>
(gfxPlatformFontList::PlatformFontList()->FindFontForChar(aCh, GetFontAt(0)));
(gfxPlatformFontList::PlatformFontList()->
SystemFindFontForChar(aCh, aRunScript, &mStyle));
if (fe) {
nsRefPtr<gfxFT2Font> f = gfxFT2Font::GetOrMakeFont(fe, &mStyle);
nsRefPtr<gfxFont> font = f.get();

View File

@ -141,7 +141,8 @@ protected: // new functions
already_AddRefed<gfxFT2Font> WhichFontSupportsChar(const nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList,
PRUint32 aCh);
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
already_AddRefed<gfxFont>
WhichSystemFontSupportsChar(PRUint32 aCh, PRInt32 aRunScript);
nsTArray<gfxTextRange> mRanges;
nsString mString;

View File

@ -690,37 +690,60 @@ void gfxFontFamily::LocalizedName(nsAString& aLocalizedName)
aLocalizedName = mName;
}
void
gfxFontFamily::FindFontForChar(FontSearch *aMatchData)
// metric for how close a given font matches a style
static PRInt32
CalcStyleMatch(gfxFontEntry *aFontEntry, const gfxFontStyle *aStyle)
{
if (!mHasStyles) {
FindStyleVariations();
PRInt32 rank = 0;
if (aStyle) {
// italics
bool wantItalic =
((aStyle->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0);
if (aFontEntry->IsItalic() == wantItalic) {
rank += 10;
}
// measure of closeness of weight to the desired value
rank += 9 - abs(aFontEntry->Weight() / 100 - aStyle->ComputeWeight());
} else {
// if no font to match, prefer non-bold, non-italic fonts
if (!aFontEntry->IsItalic()) {
rank += 3;
}
if (!aFontEntry->IsBold()) {
rank += 2;
}
}
if (!TestCharacterMap(aMatchData->mCh)) {
return rank;
}
#define RANK_MATCHED_CMAP 20
void
gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData)
{
if (mCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) {
// none of the faces in the family support the required char,
// so bail out immediately
return;
}
// iterate over fonts
PRUint32 numFonts = mAvailableFonts.Length();
for (PRUint32 i = 0; i < numFonts; i++) {
gfxFontEntry *fe = mAvailableFonts[i];
// skip certain fonts during system fallback
if (!fe || fe->SkipDuringSystemFallback())
continue;
bool needsBold;
gfxFontStyle normal;
gfxFontEntry *fe = FindFontForStyle(
(aMatchData->mStyle == nsnull) ? *aMatchData->mStyle : normal,
needsBold);
if (fe && !fe->SkipDuringSystemFallback()) {
PRInt32 rank = 0;
if (fe->TestCharacterMap(aMatchData->mCh)) {
rank += 20;
rank += RANK_MATCHED_CMAP;
aMatchData->mCount++;
#ifdef PR_LOGGING
PRLogModuleInfo *log = gfxPlatform::GetLog(eGfxLog_textrun);
if (NS_UNLIKELY(log)) {
PRUint32 charRange = gfxFontUtils::CharRangeBit(aMatchData->mCh);
PRUint32 unicodeRange = FindCharUnicodeRange(aMatchData->mCh);
@ -735,40 +758,20 @@ gfxFontFamily::FindFontForChar(FontSearch *aMatchData)
#endif
}
// if we didn't match any characters don't bother wasting more time with this face.
if (rank == 0)
continue;
// omitting from original windows code -- family name, lang group, pitch
// not available in current FontEntry implementation
if (aMatchData->mFontToMatch) {
const gfxFontStyle *style = aMatchData->mFontToMatch->GetStyle();
// matching italics takes precedence over weight
bool wantItalic =
((style->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0);
if (fe->IsItalic() == wantItalic) {
rank += 10;
}
// measure of closeness of weight to the desired value
rank += 9 - abs(fe->Weight() / 100 - style->ComputeWeight());
} else {
// if no font to match, prefer non-bold, non-italic fonts
if (!fe->IsItalic()) {
rank += 3;
}
if (!fe->IsBold()) {
rank += 2;
}
aMatchData->mCmapsTested++;
if (rank == 0) {
return;
}
// omitting from original windows code -- family name, lang group, pitch
// not available in current FontEntry implementation
rank += CalcStyleMatch(fe, aMatchData->mStyle);
// xxx - add whether AAT font with morphing info for specific lang groups
if (rank > aMatchData->mMatchRank
|| (rank == aMatchData->mMatchRank &&
Compare(fe->Name(), aMatchData->mBestMatch->Name()) > 0))
Compare(fe->Name(), aMatchData->mBestMatch->Name()) > 0))
{
aMatchData->mBestMatch = fe;
aMatchData->mMatchRank = rank;
@ -776,6 +779,26 @@ gfxFontFamily::FindFontForChar(FontSearch *aMatchData)
}
}
void
gfxFontFamily::SearchAllFontsForChar(GlobalFontMatch *aMatchData)
{
PRUint32 i, numFonts = mAvailableFonts.Length();
for (i = 0; i < numFonts; i++) {
gfxFontEntry *fe = mAvailableFonts[i];
if (fe && fe->TestCharacterMap(aMatchData->mCh)) {
PRInt32 rank = RANK_MATCHED_CMAP;
rank += CalcStyleMatch(fe, aMatchData->mStyle);
if (rank > aMatchData->mMatchRank
|| (rank == aMatchData->mMatchRank &&
Compare(fe->Name(), aMatchData->mBestMatch->Name()) > 0))
{
aMatchData->mBestMatch = fe;
aMatchData->mMatchRank = rank;
}
}
}
}
// returns true if other names were found, false otherwise
bool
gfxFontFamily::ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
@ -3153,7 +3176,7 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
nsCAutoString lang;
mStyle.language->ToUTF8String(lang);
PRUint32 runLen = runLimit - runStart;
PR_LOG(log, PR_LOG_DEBUG,\
PR_LOG(log, PR_LOG_WARNING,\
("(%s) fontgroup: [%s] lang: %s script: %d len %d "
"weight: %d width: %d style: %s "
"TEXTRUN [%s] ENDTEXTRUN\n",
@ -3359,11 +3382,12 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
*aMatchType = gfxTextRange::kFontGroup;
return font.forget();
}
// check other faces of the family
gfxFontFamily *family = font->GetFontEntry()->Family();
if (family && family->TestCharacterMap(aCh)) {
FontSearch matchData(aCh, font);
family->FindFontForChar(&matchData);
GlobalFontMatch matchData(aCh, aRunScript, &mStyle);
family->SearchAllFontsForChar(&matchData);
gfxFontEntry *fe = matchData.mBestMatch;
if (fe) {
bool needsBold =
@ -3395,6 +3419,11 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
return selectedFont.forget();
}
// never fall back for characters from unknown scripts
if (aRunScript == HB_SCRIPT_UNKNOWN) {
return nsnull;
}
// for known "space" characters, don't do a full system-fallback search;
// we'll synthesize appropriate-width spaces instead of missing-glyph boxes
if (GetGeneralCategory(aCh) ==
@ -3407,7 +3436,7 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
// -- otherwise look for other stuff
if (!selectedFont) {
*aMatchType = gfxTextRange::kSystemFallback;
selectedFont = WhichSystemFontSupportsChar(aCh);
selectedFont = WhichSystemFontSupportsChar(aCh, aRunScript);
return selectedFont.forget();
}
@ -3552,10 +3581,6 @@ gfxFontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
{
gfxFont *font;
// FindCharUnicodeRange only supports BMP character points and there are no non-BMP fonts in prefs
if (aCh > 0xFFFF)
return nsnull;
// get the pref font list if it hasn't been set up already
PRUint32 unicodeRange = FindCharUnicodeRange(aCh);
eFontPrefLang charLang = gfxPlatform::GetPlatform()->GetFontPrefLangFor(unicodeRange);
@ -3627,12 +3652,14 @@ gfxFontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
}
already_AddRefed<gfxFont>
gfxFontGroup::WhichSystemFontSupportsChar(PRUint32 aCh)
gfxFontGroup::WhichSystemFontSupportsChar(PRUint32 aCh, PRInt32 aRunScript)
{
gfxFontEntry *fe =
gfxPlatformFontList::PlatformFontList()->FindFontForChar(aCh, GetFontAt(0));
gfxPlatformFontList::PlatformFontList()->
SystemFindFontForChar(aCh, aRunScript, &mStyle);
if (fe) {
nsRefPtr<gfxFont> font = fe->FindOrMakeFont(&mStyle, false); // ignore bolder considerations in system fallback case...
// ignore bolder considerations in system fallback case...
nsRefPtr<gfxFont> font = fe->FindOrMakeFont(&mStyle, false);
return font.forget();
}

View File

@ -487,16 +487,24 @@ private:
};
// used when picking fallback font
struct FontSearch {
FontSearch(const PRUint32 aCharacter, gfxFont *aFont) :
mCh(aCharacter), mFontToMatch(aFont), mMatchRank(0), mCount(0) {
}
const PRUint32 mCh;
gfxFont* mFontToMatch;
PRInt32 mMatchRank;
nsRefPtr<gfxFontEntry> mBestMatch;
PRUint32 mCount;
// used when iterating over all fonts looking for a match for a given character
struct GlobalFontMatch {
GlobalFontMatch(const PRUint32 aCharacter,
PRInt32 aRunScript,
const gfxFontStyle *aStyle) :
mCh(aCharacter), mRunScript(aRunScript), mStyle(aStyle),
mMatchRank(0), mCount(0), mCmapsTested(0)
{
}
const PRUint32 mCh; // codepoint to be matched
PRInt32 mRunScript; // Unicode script for the codepoint
const gfxFontStyle* mStyle; // style to match
PRInt32 mMatchRank; // metric indicating closest match
nsRefPtr<gfxFontEntry> mBestMatch; // current best match
PRUint32 mCount; // number of fonts matched
PRUint32 mCmapsTested; // number of cmaps tested
};
class gfxFontFamily {
@ -557,9 +565,12 @@ public:
gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle,
bool& aNeedsSyntheticBold);
// iterates over faces looking for a match with a given characters
// checks for a matching font within the family
// used as part of the font fallback process
void FindFontForChar(FontSearch *aMatchData);
void FindFontForChar(GlobalFontMatch *aMatchData);
// checks all fonts for a matching font within the family
void SearchAllFontsForChar(GlobalFontMatch *aMatchData);
// read in other family names, if any, and use functor to add each into cache
virtual void ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList);
@ -582,7 +593,7 @@ public:
gfxFontEntry* FindFont(const nsAString& aPostscriptName);
// read in cmaps for all the faces
void ReadCMAP() {
void ReadAllCMAPs() {
PRUint32 i, numFonts = mAvailableFonts.Length();
for (i = 0; i < numFonts; i++) {
gfxFontEntry *fe = mAvailableFonts[i];
@ -598,7 +609,7 @@ public:
bool TestCharacterMap(PRUint32 aCh) {
if (!mCharacterMapInitialized) {
ReadCMAP();
ReadAllCMAPs();
}
return mCharacterMap.test(aCh);
}
@ -2975,7 +2986,8 @@ public:
// search through pref fonts for a character, return nsnull if no matching pref font
virtual already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
virtual already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
virtual already_AddRefed<gfxFont>
WhichSystemFontSupportsChar(PRUint32 aCh, PRInt32 aRunScript);
template<typename T>
void ComputeRanges(nsTArray<gfxTextRange>& mRanges,

View File

@ -37,6 +37,11 @@
*
* ***** END LICENSE BLOCK ***** */
#ifdef MOZ_LOGGING
#define FORCE_PR_LOG /* Allow logging in the release build */
#endif
#include "prlog.h"
#include "mozilla/Util.h"
#include "gfxFontUtils.h"
@ -51,6 +56,7 @@
#include "nsICharsetConverterManager.h"
#include "plbase64.h"
#include "prlog.h"
#include "woff.h"
@ -58,6 +64,13 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
#ifdef PR_LOGGING
#define LOG(log, args) PR_LOG(gfxPlatform::GetLog(log), \
PR_LOG_DEBUG, args)
#endif // PR_LOGGING
#define NO_RANGE_FOUND 126 // bit 126 in the font unicode ranges is required to be 0
#define UNICODE_BMP_LIMIT 0x10000
@ -269,6 +282,37 @@ typedef struct {
#pragma pack()
#if PR_LOGGING
void
gfxSparseBitSet::Dump(const char* aPrefix, eGfxLog aWhichLog) const
{
NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad");
PRUint32 b, numBlocks = mBlocks.Length();
for (b = 0; b < numBlocks; b++) {
Block *block = mBlocks[b];
if (!block) continue;
char outStr[256];
int index = 0;
index += sprintf(&outStr[index], "%s u+%6.6x [", aPrefix, (b << BLOCK_INDEX_SHIFT));
for (int i = 0; i < 32; i += 4) {
for (int j = i; j < i + 4; j++) {
PRUint8 bits = block->mBits[j];
PRUint8 flip1 = ((bits & 0xaa) >> 1) | ((bits & 0x55) << 1);
PRUint8 flip2 = ((flip1 & 0xcc) >> 2) | ((flip1 & 0x33) << 2);
PRUint8 flipped = ((flip2 & 0xf0) >> 4) | ((flip2 & 0x0f) << 4);
index += sprintf(&outStr[index], "%2.2x", flipped);
}
if (i + 4 != 32) index += sprintf(&outStr[index], " ");
}
index += sprintf(&outStr[index], "]");
LOG(aWhichLog, ("%s", outStr));
}
}
#endif
nsresult
gfxFontUtils::ReadCMAPTableFormat12(const PRUint8 *aBuf, PRUint32 aLength,
gfxSparseBitSet& aCharacterMap)

View File

@ -41,6 +41,7 @@
#define GFX_FONT_UTILS_H
#include "gfxTypes.h"
#include "gfxPlatform.h"
#include "prtypes.h"
#include "nsAlgorithm.h"
@ -97,6 +98,11 @@ public:
return ((block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)]) & (1 << (aIndex & 0x7))) != 0;
}
#if PR_LOGGING
// dump out contents of bitmap
void Dump(const char* aPrefix, eGfxLog aWhichLog) const;
#endif
bool TestRange(PRUint32 aStart, PRUint32 aEnd) {
PRUint32 startBlock, endBlock, blockLen;

View File

@ -83,6 +83,10 @@ using namespace mozilla;
gfxPlatform::GetLog(eGfxLog_fontlist), \
PR_LOG_DEBUG)
#define LOG_CMAPDATA_ENABLED() PR_LOG_TEST( \
gfxPlatform::GetLog(eGfxLog_cmapdata), \
PR_LOG_DEBUG)
#endif // PR_LOGGING
// font info loader constants
@ -227,6 +231,12 @@ GDIFontEntry::ReadCMAP()
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
if (LOG_CMAPDATA_ENABLED()) {
char prefix[256];
sprintf(prefix, "(cmapdata) name: %.220s",
NS_ConvertUTF16toUTF8(mName).get());
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
}
#endif
return rv;
}

View File

@ -166,6 +166,7 @@ private:
friend class gfxPlatformMac;
gfxMacPlatformFontList();
virtual ~gfxMacPlatformFontList();
// initialize font lists
virtual nsresult InitFontList();
@ -181,12 +182,23 @@ private:
static void ATSNotification(ATSFontNotificationInfoRef aInfo, void* aUserArg);
// search fonts system-wide for a given character, null otherwise
virtual gfxFontEntry* GlobalFontFallback(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aMatchStyle,
PRUint32& aCmapCount);
virtual bool UsesSystemFallback() { return true; }
// keep track of ATS generation to prevent unneeded updates when loading downloaded fonts
PRUint32 mATSGeneration;
enum {
kATSGenerationInitial = -1
};
// default font for use with system-wide font fallback
CTFontRef mDefaultFont;
};
#endif /* gfxMacPlatformFontList_H_ */

View File

@ -58,6 +58,7 @@
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsISimpleEnumerator.h"
#include "nsCharTraits.h"
#include "mozilla/Telemetry.h"
@ -136,6 +137,9 @@ static NSString* GetNSStringForString(const nsAString& aSrc)
#define LOG_FONTLIST_ENABLED() PR_LOG_TEST( \
gfxPlatform::GetLog(eGfxLog_fontlist), \
PR_LOG_DEBUG)
#define LOG_CMAPDATA_ENABLED() PR_LOG_TEST( \
gfxPlatform::GetLog(eGfxLog_cmapdata), \
PR_LOG_DEBUG)
#endif // PR_LOGGING
@ -267,6 +271,12 @@ MacOSFontEntry::ReadCMAP()
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
NS_ConvertUTF16toUTF8(mName).get(),
mCharacterMap.GetSize()));
if (LOG_CMAPDATA_ENABLED()) {
char prefix[256];
sprintf(prefix, "(cmapdata) name: %.220s",
NS_ConvertUTF16toUTF8(mName).get());
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
}
#endif
return rv;
@ -695,7 +705,8 @@ gfxSingleFaceMacFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformF
#pragma mark-
gfxMacPlatformFontList::gfxMacPlatformFontList() :
gfxPlatformFontList(false), mATSGeneration(PRUint32(kATSGenerationInitial))
gfxPlatformFontList(false), mATSGeneration(PRUint32(kATSGenerationInitial)),
mDefaultFont(nsnull)
{
::ATSFontNotificationSubscribe(ATSNotification,
kATSFontNotifyOptionDefault,
@ -710,6 +721,13 @@ gfxMacPlatformFontList::gfxMacPlatformFontList() :
sFontManager = [NSFontManager sharedFontManager];
}
gfxMacPlatformFontList::~gfxMacPlatformFontList()
{
if (mDefaultFont) {
::CFRelease(mDefaultFont);
}
}
nsresult
gfxMacPlatformFontList::InitFontList()
{
@ -866,6 +884,93 @@ gfxMacPlatformFontList::ATSNotification(ATSFontNotificationInfoRef aInfo,
qfc->UpdateFontList();
}
gfxFontEntry*
gfxMacPlatformFontList::GlobalFontFallback(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aMatchStyle,
PRUint32& aCmapCount)
{
bool useCmaps = gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
if (useCmaps) {
return gfxPlatformFontList::GlobalFontFallback(aCh,
aRunScript,
aMatchStyle,
aCmapCount);
}
CFStringRef str;
UniChar ch[2];
CFIndex len = 1;
if (IS_IN_BMP(aCh)) {
ch[0] = aCh;
str = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, ch, 1,
kCFAllocatorNull);
} else {
ch[0] = H_SURROGATE(aCh);
ch[1] = L_SURROGATE(aCh);
str = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, ch, 2,
kCFAllocatorNull);
if (!str) {
return nsnull;
}
len = 2;
}
// use CoreText to find the fallback family
gfxFontEntry *fontEntry = nsnull;
CTFontRef fallback;
bool cantUseFallbackFont = false;
if (!mDefaultFont) {
mDefaultFont = ::CTFontCreateWithName(CFSTR("Lucida Grande"), 12.f,
NULL);
}
fallback = ::CTFontCreateForString(mDefaultFont, str,
::CFRangeMake(0, len));
if (fallback) {
CFStringRef familyName = ::CTFontCopyFamilyName(fallback);
::CFRelease(fallback);
if (familyName &&
::CFStringCompare(familyName, CFSTR("LastResort"),
kCFCompareCaseInsensitive) != kCFCompareEqualTo)
{
nsAutoTArray<UniChar, 1024> buffer;
CFIndex len = ::CFStringGetLength(familyName);
buffer.SetLength(len+1);
::CFStringGetCharacters(familyName, ::CFRangeMake(0, len),
buffer.Elements());
buffer[len] = 0;
nsDependentString family(buffer.Elements(), len);
bool needsBold; // ignored in the system fallback case
fontEntry = FindFontForFamily(family, aMatchStyle, needsBold);
if (fontEntry && !fontEntry->TestCharacterMap(aCh)) {
fontEntry = nsnull;
cantUseFallbackFont = true;
}
}
if (familyName) {
::CFRelease(familyName);
}
}
if (cantUseFallbackFont) {
Telemetry::Accumulate(Telemetry::BAD_FALLBACK_FONT, cantUseFallbackFont);
}
::CFRelease(str);
return fontEntry;
}
gfxFontEntry*
gfxMacPlatformFontList::GetDefaultFont(const gfxFontStyle* aStyle, bool& aNeedsBold)
{

View File

@ -118,6 +118,7 @@ static PRLogModuleInfo *sFontlistLog = nsnull;
static PRLogModuleInfo *sFontInitLog = nsnull;
static PRLogModuleInfo *sTextrunLog = nsnull;
static PRLogModuleInfo *sTextrunuiLog = nsnull;
static PRLogModuleInfo *sCmapDataLog = nsnull;
#endif
/* Class to listen for pref changes so that chrome code can dynamically
@ -149,6 +150,7 @@ SRGBOverrideObserver::Observe(nsISupports *aSubject,
#define GFX_PREF_HARFBUZZ_SCRIPTS "gfx.font_rendering.harfbuzz.scripts"
#define HARFBUZZ_SCRIPTS_DEFAULT mozilla::unicode::SHAPING_DEFAULT
#define GFX_PREF_FALLBACK_USE_CMAPS "gfx.font_rendering.fallback.always_use_cmaps"
#ifdef MOZ_GRAPHITE
#define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
@ -232,6 +234,8 @@ gfxPlatform::gfxPlatform()
mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
mAllowDownloadableFonts = UNINITIALIZED_VALUE;
mDownloadableFontsSanitize = UNINITIALIZED_VALUE;
mFallbackUsesCmaps = UNINITIALIZED_VALUE;
#ifdef MOZ_GRAPHITE
mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
#endif
@ -268,6 +272,7 @@ gfxPlatform::Init()
sFontInitLog = PR_NewLogModule("fontinit");;
sTextrunLog = PR_NewLogModule("textrun");;
sTextrunuiLog = PR_NewLogModule("textrunui");;
sCmapDataLog = PR_NewLogModule("cmapdata");;
#endif
@ -680,6 +685,17 @@ gfxPlatform::SanitizeDownloadedFonts()
return mDownloadableFontsSanitize;
}
bool
gfxPlatform::UseCmapsDuringSystemFallback()
{
if (mFallbackUsesCmaps == UNINITIALIZED_VALUE) {
mFallbackUsesCmaps =
Preferences::GetBool(GFX_PREF_FALLBACK_USE_CMAPS, false);
}
return mFallbackUsesCmaps;
}
#ifdef MOZ_GRAPHITE
bool
gfxPlatform::UseGraphiteShaping()
@ -1358,6 +1374,8 @@ gfxPlatform::FontsPrefsChanged(const char *aPref)
mAllowDownloadableFonts = UNINITIALIZED_VALUE;
} else if (!strcmp(GFX_DOWNLOADABLE_FONTS_SANITIZE, aPref)) {
mDownloadableFontsSanitize = UNINITIALIZED_VALUE;
} else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS, aPref)) {
mFallbackUsesCmaps = UNINITIALIZED_VALUE;
#ifdef MOZ_GRAPHITE
} else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
@ -1397,6 +1415,9 @@ gfxPlatform::GetLog(eGfxLog aWhichLog)
case eGfxLog_textrunui:
return sTextrunuiLog;
break;
case eGfxLog_cmapdata:
return sCmapDataLog;
break;
default:
break;
}

View File

@ -136,7 +136,9 @@ enum eGfxLog {
// dump text runs, font matching, system fallback for content
eGfxLog_textrun = 2,
// dump text runs, font matching, system fallback for chrome
eGfxLog_textrunui = 3
eGfxLog_textrunui = 3,
// dump cmap coverage data as they are loaded
eGfxLog_cmapdata = 4
};
// when searching through pref langs, max number of pref langs
@ -317,6 +319,11 @@ public:
*/
virtual bool FontHintingEnabled() { return true; }
/**
* Whether to check all font cmaps during system font fallback
*/
bool UseCmapsDuringSystemFallback();
#ifdef MOZ_GRAPHITE
/**
* Whether to use the SIL Graphite rendering engine
@ -369,6 +376,15 @@ public:
// helper method to add a pref lang to an array, if not already in array
static void AppendPrefLang(eFontPrefLang aPrefLangs[], PRUint32& aLen, eFontPrefLang aAddLang);
// returns a list of commonly used fonts for a given character
// these are *possible* matches, no cmap-checking is done at this level
virtual void GetCommonFallbackFonts(const PRUint32 /*aCh*/,
PRInt32 /*aRunScript*/,
nsTArray<const char*>& /*aFontList*/)
{
// platform-specific override, by default do nothing
}
// helper method to indicate if we want to use Azure content drawing
static bool UseAzureContentDrawing();
@ -454,6 +470,10 @@ protected:
PRInt8 mBidiNumeralOption;
// whether to always search font cmaps globally
// when doing system font fallback
PRInt8 mFallbackUsesCmaps;
// which scripts should be shaped with harfbuzz
PRInt32 mUseHarfBuzzScripts;

View File

@ -20,6 +20,7 @@
*
* Contributor(s):
* Jonathan Kew <jfkthame@gmail.com>
* John Daggett <jdaggett@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
@ -376,44 +377,45 @@ gfxPlatformFontList::GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFami
mFontFamilies.Enumerate(FontFamilyListData::AppendFamily, &data);
}
gfxFontEntry*
gfxPlatformFontList::FindFontForChar(const PRUint32 aCh, gfxFont *aPrevFont)
{
gfxFontEntry*
gfxPlatformFontList::SystemFindFontForChar(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aStyle)
{
gfxFontEntry* fontEntry = nsnull;
// is codepoint with no matching font? return null immediately
if (mCodepointsWithNoFonts.test(aCh)) {
return nsnull;
}
// TODO: optimize fallback e.g. by caching lists of fonts to try for a given
// unicode range or script
// try to short-circuit font fallback for U+FFFD, used to represent encoding errors:
// just use a platform-specific fallback system font that is guaranteed (or at least
// highly likely) to be around, or a cached family from last time U+FFFD was seen.
// this helps speed up pages with lots of encoding errors, binary-as-text, etc.
// try to short-circuit font fallback for U+FFFD, used to represent
// encoding errors: just use a platform-specific fallback system
// font that is guaranteed (or at least highly likely) to be around,
// or a cached family from last time U+FFFD was seen. this helps
// speed up pages with lots of encoding errors, binary-as-text, etc.
if (aCh == 0xFFFD && mReplacementCharFallbackFamily.Length() > 0) {
gfxFontEntry* fontEntry = nsnull;
bool needsBold; // ignored in the system fallback case
if (aPrevFont) {
fontEntry = FindFontForFamily(mReplacementCharFallbackFamily, aPrevFont->GetStyle(), needsBold);
} else {
gfxFontStyle normalStyle;
fontEntry = FindFontForFamily(mReplacementCharFallbackFamily, &normalStyle, needsBold);
}
fontEntry = FindFontForFamily(mReplacementCharFallbackFamily,
aStyle, needsBold);
if (fontEntry && fontEntry->TestCharacterMap(aCh))
return fontEntry;
}
static bool first = true;
TimeStamp start = TimeStamp::Now();
FontSearch data(aCh, aPrevFont);
// iterate over all font families to find a font that support the character
mFontFamilies.Enumerate(gfxPlatformFontList::FindFontForCharProc, &data);
// search commonly available fonts
bool common = true;
fontEntry = CommonFontFallback(aCh, aRunScript, aStyle);
// if didn't find a font, do system-wide fallback (except for specials)
PRUint32 cmapCount = 0;
if (!fontEntry) {
common = false;
fontEntry = GlobalFontFallback(aCh, aRunScript, aStyle, cmapCount);
}
TimeDuration elapsed = TimeStamp::Now() - start;
#ifdef PR_LOGGING
@ -423,27 +425,28 @@ gfxPlatformFontList::FindFontForChar(const PRUint32 aCh, gfxFont *aPrevFont)
PRUint32 charRange = gfxFontUtils::CharRangeBit(aCh);
PRUint32 unicodeRange = FindCharUnicodeRange(aCh);
PRInt32 script = mozilla::unicode::GetScriptCode(aCh);
PR_LOG(log, PR_LOG_DEBUG,\
("(textrun-systemfallback) char: u+%6.6x "
"char-range: %d unicode-range: %d script: %d match: [%s]"
" count: %d time: %dus\n",
aCh,
charRange, unicodeRange, script,
(data.mBestMatch ?
NS_ConvertUTF16toUTF8(data.mBestMatch->Name()).get() :
"<none>"),
data.mCount,
PRInt32(elapsed.ToMicroseconds())));
PR_LOG(log, PR_LOG_WARNING,\
("(textrun-systemfallback-%s) char: u+%6.6x "
"char-range: %d unicode-range: %d script: %d match: [%s]"
" time: %dus cmaps: %d\n",
(common ? "common" : "global"), aCh,
charRange, unicodeRange, script,
(fontEntry ? NS_ConvertUTF16toUTF8(fontEntry->Name()).get() :
"<none>"),
PRInt32(elapsed.ToMicroseconds()),
cmapCount));
}
#endif
// no match? add to set of non-matching codepoints
if (!data.mBestMatch) {
mCodepointsWithNoFonts.set(aCh);
} else if (aCh == 0xFFFD) {
mReplacementCharFallbackFamily = data.mBestMatch->FamilyName();
}
if (!fontEntry) {
mCodepointsWithNoFonts.set(aCh);
} else if (aCh == 0xFFFD && fontEntry) {
mReplacementCharFallbackFamily = fontEntry->FamilyName();
}
// track system fallback time
static bool first = true;
PRInt32 intElapsed = PRInt32(first ? elapsed.ToMilliseconds() :
elapsed.ToMicroseconds());
Telemetry::Accumulate((first ? Telemetry::SYSTEM_FONT_FALLBACK_FIRST :
@ -451,18 +454,76 @@ gfxPlatformFontList::FindFontForChar(const PRUint32 aCh, gfxFont *aPrevFont)
intElapsed);
first = false;
return data.mBestMatch;
// track the script for which fallback occurred (incremented one make it
// 1-based)
Telemetry::Accumulate(Telemetry::SYSTEM_FONT_FALLBACK_SCRIPT, aRunScript + 1);
return fontEntry;
}
PLDHashOperator PR_CALLBACK
gfxPlatformFontList::FindFontForCharProc(nsStringHashKey::KeyType aKey, nsRefPtr<gfxFontFamily>& aFamilyEntry,
void *userArg)
{
FontSearch *data = static_cast<FontSearch*>(userArg);
GlobalFontMatch *data = static_cast<GlobalFontMatch*>(userArg);
// evaluate all fonts in this family for a match
aFamilyEntry->FindFontForChar(data);
// evaluate all fonts in this family for a match
aFamilyEntry->FindFontForChar(data);
return PL_DHASH_NEXT;
return PL_DHASH_NEXT;
}
#define NUM_FALLBACK_FONTS 8
gfxFontEntry*
gfxPlatformFontList::CommonFontFallback(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aMatchStyle)
{
nsAutoTArray<const char*,NUM_FALLBACK_FONTS> defaultFallbacks;
PRUint32 i, numFallbacks;
gfxPlatform::GetPlatform()->GetCommonFallbackFonts(aCh, aRunScript,
defaultFallbacks);
numFallbacks = defaultFallbacks.Length();
for (i = 0; i < numFallbacks; i++) {
nsAutoString familyName;
const char *fallbackFamily = defaultFallbacks[i];
familyName.AppendASCII(fallbackFamily);
gfxFontFamily *fallback =
gfxPlatformFontList::PlatformFontList()->FindFamily(familyName);
if (!fallback)
continue;
gfxFontEntry *fontEntry;
bool needsBold; // ignored in the system fallback case
// use first font in list that supports a given character
fontEntry = fallback->FindFontForStyle(*aMatchStyle, needsBold);
if (fontEntry && fontEntry->TestCharacterMap(aCh)) {
return fontEntry;
}
}
return nsnull;
}
gfxFontEntry*
gfxPlatformFontList::GlobalFontFallback(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aMatchStyle,
PRUint32& aCmapCount)
{
// otherwise, try to find it among local fonts
GlobalFontMatch data(aCh, aRunScript, aMatchStyle);
// iterate over all font families to find a font that support the character
mFontFamilies.Enumerate(gfxPlatformFontList::FindFontForCharProc, &data);
aCmapCount = data.mCmapsTested;
return data.mBestMatch;
}
#ifdef XP_WIN
@ -609,10 +670,12 @@ gfxPlatformFontList::InitLoader()
mNumFamilies = mFontFamiliesToLoad.Length();
}
bool
bool
gfxPlatformFontList::RunLoader()
{
PRUint32 i, endIndex = (mStartIndex + mIncrement < mNumFamilies ? mStartIndex + mIncrement : mNumFamilies);
bool loadCmaps = !UsesSystemFallback() ||
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
// for each font family, load in various font info
for (i = mStartIndex; i < endIndex; i++) {
@ -628,8 +691,10 @@ gfxPlatformFontList::RunLoader()
continue;
}
// load the cmaps
familyEntry->ReadCMAP();
// load the cmaps if needed
if (loadCmaps) {
familyEntry->ReadAllCMAPs();
}
// read in face names
familyEntry->ReadFaceNames(this, mNeedFullnamePostscriptNames);

View File

@ -20,6 +20,7 @@
*
* Contributor(s):
* Jonathan Kew <jfkthame@gmail.com>
* John Daggett <jdaggett@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
@ -97,7 +98,10 @@ public:
virtual void GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray);
gfxFontEntry* FindFontForChar(const PRUint32 aCh, gfxFont *aPrevFont);
virtual gfxFontEntry*
SystemFindFontForChar(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aStyle);
// TODO: make this virtual, for lazily adding to the font list
virtual gfxFontFamily* FindFamily(const nsAString& aFamily);
@ -146,6 +150,21 @@ protected:
nsRefPtr<gfxFontFamily>& aFamilyEntry,
void* userArg);
// returns default font for a given character, null otherwise
virtual gfxFontEntry* CommonFontFallback(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aMatchStyle);
// search fonts system-wide for a given character, null otherwise
virtual gfxFontEntry* GlobalFontFallback(const PRUint32 aCh,
PRInt32 aRunScript,
const gfxFontStyle* aMatchStyle,
PRUint32& aCmapCount);
// whether system-based font fallback is used or not
// if system fallback is used, no need to load all cmaps
virtual bool UsesSystemFallback() { return false; }
// separate initialization for reading in name tables, since this is expensive
void InitOtherFamilyNames();

View File

@ -45,6 +45,7 @@
#include "gfxPlatformGtk.h"
#include "nsUnicharUtils.h"
#include "nsUnicodeProperties.h"
#include "gfxFontconfigUtils.h"
#ifdef MOZ_PANGO
#include "gfxPangoFonts.h"
@ -82,6 +83,7 @@
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::unicode;
gfxFontconfigUtils *gfxPlatformGtk::sFontconfigUtils = nsnull;
@ -668,7 +670,7 @@ FindFontForCharProc(nsStringHashKey::KeyType aKey,
nsRefPtr<FontFamily>& aFontFamily,
void* aUserArg)
{
FontSearch *data = (FontSearch*)aUserArg;
GlobalFontMatch *data = (GlobalFontMatch*)aUserArg;
aFontFamily->FindFontForChar(data);
return PL_DHASH_NEXT;
}
@ -684,7 +686,8 @@ gfxPlatformGtk::FindFontForChar(PRUint32 aCh, gfxFont *aFont)
return nsnull;
}
FontSearch data(aCh, aFont);
GlobalFontMatch data(aCh, GetScriptCode(aCh),
(aFont ? aFont->GetStyle() : nsnull));
// find fonts that support the character
gPlatformFonts->Enumerate(FindFontForCharProc, &data);

View File

@ -263,6 +263,108 @@ gfxPlatformMac::UpdateFontList()
return NS_OK;
}
static const char kFontArialUnicodeMS[] = "Arial Unicode MS";
static const char kFontAppleBraille[] = "Apple Braille";
static const char kFontAppleSymbols[] = "Apple Symbols";
static const char kFontAppleMyungjo[] = "AppleMyungjo";
static const char kFontGeneva[] = "Geneva";
static const char kFontGeezaPro[] = "Geeza Pro";
static const char kFontHiraginoKakuGothic[] = "Hiragino Kaku Gothic ProN";
static const char kFontLucidaGrande[] = "Lucida Grande";
static const char kFontMenlo[] = "Menlo";
static const char kFontPlantagenetCherokee[] = "Plantagenet Cherokee";
static const char kFontSTHeiti[] = "STHeiti";
void
gfxPlatformMac::GetCommonFallbackFonts(const PRUint32 aCh,
PRInt32 aRunScript,
nsTArray<const char*>& aFontList)
{
aFontList.AppendElement(kFontLucidaGrande);
if (!IS_IN_BMP(aCh)) {
PRUint32 p = aCh >> 16;
if (p == 1) {
aFontList.AppendElement(kFontAppleSymbols);
aFontList.AppendElement(kFontGeneva);
}
} else {
PRUint32 b = (aCh >> 8) & 0xff;
switch (b) {
case 0x03:
case 0x05:
aFontList.AppendElement(kFontGeneva);
break;
case 0x07:
aFontList.AppendElement(kFontGeezaPro);
break;
case 0x10:
aFontList.AppendElement(kFontMenlo);
break;
case 0x13: // Cherokee
aFontList.AppendElement(kFontPlantagenetCherokee);
break;
case 0x18: // Mongolian
aFontList.AppendElement(kFontSTHeiti);
break;
case 0x1d:
case 0x1e:
aFontList.AppendElement(kFontGeneva);
break;
case 0x20: // Symbol ranges
case 0x21:
case 0x22:
case 0x23:
case 0x24:
case 0x25:
case 0x26:
case 0x27:
case 0x29:
case 0x2a:
case 0x2b:
case 0x2e:
aFontList.AppendElement(kFontAppleSymbols);
aFontList.AppendElement(kFontMenlo);
aFontList.AppendElement(kFontGeneva);
aFontList.AppendElement(kFontHiraginoKakuGothic);
break;
case 0x2c:
case 0x2d:
aFontList.AppendElement(kFontGeneva);
break;
case 0x28: // Braille
aFontList.AppendElement(kFontAppleBraille);
break;
case 0x4d:
aFontList.AppendElement(kFontAppleSymbols);
break;
case 0xa0: // Yi
case 0xa1:
case 0xa2:
case 0xa3:
case 0xa4:
aFontList.AppendElement(kFontSTHeiti);
break;
case 0xa6:
case 0xa7:
aFontList.AppendElement(kFontGeneva);
aFontList.AppendElement(kFontAppleSymbols);
break;
case 0xfc:
case 0xff:
aFontList.AppendElement(kFontAppleSymbols);
break;
default:
break;
}
}
// Arial Unicode MS has lots of glyphs for obscure, use it as a last resort
aFontList.AppendElement(kFontArialUnicodeMS);
}
PRInt32
gfxPlatformMac::OSXVersion()
{

View File

@ -50,6 +50,7 @@
#define MAC_OS_X_MAJOR_VERSION_MASK 0xFFFFFFF0U
class gfxTextRun;
class gfxFontFamily;
class mozilla::gfx::DrawTarget;
class THEBES_API gfxPlatformMac : public gfxPlatform {
@ -98,6 +99,10 @@ public:
nsTArray<nsString>& aListOfFonts);
nsresult UpdateFontList();
virtual void GetCommonFallbackFonts(const PRUint32 aCh,
PRInt32 aRunScript,
nsTArray<const char*>& aFontList);
// Returns the OS X version as returned from Gestalt(gestaltSystemVersion, ...)
// Ex: Mac OS X 10.4.x ==> 0x104x
PRInt32 OSXVersion();

Some files were not shown because too many files have changed in this diff Show More