Merge mozilla-central to tracemonkey.
Merge mozilla-central to tracemonkey.
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -212,17 +212,16 @@ ACCESSIBILITY_ATOM(textPosition, "text-p
ACCESSIBILITY_ATOM(role, "role")
ACCESSIBILITY_ATOM(aria_activedescendant, "aria-activedescendant")
ACCESSIBILITY_ATOM(aria_atomic, "aria-atomic")
ACCESSIBILITY_ATOM(aria_autocomplete, "aria-autocomplete")
ACCESSIBILITY_ATOM(aria_busy, "aria-busy")
ACCESSIBILITY_ATOM(aria_checked, "aria-checked")
ACCESSIBILITY_ATOM(aria_controls, "aria-controls")
ACCESSIBILITY_ATOM(aria_describedby, "aria-describedby")
-ACCESSIBILITY_ATOM(aria_droppable, "aria-droppable")
ACCESSIBILITY_ATOM(aria_disabled, "aria-disabled")
ACCESSIBILITY_ATOM(aria_dropeffect, "aria-dropeffect")
ACCESSIBILITY_ATOM(aria_expanded, "aria-expanded")
ACCESSIBILITY_ATOM(aria_flowto, "aria-flowto")
ACCESSIBILITY_ATOM(aria_grabbed, "aria-grabbed")
ACCESSIBILITY_ATOM(aria_haspopup, "aria-haspopup")
ACCESSIBILITY_ATOM(aria_invalid, "aria-invalid")
ACCESSIBILITY_ATOM(aria_label, "aria-label")
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1126,18 +1126,17 @@ nsDocAccessible::AttributeChangedImpl(ns
aAttribute->GetUTF8String(&attributeName);
if (!PL_strncmp("aria-", attributeName, 5)) {
ARIAAttributeChanged(aContent, aAttribute);
}
}
if (aAttribute == nsAccessibilityAtoms::role ||
aAttribute == nsAccessibilityAtoms::href ||
- aAttribute == nsAccessibilityAtoms::onclick ||
- aAttribute == nsAccessibilityAtoms::aria_droppable) {
+ aAttribute == nsAccessibilityAtoms::onclick) {
// Not worth the expense to ensure which namespace these are in
// It doesn't kill use to recreate the accessible even if the attribute was used
// in the wrong namespace or an element that doesn't support it
InvalidateCacheSubtree(aContent, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
return;
}
if (aAttribute == nsAccessibilityAtoms::alt ||
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -91,16 +91,22 @@ window[chromehidden~="toolbar"] toolbar:
#identity-popup-content-box.unknownIdentity > #identity-popup-runByLabel ,
#identity-popup-content-box.unknownIdentity > #identity-popup-content-host ,
#identity-popup-content-box.unknownIdentity > #identity-popup-content-owner ,
#identity-popup-content-box.verifiedIdentity > #identity-popup-connectedToLabel2 ,
#identity-popup-content-box.verifiedDomain > #identity-popup-connectedToLabel2 {
display: none;
}
+
+/* Bug 483950 - Hide domain name in status bar pending removal */
+#security-button > label {
+ display: none;
+}
+
/* ::::: Fullscreen pseudo-toolbar ::::: */
#fullscr-toggler {
display: none;
min-height: 5px;
height: 5px;
}
#navigator-toolbox[inFullscreen="true"] #fullscr-toggler {
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -896,27 +896,25 @@ var PlacesSearchBox = {
switch (PlacesSearchBox.filterCollection) {
case "collection":
content.applyFilter(filterString, this.folders);
// XXX changing the button text is badness
//var scopeBtn = document.getElementById("scopeBarFolder");
//scopeBtn.label = PlacesOrganizer._places.selectedNode.title;
break;
case "bookmarks":
- // Make sure we're getting uri results.
- // We do not yet support searching into grouped queries or into
- // tag containers, so we must fall to the default case.
- currentOptions.resultType = currentOptions.RESULT_TYPE_URI;
content.applyFilter(filterString, this.folders);
break;
case "history":
if (currentOptions.queryType != Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) {
var query = PlacesUtils.history.getNewQuery();
query.searchTerms = filterString;
var options = currentOptions.clone();
+ // Make sure we're getting uri results.
+ options.resultType = currentOptions.RESULT_TYPE_URI;
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
content.load([query], options);
}
else
content.applyFilter(filterString);
break;
default:
throw "Invalid filterCollection on search";
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -90,16 +90,24 @@
<method name="applyFilter">
<parameter name="filterString"/>
<parameter name="folderRestrict"/>
<body><![CDATA[
// preserve grouping
var queryNode = asQuery(this.getResultNode());
var options = queryNode.queryOptions.clone();
+ // Make sure we're getting uri results.
+ // We do not yet support searching into grouped queries or into
+ // tag containers, so we must fall to the default case.
+ if (PlacesUtils.nodeIsHistoryContainer(queryNode) ||
+ options.resultType == options.RESULTS_AS_TAG_QUERY ||
+ options.resultType == options.RESULTS_AS_TAG_CONTENTS)
+ options.resultType = options.RESULT_TYPE_URI;
+
var query = PlacesUtils.history.getNewQuery();
query.searchTerms = filterString;
if (folderRestrict) {
query.setFolders(folderRestrict, folderRestrict.length);
options.queryType = options.QUERY_TYPE_BOOKMARKS;
}
--- a/browser/components/places/tests/browser/browser_library_search.js
+++ b/browser/components/places/tests/browser/browser_library_search.js
@@ -54,63 +54,65 @@
* 3. ensures that the folder scope button is disabled appropriate to the
* folder,
* 4. if the folder scope button is enabled clicks it,
* 5. resets the search and ensures that the content tree is correct and that
* the search UI is hidden, and
* 6. if folder scope was clicked, searches again and ensures folder scope
* remains selected.
*/
+
+const TEST_URL = "http://dummy.mozilla.org/";
// Add your tests here. Each is a function that's called by testHelper().
var testCases = [
// All Bookmarks
function () {
var defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
- search(PlacesUIUtils.allBookmarksFolderId, "dummy search", defScope);
+ search(PlacesUIUtils.allBookmarksFolderId, "dummy", defScope);
is(selectScope("scopeBarFolder"), false,
"Folder scope should be disabled for All Bookmarks");
resetSearch(defScope);
},
// History
function () {
defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
- search(PlacesUIUtils.leftPaneQueries["History"], "dummy search", defScope);
+ search(PlacesUIUtils.leftPaneQueries["History"], "dummy", defScope);
is(selectScope("scopeBarFolder"), false,
"Folder scope should be disabled for History");
resetSearch(defScope);
},
// Toolbar folder
function () {
defScope = getDefaultScope(bmsvc.toolbarFolder);
- search(bmsvc.toolbarFolder, "dummy search", defScope);
+ search(bmsvc.toolbarFolder, "dummy", defScope);
is(selectScope("scopeBarFolder"), true,
"Folder scope should be enabled for toolbar folder");
// Ensure that folder scope is still selected after resetting and searching
// again.
resetSearch("scopeBarFolder");
- search(bmsvc.toolbarFolder, "dummy search", "scopeBarFolder");
+ search(bmsvc.toolbarFolder, "dummy", "scopeBarFolder");
},
// A regular non-root subfolder
function () {
var folderId = bmsvc.createFolder(bmsvc.toolbarFolder,
"dummy folder",
bmsvc.DEFAULT_INDEX);
defScope = getDefaultScope(folderId);
- search(folderId, "dummy search", defScope);
+ search(folderId, "dummy", defScope);
is(selectScope("scopeBarFolder"), true,
"Folder scope should be enabled for regular subfolder");
// Ensure that folder scope is still selected after resetting and searching
// again.
resetSearch("scopeBarFolder");
- search(folderId, "dummy search", "scopeBarFolder");
+ search(folderId, "dummy", "scopeBarFolder");
bmsvc.removeItem(folderId);
},
];
///////////////////////////////////////////////////////////////////////////////
const bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
@@ -214,16 +216,25 @@ function search(aFolderId, aSearchStr, a
searchBox.value = aSearchStr;
libraryWin.PlacesSearchBox.search(searchBox.value);
query = queryStringToQuery(contentTree.getResult().root.uri);
if (aSearchStr) {
is(query.searchTerms, aSearchStr,
"Content tree's searchTerms should be text in search box");
is(doc.getElementById("searchModifiers").hidden, false,
"Scope bar should not be hidden after searching");
+ if (getSelectedScopeButtonId() == "scopeBarHistory" ||
+ getSelectedScopeButtonId() == "scopeBarAll" ||
+ aFolderId == PlacesUtils.bookmarks.unfiledBookmarksFolder) {
+ // Check that search has returned a valid result.
+ contentTree.view.selection.select(0);
+ var foundNode = contentTree.selectedNode;
+ isnot(foundNode, null, "Found a valid node");
+ is(foundNode.uri, TEST_URL);
+ }
}
else {
is(query.hasSearchTerms, false,
"Content tree's searchTerms should not exist after search reset");
ok(doc.getElementById("searchModifiers").hidden,
"Scope bar should be hidden after search reset");
}
is(getSelectedScopeButtonId(), aExpectedScopeButtonId,
@@ -255,24 +266,42 @@ function selectScope(aScopeButtonId) {
*
* @param aLibraryWin
* the Places Library window
*/
function testHelper(aLibraryWin) {
libraryWin = aLibraryWin;
testCases.forEach(function (aTest) aTest());
aLibraryWin.close();
+
+ // Cleanup.
+ PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL), ["dummyTag"]);
+ PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.unfiledBookmarksFolder);
+ PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
+
finish();
}
///////////////////////////////////////////////////////////////////////////////
function test() {
waitForExplicitFinish();
+ // Sanity:
+ ok(PlacesUtils, "PlacesUtils in context");
+ // Add a visit, a bookmark and a tag.
+ PlacesUtils.history.addVisit(PlacesUtils._uri(TEST_URL),
+ Date.now() * 1000, null,
+ PlacesUtils.history.TRANSITION_TYPED, false, 0);
+ PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.unfiledBookmarksFolder,
+ PlacesUtils._uri(TEST_URL),
+ PlacesUtils.bookmarks.DEFAULT_INDEX,
+ "dummy");
+ PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL), ["dummyTag"]);
+
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
var windowObserver = {
observe: function(aSubject, aTopic, aData) {
if (aTopic === "domwindowopened") {
ww.unregisterNotification(this);
var win = aSubject.QueryInterface(Ci.nsIDOMWindow);
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -70,16 +70,16 @@
locale/browser/preferences/tabs.dtd (%chrome/browser/preferences/tabs.dtd)
locale/browser/sidebar/sidebar.properties (%chrome/browser/sidebar/sidebar.properties)
% locale browser-region @AB_CD@ %locale/browser-region/
locale/browser-region/region.properties (%chrome/browser-region/region.properties)
# the following files are browser-specific overrides
* locale/browser/netError.dtd (%chrome/overrides/netError.dtd)
* locale/browser/appstrings.properties (%chrome/overrides/appstrings.properties)
* locale/browser/downloads/settingsChange.dtd (%chrome/overrides/settingsChange.dtd)
-% override chrome://global/locale/netErrorApp.dtd chrome://browser/locale/netError.dtd
+% override chrome://global/locale/netError.dtd chrome://browser/locale/netError.dtd
% override chrome://global/locale/appstrings.properties chrome://browser/locale/appstrings.properties
% override chrome://mozapps/locale/downloads/settingsChange.dtd chrome://browser/locale/downloads/settingsChange.dtd
#ifdef MOZ_USE_GENERIC_BRANDING
% locale branding @AB_CD@ %locale/branding/
locale/branding/brand.dtd (%chrome/branding/brand.dtd)
locale/branding/brand.properties (%chrome/branding/brand.properties)
#endif
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -1288,16 +1288,17 @@ tabpanels {
margin-top: -2px;
margin-bottom: -2px;
}
/* Tabstrip close button */
.tabs-closebutton {
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
border: none;
+ margin-bottom: 1px;
}
.tabs-closebutton > .toolbarbutton-icon {
margin: 0;
}
/* Tabbrowser arrowscrollbox arrows */
.tabbrowser-arrowscrollbox > .scrollbutton-up {
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -242,16 +242,17 @@ user_pref("layout.debug.enable_data_xbl"
user_pref("browser.EULA.override", true);
user_pref("javascript.options.jit.content", true);
user_pref("gfx.color_management.force_srgb", true);
user_pref("network.manage-offline-status", false);
user_pref("security.default_personal_cert", "Select Automatically"); // Need to client auth test be w/o any dialogs
user_pref("network.http.prompt-temp-redirect", false);
user_pref("svg.smil.enabled", true); // Needed for SMIL mochitests until bug 482402 lands
user_pref("media.cache_size", 100);
+user_pref("security.warn_viewing_mixed", false);
user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
"""
prefs.append(part)
# Increase the max script run time 10-fold for debug builds
if (IS_DEBUG_BUILD):
new file mode 100644
--- /dev/null
+++ b/build/package/wince/make_wince_cab.py
@@ -0,0 +1,368 @@
+# ***** 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 build system.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# John Wolfe <wolfe@lobo.us>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+################################################################
+#
+# make-wince-cab.py --- Given a directory, walk it and make an
+# installer based upon the contents of that directory
+#
+# Usage: python make-wince-inf.py CABWIZ_PATH SOURCE_DIR PROGRAM_NAME CAB_FINAL_NAME
+#
+# Walk through the relative directory SOURCE_DIR, parsing filenames
+# Checks for duplicate filenames and renames where needed
+# Then builds a WinMobile INF file based upon results
+#
+# Each directory in SOURCE_DIR may have a file named
+# 'install-exceptions', which lists files in SOURCE_DIR that
+# need not be placed into an installation CAB file. The
+# 'install-exceptions' file itself is always ignored.
+#
+# Blank lines and '#' comments in the 'install-exceptions' file are
+# ignored.
+#
+# EXAMPLE OF COMMAND LINE:
+# python make_wince_inf.py /c/Program\ Files/Microsoft\ Visual\ Studio\ 9.0/SmartDevices/SDK/SDKTools/cabwiz.exe dist/fennec Fennec fennec-0.11.en-US.wince-arm.cab
+#
+# ARGS:
+# cabiz_path - Path to CABWIZ.EXE executable inside Visual Studio
+#
+# source_dir - sub-directory which contains the target program
+# NOTE: It is assumed that the application name is SOURCE_DIR.exe
+# EXAMPLE: source_dir=fennec, there should be a fennec/fennec.exe application
+#
+# program_name - Name of the program to place inside the INF file
+#
+# cab_final_name - actual final name for the produced CAB file
+#
+# NOTE: In our example, "fennec" is the directory [source_name]
+# "fennec.exe" is the application [$(source_name).exe], and
+# "Fennec" is the shortcut name [program_name]
+################################################################
+
+import sys
+import os
+from os.path import join
+from subprocess import call, STDOUT
+import fnmatch
+import string
+import shutil
+
+
+class FileEntry:
+ def __init__(self, dirpath, dircount, filename, filecount, actual_filename):
+ self.dirpath = dirpath
+ self.dircount = dircount
+ self.filename = filename
+ self.filecount = filecount
+ self.actual_filename = actual_filename
+
+
+class DirEntry:
+ def __init__(self, dirpath, dircount, filecount):
+ self.dirpath = dirpath
+ self.dircount = dircount
+ self.filecount = filecount
+
+# Ignore detritus left lying around by editing tools.
+ignored_patterns = ['*~', '.#*', '#*#', '*.orig', '*.rej']
+
+file_entry_count = 0
+file_entries = []
+
+fcount = 0
+fnames = {}
+
+directories = {}
+files_in_directory = []
+
+# Return the contents of FILENAME, a 'install-exceptions' file, as
+# a dictionary whose keys are exactly the list of filenames, along
+# with the basename of FILENAME itself. If FILENAME does not exist,
+# return the empty dictionary.
+def read_exceptions(filename):
+ exceptions = set()
+ if os.path.exists(filename):
+ f = file(filename)
+ for line in f:
+ line = line.strip()
+ if line and line[0] != '#':
+ exceptions.add(line)
+ exceptions.add( os.path.basename(filename) )
+ f.close()
+ return exceptions
+
+
+# Sorts two items based first upon directory count (index of
+# directory in list of directories), then upon filename. A way of
+# getting a list sorted into directories, and then alphabetically by
+# filename within each directory.
+def sort_dircount_then_filename(item1, item2):
+ # First Compare dirpaths
+ if item1.dircount != item2.dircount:
+ return cmp(item1.dircount, item2.dircount)
+
+ # Next compare filenames
+ next_result = cmp(item1.filename, item2.filename)
+ if next_result != 0:
+ return next_result
+
+ # Lastly, compare filecounts
+ return cmp(item1.filecount, item2.filecount)
+
+
+def handle_duplicate_filename(dirpath, filename, filecount):
+ if filecount == 1:
+ return filename
+ file_parts = os.path.splitext(filename)
+ new_filename = "%s_%d%s" % (file_parts[0], filecount, file_parts[1])
+ old_relative_filename = join(dirpath, filename)
+ new_relative_filename = join(dirpath, new_filename)
+ shutil.copyfile(old_relative_filename, new_relative_filename)
+ return new_filename
+
+def add_new_entry(dirpath, dircount, filename, filecount):
+ global file_entries
+ global file_entry_count
+ actual_filename = handle_duplicate_filename(dirpath, filename, filecount)
+ file_entries.append( FileEntry(dirpath, dircount, filename, filecount, actual_filename) )
+ file_entry_count += 1
+
+
+def walk_tree(start_dir, ignore):
+ global fcount
+ global fnames
+ global directories
+ global files_in_directory
+
+ dircount = 0;
+ files_in_directory = [0]
+
+ for (dirpath, dirnames, filenames) in os.walk(start_dir):
+ exceptions = read_exceptions(join(dirpath, 'install-exceptions'))
+
+ dircount += 1
+ directories[dirpath] = DirEntry(dirpath, dircount, len(filenames))
+
+ if len(filenames) < 1:
+ print "WARNING: No files in directory [%s]" % dirpath
+
+ for filename in filenames:
+ if len(exceptions) > 0 and filename in exceptions:
+ continue
+ if any(fnmatch.fnmatch(filename, p) for p in ignore):
+ continue
+ filecount = 1
+ if filename in fnames:
+ filecount = fnames[filename] + 1
+ fnames[filename] = filecount
+
+ add_new_entry(dirpath, dircount, filename, filecount)
+
+
+def output_inf_file_header(f, program_name):
+ f.write("""; Duplicated Filenames ==> One of the two files
+; needs renaming before packaging up the CAB
+;
+; Technique: Rename the second directory's file to XXXX_1 prior to starting the CABWIZ,
+; then take care of the name in the File.xxxxx section
+
+[Version]
+Signature = "$Windows NT$" ; required as-is
+Provider = "Mozilla" ; maximum of 30 characters, full app name will be \"<Provider> <AppName>\"
+CESignature = "$Windows CE$" ; required as-is
+
+[CEStrings]
+AppName = "%s" ; maximum of 40 characters, full app name will be \"<Provider> <AppName>\"\n""" % program_name)
+
+ f.write("InstallDir = %CE1%\\%AppName% ; Program Files\Fennec\n\n")
+
+
+def output_sourcedisksnames_section(f, dirs):
+ f.write("[SourceDisksNames] ; directory that holds the application's files\n")
+ for dir in dirs:
+ f.write("""%d = , "%s",,%s\n""" % (directories[dir].dircount, dir, dir))
+ f.write(" \n")
+
+
+def output_sourcedisksfiles_section(f):
+ f.write("[SourceDisksFiles] ; list of files to be included in .cab\n")
+ for entry in sorted(file_entries, sort_dircount_then_filename):
+ f.write("%s=%d\n" % (entry.actual_filename, entry.dircount))
+ f.write("\n")
+
+
+def output_defaultinstall_section(f, dirs):
+ copyfileslist = ""
+ copyfilesrawlist=[]
+ for dir in dirs:
+ if directories[dir].filecount < 1:
+ continue
+ copyfilesrawlist.append( "Files.%s" % '.'.join( dir.split('\\') ) )
+ prefix = ", "
+ copyfileslist = ','.join(copyfilesrawlist)
+
+ f.write("""[DefaultInstall] ; operations to be completed during install
+CopyFiles = %s
+AddReg = RegData
+CEShortcuts = Shortcuts
+\n""" % copyfileslist)
+
+
+def output_destinationdirs_section(f, dirs):
+ f.write("[DestinationDirs] ; default destination directories for each operation section\n")
+ for dir in dirs:
+ dir_split = dir.split('\\')
+ mod_dir_string = '.'.join(dir_split)
+ if len(dir_split) > 1:
+ dir_minus_top_level = '\\'.join(dir_split[1:])
+ else:
+ dir_minus_top_level = ""
+ if dir_minus_top_level:
+ dir_minus_top_level = "\\%s" % dir_minus_top_level
+ if directories[dir].filecount < 1:
+ f.write(";Files.%s = 0, %%InstallDir%%%s ; NO FILES IN THIS DIRECTORY\n" % (mod_dir_string, dir_minus_top_level))
+ else:
+ f.write("Files.%s = 0, %%InstallDir%%%s\n" % (mod_dir_string, dir_minus_top_level))
+ f.write("Shortcuts = 0, %CE11% ; \Windows\Start Menu\Programs\n\n")
+
+
+def output_directory_sections(f, dirs):
+ for dir in dirs:
+ if directories[dir].filecount < 1:
+ f.write(";[Files.%s]\n;===NO FILES===\n" % '.'.join( dir.split('\\') ))
+ else:
+ f.write("[Files.%s]\n" % '.'.join( dir.split('\\') ))
+ for entry in file_entries:
+ if entry.dirpath == dir:
+ f.write("\"%s\",%s\n" % (entry.filename, entry.actual_filename))
+ f.write("\n")
+
+
+def output_registry_section(f):
+ f.write("""[RegData] ; registry key list
+HKCU,Software\%AppName%,MajorVersion,0x00010001,1
+HKCU,Software\%AppName%,MinorVersion,0x00010001,0
+\n""")
+
+
+def output_shortcuts_section(f, app_name):
+ f.write("[Shortcuts] ; Shortcut created in destination dir, %CE14%\n")
+ f.write("%%AppName%%,0,%s\n" % app_name)
+
+
+def output_inf_file(program_name, app_name):
+ global files_in_directory
+ inf_name = "%s.inf" % program_name
+ f = open(inf_name, 'w')
+ output_inf_file_header(f, program_name)
+ dirs = sorted(directories)
+ output_sourcedisksnames_section(f, dirs)
+ output_sourcedisksfiles_section(f)
+ output_defaultinstall_section(f, dirs)
+ output_destinationdirs_section(f, dirs)
+ output_directory_sections(f, dirs)
+ output_registry_section(f)
+ output_shortcuts_section(f, app_name)
+ f.close()
+
+
+
+def make_cab_file(cabwiz_path, program_name, cab_final_name):
+ make_cab_command = "\"%s\" %s.inf /compress" % (cabwiz_path, program_name)
+ print "INFORMATION: Executing command to make %s CAB file (only works on BASH)" % program_name
+ print " [%s]" % make_cab_command
+ sys.stdout.flush()
+
+ success = call([cabwiz_path, "%s.inf" % program_name, "/compress"],
+ stdout=open("NUL:","w"), stderr=STDOUT)
+
+ if not os.path.isfile("%s.CAB" % program_name):
+ print """***************************************************************************
+ERROR: CAB FILE NOT CREATED.
+ You can try running the command by hand:
+ %s" % make_cab_comman
+ ----
+ NOTE: If you see an error like this:
+ Error: File XXXXXXXXXX.inf contains DirIDs, which are not supported
+ --
+ this may mean that your PYTHON is outputting Windows files WITHOUT CR-LF
+ line endings. Please verify that your INF file has CR-LF line endings.
+***************************************************************************"""
+ return
+
+ print "INFORMATION: Executing command to move %s.CAB to %s" % (program_name, cab_final_name)
+ sys.stdout.flush()
+ shutil.move("%s.CAB" % program_name, cab_final_name)
+
+
+def purge_copied_files():
+ for entry in file_entries:
+ if entry.filename != entry.actual_filename:
+ new_relative_filename = join(entry.dirpath, entry.actual_filename)
+ os.remove(new_relative_filename)
+
+
+def main():
+ if len(sys.argv) != 5:
+ print >> sys.stderr, "Usage: %s CABWIZ_PATH SOURCE_DIR PROGRAM_NAME CAB_FINAL_NAME" % sys.argv[0]
+ print >> sys.stderr, "Example: %s /c/Program\ Files/Microsoft\ Visual\ Studio\ 9.0/ fennec Fennec fennec-0.11.en-US.wince-arm.cab" % sys.argv[0]
+ sys.exit(1)
+
+ cabwiz_path = sys.argv[1]
+ source_dir = sys.argv[2]
+ program_name = sys.argv[3]
+ app_name = "%s.exe" % source_dir
+ cab_final_name = sys.argv[4]
+
+ if not os.path.isfile(cabwiz_path):
+ print """***************************************************************************
+ERROR: CABWIZ_PATH is not a valid file!
+ Perhaps your VSINSTALLDIR is not properly set up?
+ EXITING...
+***************************************************************************"""
+ sys.exit(2)
+
+ walk_tree(source_dir, ignored_patterns)
+ sys.stdout.flush()
+ output_inf_file(program_name, app_name)
+ sys.stdout.flush()
+ make_cab_file(cabwiz_path, program_name, cab_final_name)
+ purge_copied_files()
+
+
+# run main if run directly
+if __name__ == "__main__":
+ main()
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -67,16 +67,17 @@ installdir = $(libdir)/$(MOZ_APP_NAME)-$
sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_VERSION)
DIST = $(DEPTH)/dist
LIBXUL_SDK = @LIBXUL_SDK@
L10NBASEDIR = @L10NBASEDIR@
LIBXUL_DIST = @LIBXUL_DIST@
+SYSTEM_LIBXUL = @SYSTEM_LIBXUL@
XULRUNNER_STUB_NAME = @XULRUNNER_STUB_NAME@
MOZ_CHROME_FILE_FORMAT = @MOZ_CHROME_FILE_FORMAT@
MOZ_WIDGET_TOOLKIT = @MOZ_WIDGET_TOOLKIT@
MOZ_GFX_TOOLKIT = @MOZ_GFX_TOOLKIT@
MOZ_GFX_OPTIMIZE_MOBILE = @MOZ_GFX_OPTIMIZE_MOBILE@
--- a/configure.in
+++ b/configure.in
@@ -1827,18 +1827,16 @@ case "$target" in
_PLATFORM_DEFAULT_TOOLKIT='cairo-cocoa'
MOZ_ENABLE_POSTSCRIPT=
TARGET_NSPR_MDCPUCFG='\"md/_darwin.cfg\"'
LDFLAGS="$LDFLAGS -framework Cocoa"
# The ExceptionHandling framework is needed for Objective-C exception
# logging code in nsObjCExceptions.h. Currently we only use that in debug
# builds.
MOZ_DEBUG_LDFLAGS="$MOZ_DEBUG_LDFLAGS -framework ExceptionHandling"
- # set MACOSX to generate lib/mac/MoreFiles/Makefile
- MACOSX=1
dnl DTrace and -dead_strip don't interact well. See bug 403132.
dnl ===================================================================
if test "x$enable_dtrace" = "xyes"; then
echo "Skipping -dead_strip because DTrace is enabled. See bug 403132."
else
dnl check for the presence of the -dead_strip linker flag
AC_MSG_CHECKING([for -dead_strip option to ld])
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -129,17 +129,24 @@ nsAsyncInstantiateEvent::Run()
mContent->mPendingInstantiateEvent = nsnull;
// Make sure that we still have the right frame (NOTE: we don't need to check
// the type here - GetExistingFrame() only returns object frames, and that
// means we're a plugin)
// Also make sure that we still refer to the same data.
nsIObjectFrame* frame = mContent->
GetExistingFrame(nsObjectLoadingContent::eFlushContent);
- if (mFrame.IsAlive() &&
+#ifdef DEBUG
+ if (frame && mFrame.IsAlive()) {
+ nsIFrame* objectFrame = do_QueryFrame(frame);
+ NS_ASSERTION(objectFrame == mFrame.GetFrame(), "Wrong frame!");
+ }
+#endif
+ if (frame &&
+ mFrame.IsAlive() &&
mContent->mURI == mURI &&
mContent->mContentType.Equals(mContentType)) {
if (LOG_ENABLED()) {
nsCAutoString spec;
if (mURI) {
mURI->GetSpec(spec);
}
LOG(("OBJLC [%p]: Handling Instantiate event: Type=<%s> URI=%p<%s>\n",
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -39,17 +39,17 @@
* ***** END LICENSE BLOCK ***** */
#include "nsStyledElement.h"
#include "nsGkAtoms.h"
#include "nsAttrValue.h"
#include "nsGenericElement.h"
#include "nsMutationEvent.h"
#include "nsDOMCSSDeclaration.h"
-#include "nsICSSOMFactory.h"
+#include "nsDOMCSSAttrDeclaration.h"
#include "nsServiceManagerUtils.h"
#include "nsIDocument.h"
#include "nsICSSStyleRule.h"
#include "nsICSSParser.h"
#include "nsICSSLoader.h"
#ifdef MOZ_SVG
#include "nsIDOMSVGStylable.h"
@@ -162,38 +162,28 @@ nsStyledElement::BindToTree(nsIDocument*
ReparseStyleAttribute(PR_FALSE);
return rv;
}
// ---------------------------------------------------------------
// Others and helpers
-static nsICSSOMFactory* gCSSOMFactory = nsnull;
-static NS_DEFINE_CID(kCSSOMFactoryCID, NS_CSSOMFACTORY_CID);
-
nsresult
nsStyledElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
{
nsGenericElement::nsDOMSlots *slots = GetDOMSlots();
NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
if (!slots->mStyle) {
// Just in case...
ReparseStyleAttribute(PR_TRUE);
- nsresult rv;
- if (!gCSSOMFactory) {
- rv = CallGetService(kCSSOMFactoryCID, &gCSSOMFactory);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = gCSSOMFactory->CreateDOMCSSAttributeDeclaration(this,
- getter_AddRefs(slots->mStyle));
- NS_ENSURE_SUCCESS(rv, rv);
+ slots->mStyle = new nsDOMCSSAttributeDeclaration(this);
+ NS_ENSURE_TRUE(slots->mStyle, NS_ERROR_OUT_OF_MEMORY);
SetFlags(NODE_MAY_HAVE_STYLE);
}
// Why bother with QI?
NS_ADDREF(*aStyle = slots->mStyle);
return NS_OK;
}
@@ -260,15 +250,8 @@ nsStyledElement::ParseStyleAttribute(nsI
return;
}
}
}
}
aResult.SetTo(aValue);
}
-
-
-/* static */ void
-nsStyledElement::Shutdown()
-{
- NS_IF_RELEASE(gCSSOMFactory);
-}
--- a/content/base/src/nsStyledElement.h
+++ b/content/base/src/nsStyledElement.h
@@ -84,18 +84,16 @@ public:
* @param aValue the value to parse
* @param aResult the resulting HTMLValue [OUT]
*/
static void ParseStyleAttribute(nsIContent* aContent,
const nsAString& aValue,
nsAttrValue& aResult,
PRBool aForceInDataDoc);
- static void Shutdown();
-
protected:
virtual PRBool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult);
nsresult GetStyle(nsIDOMCSSStyleDeclaration** aStyle);
/**
--- a/content/canvas/public/nsICanvasElement.h
+++ b/content/canvas/public/nsICanvasElement.h
@@ -34,20 +34,20 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsICanvasElement_h___
#define nsICanvasElement_h___
#include "nsISupports.h"
-#include "nsRect.h"
class gfxContext;
class nsIFrame;
+struct gfxRect;
// {C234660C-BD06-493e-8583-939A5A158B37}
#define NS_ICANVASELEMENT_IID \
{ 0xc234660c, 0xbd06, 0x493e, { 0x85, 0x83, 0x93, 0x9a, 0x5a, 0x15, 0x8b, 0x37 } }
class nsIRenderingContext;
class nsICanvasRenderingContextInternal;
@@ -86,19 +86,19 @@ public:
/*
* Ask the canvas frame to invalidate itself
*/
NS_IMETHOD InvalidateFrame () = 0;
/*
* Ask the canvas frame to invalidate a portion of the frame; damageRect
- * is relative to the origin of the canvas frame.
+ * is relative to the origin of the canvas frame in CSS pixels.
*/
- NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect) = 0;
+ NS_IMETHOD InvalidateFrameSubrect (const gfxRect& damageRect) = 0;
/*
* Get the number of contexts in this canvas, and request a context at
* an index.
*/
virtual PRInt32 CountContexts () = 0;
virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index) = 0;
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -313,16 +313,18 @@ class nsCanvasRenderingContext2D :
public nsIDOMCanvasRenderingContext2D,
public nsICanvasRenderingContextInternal
{
public:
nsCanvasRenderingContext2D();
virtual ~nsCanvasRenderingContext2D();
nsresult Redraw();
+ // this rect is in CSS pixels
+ nsresult Redraw(const gfxRect& r);
// nsICanvasRenderingContextInternal
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
NS_IMETHOD Render(gfxContext *ctx);
NS_IMETHOD GetInputStream(const char* aMimeType,
const PRUnichar* aEncoderOptions,
nsIInputStream **aStream);
@@ -884,16 +886,30 @@ nsCanvasRenderingContext2D::Redraw()
if (!mIsFrameInvalid) {
mIsFrameInvalid = PR_TRUE;
return mCanvasElement->InvalidateFrame();
}
return NS_OK;
}
+nsresult
+nsCanvasRenderingContext2D::Redraw(const gfxRect& r)
+{
+ if (!mCanvasElement)
+ return NS_OK;
+
+ if (!mIsFrameInvalid) {
+ mIsFrameInvalid = PR_TRUE;
+ return mCanvasElement->InvalidateFrameSubrect(r);
+ }
+
+ return NS_OK;
+}
+
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
{
Destroy();
mWidth = width;
mHeight = height;
@@ -3392,17 +3408,19 @@ nsCanvasRenderingContext2D::DrawWindow(n
// scrollbars should be allowed)
if (!nsContentUtils::IsCallerTrustedForRead()) {
// not permitted to use DrawWindow
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_DOM_SECURITY_ERR;
}
// Flush layout updates
- if (!(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH))
+ PRBool skipFlush =
+ (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH) != 0;
+ if (!skipFlush)
FlushLayoutForTree(aWindow);
nsCOMPtr<nsPresContext> presContext;
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aWindow);
if (win) {
nsIDocShell* docshell = win->GetDocShell();
if (docshell) {
docshell->GetPresContext(getter_AddRefs(presContext));
@@ -3422,23 +3440,33 @@ nsCanvasRenderingContext2D::DrawWindow(n
nsRect r(nsPresContext::CSSPixelsToAppUnits(aX),
nsPresContext::CSSPixelsToAppUnits(aY),
nsPresContext::CSSPixelsToAppUnits(aW),
nsPresContext::CSSPixelsToAppUnits(aH));
PRUint32 renderDocFlags = nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_CARET) {
renderDocFlags |= nsIPresShell::RENDER_CARET;
}
+
+ PRBool oldDisableValue = nsLayoutUtils::sDisableGetUsedXAssertions;
+ nsLayoutUtils::sDisableGetUsedXAssertions = oldDisableValue || skipFlush;
presShell->RenderDocument(r, renderDocFlags, bgColor, mThebes);
+ nsLayoutUtils::sDisableGetUsedXAssertions = oldDisableValue;
// get rid of the pattern surface ref, just in case
mThebes->SetColor(gfxRGBA(1,1,1,1));
DirtyAllStyles();
- Redraw();
+ // note that aX and aY are coordinates in the document that
+ // we're drawing; aX and aY are drawn to 0,0 in current user
+ // space.
+ gfxRect damageRect = mThebes->UserToDevice(gfxRect(0, 0, aW, aH));
+ damageRect.RoundOut();
+
+ Redraw(damageRect);
return rv;
}
//
// device pixel getting/setting
//
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -88,17 +88,16 @@
#include "nsContentUtils.h"
#include "nsString.h"
#include "nsUnicharUtils.h"
#include "nsGkAtoms.h"
#include "nsIEventStateManager.h"
#include "nsIDOMEvent.h"
#include "nsIDOMNSEvent.h"
#include "nsDOMCSSDeclaration.h"
-#include "nsICSSOMFactory.h"
#include "nsITextControlFrame.h"
#include "nsIForm.h"
#include "nsIFormControl.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsMutationEvent.h"
#include "nsContentCID.h"
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -87,17 +87,17 @@ public:
// nsICanvasElement
NS_IMETHOD GetPrimaryCanvasFrame(nsIFrame **aFrame);
NS_IMETHOD GetSize(PRUint32 *width, PRUint32 *height);
NS_IMETHOD RenderContexts(gfxContext *ctx);
virtual PRBool IsWriteOnly();
virtual void SetWriteOnly();
NS_IMETHOD InvalidateFrame ();
- NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect);
+ NS_IMETHOD InvalidateFrameSubrect (const gfxRect& damageRect);
virtual PRInt32 CountContexts();
virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index);
virtual PRBool GetIsOpaque();
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
@@ -550,21 +550,39 @@ nsHTMLCanvasElement::InvalidateFrame()
r.x = r.y = 0;
frame->Invalidate(r);
}
return NS_OK;
}
NS_IMETHODIMP
-nsHTMLCanvasElement::InvalidateFrameSubrect(const nsRect& damageRect)
+nsHTMLCanvasElement::InvalidateFrameSubrect(const gfxRect& damageRect)
{
nsIFrame *frame = GetPrimaryFrame(Flush_Frames);
if (frame) {
- frame->Invalidate(damageRect);
+ nsRect contentArea(frame->GetContentRect());
+ nsIntSize size = GetWidthHeight();
+
+ // damageRect and size are in CSS pixels; contentArea is in appunits
+ // We want a rect in appunits; so avoid doing pixels-to-appunits and
+ // vice versa conversion here.
+ gfxRect realRect(damageRect);
+ realRect.Scale(contentArea.width / gfxFloat(size.width),
+ contentArea.height / gfxFloat(size.height));
+ realRect.RoundOut();
+
+ // then make it a nsRect
+ nsRect invalRect(realRect.X(), realRect.Y(),
+ realRect.Width(), realRect.Height());
+
+ // account for border/padding
+ invalRect.MoveBy(contentArea.TopLeft() - frame->GetPosition());
+
+ frame->Invalidate(invalRect);
}
return NS_OK;
}
PRInt32
nsHTMLCanvasElement::CountContexts()
{
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -821,16 +821,17 @@ nsSVGElement::sViewportsMap[] = {
{ &nsGkAtoms::overflow },
{ &nsGkAtoms::clip },
{ nsnull }
};
// PresentationAttributes-Makers
/* static */ const nsGenericElement::MappedAttributeEntry
nsSVGElement::sMarkersMap[] = {
+ { &nsGkAtoms::marker },
{ &nsGkAtoms::marker_end },
{ &nsGkAtoms::marker_mid },
{ &nsGkAtoms::marker_start },
{ nsnull }
};
// PresentationAttributes-Color
/* static */ const nsGenericElement::MappedAttributeEntry
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -1417,74 +1417,127 @@ nsBindingManager::GetNestedSingleInserti
aMultipleInsertionPoints);
if (nestedPoint)
insertionElement = nestedPoint;
}
return insertionElement;
}
+nsXBLInsertionPoint*
+nsBindingManager::FindInsertionPointAndIndex(nsIContent* aContainer,
+ nsIContent* aInsertionParent,
+ PRUint32 aIndexInContainer,
+ PRInt32 aAppend,
+ PRInt32* aInsertionIndex)
+{
+ PRBool isAnonymousContentList;
+ nsINodeList* nodeList =
+ GetXBLChildNodesInternal(aInsertionParent, &isAnonymousContentList);
+ if (!nodeList || !isAnonymousContentList) {
+ return nsnull;
+ }
+
+ // Find a non-pseudo-insertion point and just jam ourselves in. This is
+ // not 100% correct, since there might be multiple insertion points under
+ // this insertion parent, and we should really be using the one that
+ // matches our content... Hack city, baby.
+ nsAnonymousContentList* contentList =
+ static_cast<nsAnonymousContentList*>(nodeList);
+
+ PRInt32 count = contentList->GetInsertionPointCount();
+ for (PRInt32 i = 0; i < count; i++) {
+ nsXBLInsertionPoint* point = contentList->GetInsertionPointAt(i);
+ if (point->GetInsertionIndex() != -1) {
+ // We're real. Jam the kid in.
+
+ // Find the right insertion spot. Can't just insert in the insertion
+ // point at aIndexInContainer since the point may contain anonymous
+ // content, not all of aContainer's kids, etc. So find the last
+ // child of aContainer that comes before aIndexInContainer and is in
+ // the insertion point and insert right after it.
+ PRInt32 pointSize = point->ChildCount();
+ for (PRInt32 parentIndex = aIndexInContainer - 1; parentIndex >= 0;
+ --parentIndex) {
+ nsIContent* currentSibling = aContainer->GetChildAt(parentIndex);
+ for (PRInt32 pointIndex = pointSize - 1; pointIndex >= 0;
+ --pointIndex) {
+ if (point->ChildAt(pointIndex) == currentSibling) {
+ *aInsertionIndex = pointIndex + 1;
+ return point;
+ }
+ }
+ }
+
+ // None of our previous siblings are in here... just stick
+ // ourselves in at the end of the insertion point if we're
+ // appending, and at the beginning otherwise.
+ // XXXbz if we ever start doing the filter thing right, this may be no
+ // good, since we may _still_ have anonymous kids in there and may need
+ // to get the ordering with those right. In fact, this is even wrong
+ // without the filter thing for nested insertion points, since they might
+ // contain anonymous content that needs to come after all explicit
+ // kids... but we have no way to know that here easily.
+ if (aAppend) {
+ *aInsertionIndex = pointSize;
+ } else {
+ *aInsertionIndex = 0;
+ }
+ return point;
+ }
+ }
+
+ return nsnull;
+}
+
void
nsBindingManager::ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
- // XXX This is hacked and not quite correct. See below.
if (aNewIndexInContainer != -1 &&
(mContentListTable.ops || mAnonymousNodesTable.ops)) {
// It's not anonymous.
+ NS_ASSERTION(aNewIndexInContainer >= 0, "Bogus index");
+
PRBool multiple;
nsIContent* ins = GetNestedSingleInsertionPoint(aContainer, &multiple);
if (multiple) {
// Do each kid individually
PRInt32 childCount = aContainer->GetChildCount();
- NS_ASSERTION(aNewIndexInContainer >= 0, "Bogus index");
for (PRInt32 idx = aNewIndexInContainer; idx < childCount; ++idx) {
HandleChildInsertion(aContainer, aContainer->GetChildAt(idx),
idx, PR_TRUE);
}
}
else if (ins) {
- PRBool isAnonymousContentList;
- nsCOMPtr<nsIDOMNodeList> nodeList =
- GetXBLChildNodesInternal(ins, &isAnonymousContentList);
-
- if (nodeList && isAnonymousContentList) {
- // Find the one non-pseudo-insertion point and just add ourselves.
- nsAnonymousContentList* contentList =
- static_cast<nsAnonymousContentList*>(nodeList.get());
-
- PRInt32 count = contentList->GetInsertionPointCount();
- for (PRInt32 i = 0; i < count; i++) {
- nsXBLInsertionPoint* point = contentList->GetInsertionPointAt(i);
- PRInt32 index = point->GetInsertionIndex();
- if (index != -1) {
- // We're real. Jam all the kids in.
- PRInt32 childCount = aContainer->GetChildCount();
- for (PRInt32 j = aNewIndexInContainer; j < childCount; j++) {
- nsIContent* child = aContainer->GetChildAt(j);
- point->AddChild(child);
- SetInsertionParent(child, ins);
- }
- break;
- }
+ PRInt32 insertionIndex;
+ nsXBLInsertionPoint* point =
+ FindInsertionPointAndIndex(aContainer, ins, aNewIndexInContainer,
+ PR_TRUE, &insertionIndex);
+ if (point) {
+ PRInt32 childCount = aContainer->GetChildCount();
+ for (PRInt32 j = aNewIndexInContainer; j < childCount;
+ j++, insertionIndex++) {
+ nsIContent* child = aContainer->GetChildAt(j);
+ point->InsertChildAt(insertionIndex, child);
+ SetInsertionParent(child, ins);
}
}
}
}
}
void
nsBindingManager::ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
- // XXX This is hacked just to make menus work again.
if (aIndexInContainer != -1 &&
(mContentListTable.ops || mAnonymousNodesTable.ops)) {
// It's not anonymous.
NS_ASSERTION(aIndexInContainer >= 0, "Bogus index");
HandleChildInsertion(aContainer, aChild, aIndexInContainer, PR_FALSE);
}
}
@@ -1635,66 +1688,18 @@ nsBindingManager::HandleChildInsertion(n
NS_PRECONDITION(aChild, "Must have child");
NS_PRECONDITION(!aContainer ||
PRUint32(aContainer->IndexOf(aChild)) == aIndexInContainer,
"Child not at the right index?");
nsIContent* ins = GetNestedInsertionPoint(aContainer, aChild);
if (ins) {
- PRBool isAnonymousContentList;
- nsCOMPtr<nsIDOMNodeList> nodeList =
- GetXBLChildNodesInternal(ins, &isAnonymousContentList);
-
- if (nodeList && isAnonymousContentList) {
- // Find a non-pseudo-insertion point and just jam ourselves in. This is
- // not 100% correct, since there might be multiple insertion points under
- // this insertion parent, and we should really be using the one that
- // matches our content... Hack city, baby.
- nsAnonymousContentList* contentList =
- static_cast<nsAnonymousContentList*>(nodeList.get());
-
- PRInt32 count = contentList->GetInsertionPointCount();
- for (PRInt32 i = 0; i < count; i++) {
- nsXBLInsertionPoint* point = contentList->GetInsertionPointAt(i);
- if (point->GetInsertionIndex() != -1) {
- // We're real. Jam the kid in.
-
- // Find the right insertion spot. Can't just insert in the insertion
- // point at aIndexInContainer since the point may contain anonymous
- // content, not all of aContainer's kids, etc. So find the last
- // child of aContainer that comes before aIndexInContainer and is in
- // the insertion point and insert right after it.
- PRInt32 pointSize = point->ChildCount();
- PRBool inserted = PR_FALSE;
- for (PRInt32 parentIndex = aIndexInContainer - 1;
- parentIndex >= 0 && !inserted; --parentIndex) {
- nsIContent* currentSibling = aContainer->GetChildAt(parentIndex);
- for (PRInt32 pointIndex = pointSize - 1; pointIndex >= 0;
- --pointIndex) {
- nsCOMPtr<nsIContent> currContent = point->ChildAt(pointIndex);
- if (currContent == currentSibling) {
- point->InsertChildAt(pointIndex + 1, aChild);
- inserted = PR_TRUE;
- break;
- }
- }
- }
- if (!inserted) {
- // None of our previous siblings are in here... just stick
- // ourselves in at the end of the insertion point if we're
- // appending, and at the beginning otherwise.
- // XXXbz if we ever start doing the filter thing right, this may be
- // no good, since we may _still_ have anonymous kids in there and
- // may need to get the ordering with those right.
- if (aAppend) {
- point->AddChild(aChild);
- } else {
- point->InsertChildAt(0, aChild);
- }
- }
- SetInsertionParent(aChild, ins);
- break;
- }
- }
+ PRInt32 insertionIndex;
+ nsXBLInsertionPoint* point =
+ FindInsertionPointAndIndex(aContainer, ins, aIndexInContainer, aAppend,
+ &insertionIndex);
+ if (point) {
+ point->InsertChildAt(insertionIndex, aChild);
+ SetInsertionParent(aChild, ins);
}
}
}
--- a/content/xbl/src/nsBindingManager.h
+++ b/content/xbl/src/nsBindingManager.h
@@ -237,16 +237,29 @@ protected:
// Called by ContentAppended and ContentInserted to handle a single child
// insertion. aChild must not be null. aContainer may be null.
// aIndexInContainer is the index of the child in the parent. aAppend is
// true if this child is being appended, not inserted.
void HandleChildInsertion(nsIContent* aContainer, nsIContent* aChild,
PRUint32 aIndexInContainer, PRBool aAppend);
+ // For the given container under which a child is being added, given
+ // insertion parent and given index of the child being inserted, find the
+ // right nsXBLInsertionPoint and the right index in that insertion point to
+ // insert it at. If null is returned, aInsertionIndex might be garbage.
+ // aAppend controls what should be returned as the aInsertionIndex if the
+ // right index can't be found. If true, the length of the insertion point
+ // will be returned; otherwise 0 will be returned.
+ nsXBLInsertionPoint* FindInsertionPointAndIndex(nsIContent* aContainer,
+ nsIContent* aInsertionParent,
+ PRUint32 aIndexInContainer,
+ PRInt32 aAppend,
+ PRInt32* aInsertionIndex);
+
// Same as ProcessAttachedQueue, but also nulls out
// mProcessAttachedQueueEvent
void DoProcessAttachedQueue();
// Post an event to process the attached queue.
void PostProcessAttachedQueueEvent();
// MEMBER VARIABLES
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -98,16 +98,17 @@
#include "nsIRDFService.h"
#include "nsIScriptContext.h"
#include "nsIScriptRuntime.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptGlobalObjectOwner.h"
#include "nsIServiceManager.h"
#include "nsICSSStyleRule.h"
#include "nsIStyleSheet.h"
+#include "nsDOMCSSAttrDeclaration.h"
#include "nsIURL.h"
#include "nsIViewManager.h"
#include "nsIWidget.h"
#include "nsIXULDocument.h"
#include "nsIXULTemplateBuilder.h"
#include "nsIXBLService.h"
#include "nsLayoutCID.h"
#include "nsContentCID.h"
@@ -154,17 +155,16 @@
#include "mozAutoDocUpdate.h"
#include "nsIDOMXULCommandEvent.h"
#include "nsIDOMNSEvent.h"
#include "nsCCUncollectableMarker.h"
// Global object maintenance
nsICSSParser* nsXULPrototypeElement::sCSSParser = nsnull;
nsIXBLService * nsXULElement::gXBLService = nsnull;
-nsICSSOMFactory* nsXULElement::gCSSOMFactory = nsnull;
/**
* A tearoff class for nsXULElement to implement nsIScriptEventHandlerOwner.
*/
class nsScriptEventHandlerOwnerTearoff : public nsIScriptEventHandlerOwner
{
public:
nsScriptEventHandlerOwnerTearoff(nsXULElement* aElement)
@@ -186,17 +186,16 @@ public:
private:
nsRefPtr<nsXULElement> mElement;
};
//----------------------------------------------------------------------
static NS_DEFINE_CID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
-static NS_DEFINE_CID(kCSSOMFactoryCID, NS_CSSOMFACTORY_CID);
//----------------------------------------------------------------------
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
PRUint32 nsXULPrototypeAttribute::gNumElements;
PRUint32 nsXULPrototypeAttribute::gNumAttributes;
PRUint32 nsXULPrototypeAttribute::gNumEventHandlers;
PRUint32 nsXULPrototypeAttribute::gNumCacheTests;
@@ -1924,24 +1923,18 @@ nsXULElement::GetStyle(nsIDOMCSSStyleDec
NS_ENSURE_SUCCESS(rv, rv);
}
}
nsDOMSlots* slots = GetDOMSlots();
NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
if (!slots->mStyle) {
- if (!gCSSOMFactory) {
- rv = CallGetService(kCSSOMFactoryCID, &gCSSOMFactory);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = gCSSOMFactory->CreateDOMCSSAttributeDeclaration(this,
- getter_AddRefs(slots->mStyle));
- NS_ENSURE_SUCCESS(rv, rv);
+ slots->mStyle = new nsDOMCSSAttributeDeclaration(this);
+ NS_ENSURE_TRUE(slots->mStyle, NS_ERROR_OUT_OF_MEMORY);
SetFlags(NODE_MAY_HAVE_STYLE);
}
NS_IF_ADDREF(*aStyle = slots->mStyle);
return NS_OK;
}
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -65,17 +65,16 @@
#include "nsIRDFCompositeDataSource.h"
#include "nsIRDFResource.h"
#include "nsIScriptObjectOwner.h"
#include "nsBindingManager.h"
#include "nsIURI.h"
#include "nsIXULTemplateBuilder.h"
#include "nsIBoxObject.h"
#include "nsIXBLService.h"
-#include "nsICSSOMFactory.h"
#include "nsLayoutCID.h"
#include "nsAttrAndChildArray.h"
#include "nsGkAtoms.h"
#include "nsAutoPtr.h"
#include "nsGenericElement.h"
#include "nsDOMScriptObjectHolder.h"
#include "nsIFrameLoader.h"
@@ -485,23 +484,21 @@ public:
public:
static nsIXBLService* GetXBLService() {
if (!gXBLService)
CallGetService("@mozilla.org/xbl;1", &gXBLService);
return gXBLService;
}
static void ReleaseGlobals() {
NS_IF_RELEASE(gXBLService);
- NS_IF_RELEASE(gCSSOMFactory);
}
protected:
// pseudo-constants
static nsIXBLService* gXBLService;
- static nsICSSOMFactory* gCSSOMFactory;
public:
static nsresult
Create(nsXULPrototypeElement* aPrototype, nsIDocument* aDocument,
PRBool aIsScriptable, nsIContent** aResult);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -747,39 +747,16 @@ nsHTMLEditor::GetBlockNodeParent(nsIDOMN
if ( NS_FAILED(p->GetParentNode(getter_AddRefs(tmp))) || !tmp) // no parent, ran off top of tree
return p;
p = tmp;
}
return p;
}
-
-///////////////////////////////////////////////////////////////////////////
-// HasSameBlockNodeParent: true if nodes have same block level ancestor
-//
-PRBool
-nsHTMLEditor::HasSameBlockNodeParent(nsIDOMNode *aNode1, nsIDOMNode *aNode2)
-{
- if (!aNode1 || !aNode2)
- {
- NS_NOTREACHED("null node passed to HasSameBlockNodeParent()");
- return PR_FALSE;
- }
-
- if (aNode1 == aNode2)
- return PR_TRUE;
-
- nsCOMPtr<nsIDOMNode> p1 = GetBlockNodeParent(aNode1);
- nsCOMPtr<nsIDOMNode> p2 = GetBlockNodeParent(aNode2);
-
- return (p1 == p2);
-}
-
-
///////////////////////////////////////////////////////////////////////////
// GetBlockSection: return leftmost/rightmost nodes in aChild's block
//
nsresult
nsHTMLEditor::GetBlockSection(nsIDOMNode *aChild,
nsIDOMNode **aLeftNode,
nsIDOMNode **aRightNode)
{
@@ -2170,127 +2147,16 @@ nsHTMLEditor::SetParagraphFormat(const n
nsAutoString tag; tag.Assign(aParagraphFormat);
ToLowerCase(tag);
if (tag.EqualsLiteral("dd") || tag.EqualsLiteral("dt"))
return MakeDefinitionItem(tag);
else
return InsertBasicBlock(tag);
}
-// XXX: ERROR_HANDLING -- this method needs a little work to ensure all error codes are
-// checked properly, all null pointers are checked, and no memory leaks occur
-NS_IMETHODIMP
-nsHTMLEditor::GetParentBlockTags(nsTArray<nsString> *aTagList, PRBool aGetLists)
-{
- nsresult res;
- nsCOMPtr<nsISelection>selection;
- res = GetSelection(getter_AddRefs(selection));
- if (NS_FAILED(res)) return res;
- if (!selection) return NS_ERROR_NULL_POINTER;
- nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
-
- // Find out if the selection is collapsed:
- PRBool isCollapsed;
- res = selection->GetIsCollapsed(&isCollapsed);
- if (NS_FAILED(res)) return res;
- if (isCollapsed)
- {
- nsCOMPtr<nsIDOMNode> node, blockParent;
- PRInt32 offset;
-
- res = GetStartNodeAndOffset(selection, address_of(node), &offset);
- if (!node) res = NS_ERROR_FAILURE;
- if (NS_FAILED(res)) return res;
-
- nsCOMPtr<nsIDOMElement> blockParentElem;
- if (aGetLists)
- {
- // Get the "ol", "ul", or "dl" parent element
- res = GetElementOrParentByTagName(NS_LITERAL_STRING("list"), node, getter_AddRefs(blockParentElem));
- if (NS_FAILED(res)) return res;
- }
- else
- {
- PRBool isBlock (PR_FALSE);
- NodeIsBlock(node, &isBlock);
- if (isBlock) blockParent = node;
- else blockParent = GetBlockNodeParent(node);
- blockParentElem = do_QueryInterface(blockParent);
- }
- if (blockParentElem)
- {
- nsAutoString blockParentTag;
- blockParentElem->GetTagName(blockParentTag);
- aTagList->AppendElement(blockParentTag);
- }
-
- return res;
- }
-
- // else non-collapsed selection
- nsCOMPtr<nsIEnumerator> enumerator;
- res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
- if (NS_FAILED(res)) return res;
- if (!enumerator) return NS_ERROR_NULL_POINTER;
-
- enumerator->First();
- nsCOMPtr<nsISupports> currentItem;
- res = enumerator->CurrentItem(getter_AddRefs(currentItem));
- if (NS_FAILED(res)) return res;
- //XXX: should be while loop?
- if (currentItem)
- {
- nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
- // scan the range for all the independent block content blockSections
- // and get the block parent of each
- nsCOMArray<nsIDOMRange> blockSections;
- res = GetBlockSectionsForRange(range, blockSections);
- if (NS_SUCCEEDED(res))
- {
- nsCOMPtr<nsIDOMRange> subRange = blockSections[0];
- while (subRange)
- {
- nsCOMPtr<nsIDOMNode>startParent;
- res = subRange->GetStartContainer(getter_AddRefs(startParent));
- if (NS_SUCCEEDED(res) && startParent)
- {
- nsCOMPtr<nsIDOMElement> blockParent;
- if (aGetLists)
- {
- // Get the "ol", "ul", or "dl" parent element
- res = GetElementOrParentByTagName(NS_LITERAL_STRING("list"), startParent, getter_AddRefs(blockParent));
- }
- else
- {
- blockParent = do_QueryInterface(GetBlockNodeParent(startParent));
- }
- if (NS_SUCCEEDED(res) && blockParent)
- {
- nsAutoString blockParentTag;
- blockParent->GetTagName(blockParentTag);
- PRBool isRoot;
- IsRootTag(blockParentTag, isRoot);
- if ((!isRoot) && !aTagList->Contains(blockParentTag)) {
- aTagList->AppendElement(blockParentTag);
- }
- }
- }
- if (NS_FAILED(res))
- return res;
- blockSections.RemoveObject(0);
- if (blockSections.Count() == 0)
- break;
- subRange = blockSections[0];
- }
- }
- }
- return res;
-}
-
-
NS_IMETHODIMP
nsHTMLEditor::GetParagraphState(PRBool *aMixed, nsAString &outFormat)
{
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
if (!aMixed) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIHTMLEditRules> htmlRules = do_QueryInterface(mRules);
if (!htmlRules) return NS_ERROR_FAILURE;
@@ -2327,30 +2193,16 @@ nsHTMLEditor::GetHighlightColorState(PRB
// in CSS mode, text background can be added by the Text Highlight button
// we need to query the background of the selection without looking for
// the block container of the ranges in the selection
res = GetCSSBackgroundColorState(aMixed, aOutColor, PR_FALSE);
}
return res;
}
-NS_IMETHODIMP
-nsHTMLEditor::GetHighlightColor(PRBool *aMixed, PRUnichar **_retval)
-{
- if (!aMixed || !_retval) return NS_ERROR_NULL_POINTER;
- nsAutoString outColorString(NS_LITERAL_STRING("transparent"));
- *aMixed = PR_FALSE;
-
- nsresult err = NS_NOINTERFACE;
- err = GetHighlightColorState(aMixed, outColorString);
- *_retval = ToNewUnicode(outColorString);
- return err;
-}
-
-
nsresult
nsHTMLEditor::GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor, PRBool aBlockLevel)
{
if (!aMixed) return NS_ERROR_NULL_POINTER;
*aMixed = PR_FALSE;
// the default background color is transparent
aOutColor.AssignLiteral("transparent");
@@ -4420,54 +4272,16 @@ nsHTMLEditor::IsRootTag(nsString &aTag,
aIsTag = PR_TRUE;
}
else {
aIsTag = PR_FALSE;
}
return NS_OK;
}
-NS_IMETHODIMP
-nsHTMLEditor::IsSubordinateBlock(nsString &aTag, PRBool &aIsTag)
-{
- static char p[] = "p";
- static char h1[] = "h1";
- static char h2[] = "h2";
- static char h3[] = "h3";
- static char h4[] = "h4";
- static char h5[] = "h5";
- static char h6[] = "h6";
- static char address[] = "address";
- static char pre[] = "pre";
- static char li[] = "li";
- static char dt[] = "dt";
- static char dd[] = "dd";
- if (aTag.EqualsIgnoreCase(p) ||
- aTag.EqualsIgnoreCase(h1) ||
- aTag.EqualsIgnoreCase(h2) ||
- aTag.EqualsIgnoreCase(h3) ||
- aTag.EqualsIgnoreCase(h4) ||
- aTag.EqualsIgnoreCase(h5) ||
- aTag.EqualsIgnoreCase(h6) ||
- aTag.EqualsIgnoreCase(address) ||
- aTag.EqualsIgnoreCase(pre) ||
- aTag.EqualsIgnoreCase(li) ||
- aTag.EqualsIgnoreCase(dt) ||
- aTag.EqualsIgnoreCase(dd) )
- {
- aIsTag = PR_TRUE;
- }
- else {
- aIsTag = PR_FALSE;
- }
- return NS_OK;
-}
-
-
-
///////////////////////////////////////////////////////////////////////////
// GetEnclosingTable: find ancestor who is a table, if any
//
nsCOMPtr<nsIDOMNode>
nsHTMLEditor::GetEnclosingTable(nsIDOMNode *aNode)
{
NS_PRECONDITION(aNode, "null node passed to nsHTMLEditor::GetEnclosingTable");
nsCOMPtr<nsIDOMNode> tbl, tmp, node = aNode;
@@ -4582,60 +4396,16 @@ nsHTMLEditor::CollapseAdjacentTextNodes(
}
textNodes.RemoveElementAt(0); // remove the leftmost text node from the list
}
return result;
}
-NS_IMETHODIMP
-nsHTMLEditor::GetNextElementByTagName(nsIDOMElement *aCurrentElement,
- const nsAString *aTagName,
- nsIDOMElement **aReturn)
-{
- nsresult res = NS_OK;
- if (!aCurrentElement || !aTagName || !aReturn)
- return NS_ERROR_NULL_POINTER;
-
- nsCOMPtr<nsIAtom> tagAtom = do_GetAtom(*aTagName);
- if (!tagAtom) { return NS_ERROR_NULL_POINTER; }
- if (tagAtom==nsEditProperty::th)
- tagAtom=nsEditProperty::td;
-
- nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(aCurrentElement);
- if (!currentNode)
- return NS_ERROR_FAILURE;
-
- *aReturn = nsnull;
-
- nsCOMPtr<nsIDOMNode> nextNode;
- PRBool done = PR_FALSE;
-
- do {
- res = GetNextNode(currentNode, PR_TRUE, address_of(nextNode));
- if (NS_FAILED(res)) return res;
- if (!nextNode) break;
-
- if (GetTag(currentNode) == tagAtom)
- {
- nsCOMPtr<nsIDOMElement> element = do_QueryInterface(currentNode);
- if (!element) return NS_ERROR_NULL_POINTER;
-
- *aReturn = element;
- NS_ADDREF(*aReturn);
- done = PR_TRUE;
- return NS_OK;
- }
- currentNode = nextNode;
- } while (!done);
-
- return res;
-}
-
NS_IMETHODIMP
nsHTMLEditor::SetSelectionAtDocumentStart(nsISelection *aSelection)
{
nsIDOMElement *rootElement = GetRoot();
if (!rootElement)
return NS_ERROR_NULL_POINTER;
return aSelection->Collapse(rootElement,0);
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -167,24 +167,19 @@ public:
NS_DECL_NSIHTMLINLINETABLEEDITOR
/* ------------ nsIHTMLEditor methods -------------- */
NS_IMETHOD CopyLastEditableChildStyles(nsIDOMNode *aPreviousBlock, nsIDOMNode *aNewBlock,
nsIDOMNode **aOutBrNode);
NS_IMETHOD LoadHTML(const nsAString &aInputString);
- NS_IMETHOD GetParentBlockTags(nsTArray<nsString> *aTagList, PRBool aGetLists);
-
nsresult GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor,
PRBool aBlockLevel);
NS_IMETHOD GetHTMLBackgroundColorState(PRBool *aMixed, nsAString &outColor);
- NS_IMETHOD GetHighlightColor(PRBool *mixed, PRUnichar **_retval);
-
- NS_IMETHOD GetNextElementByTagName(nsIDOMElement *aCurrentElement, const nsAString *aTagName, nsIDOMElement **aReturn);
/* ------------ nsIEditorStyleSheets methods -------------- */
NS_IMETHOD AddStyleSheet(const nsAString & aURL);
NS_IMETHOD ReplaceStyleSheet(const nsAString& aURL);
NS_IMETHOD RemoveStyleSheet(const nsAString &aURL);
NS_IMETHOD AddOverrideStyleSheet(const nsAString & aURL);
@@ -226,18 +221,16 @@ public:
PRInt32 aRowIndex, PRInt32 aColIndex,
nsIDOMElement **aCell,
PRInt32* aStartRowIndex, PRInt32* aStartColIndex,
PRInt32* aRowSpan, PRInt32* aColSpan,
PRInt32* aActualRowSpan, PRInt32* aActualColSpan,
PRBool* aIsSelected);
NS_IMETHOD GetFirstRow(nsIDOMElement* aTableElement, nsIDOMNode** aRowNode);
NS_IMETHOD GetNextRow(nsIDOMNode* aCurrentRowNode, nsIDOMNode** aRowNode);
- NS_IMETHOD GetFirstCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode);
- NS_IMETHOD GetNextCellInRow(nsIDOMNode* aCurrentCellNode, nsIDOMNode** aRowNode);
NS_IMETHOD GetLastCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode);
NS_IMETHOD SetSelectionAfterTableEdit(nsIDOMElement* aTable, PRInt32 aRow, PRInt32 aCol,
PRInt32 aDirection, PRBool aSelected);
NS_IMETHOD GetSelectedOrParentTableElement(nsAString& aTagName,
PRInt32 *aSelectedCount,
nsIDOMElement** aTableElement);
NS_IMETHOD GetSelectedCellsType(nsIDOMElement *aElement, PRUint32 *aSelectionType);
@@ -260,17 +253,16 @@ public:
/* miscellaneous */
// This sets background on the appropriate container element (table, cell,)
// or calls into nsTextEditor to set the page background
NS_IMETHOD SetCSSBackgroundColor(const nsAString& aColor);
NS_IMETHOD SetHTMLBackgroundColor(const nsAString& aColor);
/* ------------ Block methods moved from nsEditor -------------- */
static nsCOMPtr<nsIDOMNode> GetBlockNodeParent(nsIDOMNode *aNode);
- static PRBool HasSameBlockNodeParent(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
/** Determines the bounding nodes for the block section containing aNode.
* The calculation is based on some nodes intrinsically being block elements
* acording to HTML. Style sheets are not considered in this calculation.
* <BR> tags separate block content sections. So the HTML markup:
* <PRE>
* <P>text1<BR>text2<B>text3</B></P>
* </PRE>
* contains two block content sections. The first has the text node "text1"
@@ -388,24 +380,16 @@ public:
/** returns the absolute position of the end points of aSelection
* in the document as a text stream.
*/
nsresult GetTextSelectionOffsets(nsISelection *aSelection,
PRInt32 &aStartOffset,
PRInt32 &aEndOffset);
- nsresult GetAbsoluteOffsetsForPoints(nsIDOMNode *aInStartNode,
- PRInt32 aInStartOffset,
- nsIDOMNode *aInEndNode,
- PRInt32 aInEndOffset,
- nsIDOMNode *aInCommonParentNode,
- PRInt32 &aOutStartOffset,
- PRInt32 &aEndOffset);
-
// Use this to assure that selection is set after attribute nodes when
// trying to collapse selection at begining of a block node
// e.g., when setting at beginning of a table cell
// This will stop at a table, however, since we don't want to
// "drill down" into nested tables.
// aSelection is optional -- if null, we get current seletion
nsresult CollapseSelectionToDeepestNonTableFirstChild(nsISelection *aSelection, nsIDOMNode *aNode);
@@ -421,17 +405,16 @@ public:
nsresult IsEmptyNodeImpl(nsIDOMNode *aNode,
PRBool *outIsEmptyBlock,
PRBool aMozBRDoesntCount,
PRBool aListOrCellNotEmpty,
PRBool aSafeToAskFrames,
PRBool *aSeenBR);
// Stylesheet-related methods that aren't part of nsIEditorStyleSheets.
- nsresult AddCSSStyleSheet(nsICSSStyleSheet* aSheet);
nsresult GetCSSLoader(const nsAString& aURL, nsICSSLoader** aCSSLoader);
// Returns TRUE if sheet was loaded, false if it wasn't
PRBool EnableExistingStyleSheet(const nsAString& aURL);
// Dealing with the internal style sheet lists:
NS_IMETHOD GetStyleSheetForURL(const nsAString &aURL,
nsICSSStyleSheet **_retval);
@@ -538,18 +521,16 @@ protected:
// Fallback method: Call this after using ClearSelection() and you
// failed to set selection to some other content in the document
NS_IMETHOD SetSelectionAtDocumentStart(nsISelection *aSelection);
// End of Table Editing utilities
NS_IMETHOD IsRootTag(nsString &aTag, PRBool &aIsTag);
- NS_IMETHOD IsSubordinateBlock(nsString &aTag, PRBool &aIsTag);
-
virtual PRBool IsBlockNode(nsIDOMNode *aNode);
static nsCOMPtr<nsIDOMNode> GetEnclosingTable(nsIDOMNode *aNode);
/** content-based query returns PR_TRUE if <aProperty aAttribute=aValue> effects aNode
* If <aProperty aAttribute=aValue> contains aNode,
* but <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
* more deeply nested than the first, then the first does not effect aNode.
@@ -567,21 +548,16 @@ protected:
virtual void IsTextPropertySetByContent(nsIDOMNode *aNode,
nsIAtom *aProperty,
const nsAString *aAttribute,
const nsAString *aValue,
PRBool &aIsSet,
nsIDOMNode **aStyleNode,
nsAString *outValue = nsnull);
- void ResetTextSelectionForRange(nsIDOMNode *aParent,
- PRInt32 aStartOffset,
- PRInt32 aEndOffset,
- nsISelection *aSelection);
-
// Methods for handling plaintext quotations
NS_IMETHOD PasteAsPlaintextQuotation(PRInt32 aSelectionType);
/** Insert a string as quoted text,
* replacing the selected text (if any).
* @param aQuotedText The string to insert.
* @param aAddCites Whether to prepend extra ">" to each line
* (usually true, unless those characters
--- a/editor/libeditor/html/nsTableEditor.cpp
+++ b/editor/libeditor/html/nsTableEditor.cpp
@@ -387,80 +387,16 @@ nsHTMLEditor::GetNextRow(nsIDOMNode* aCu
parentSibling = nextNode;
}
// If here, row was not found
return NS_EDITOR_ELEMENT_NOT_FOUND;
}
NS_IMETHODIMP
-nsHTMLEditor::GetFirstCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode)
-{
- if (!aCellNode) return NS_ERROR_NULL_POINTER;
-
- *aCellNode = nsnull;
-
- if (!aRowNode) return NS_ERROR_NULL_POINTER;
-
- nsCOMPtr<nsIDOMNode> rowChild;
- nsresult res = aRowNode->GetFirstChild(getter_AddRefs(rowChild));
- if (NS_FAILED(res)) return res;
-
- while (rowChild && !nsHTMLEditUtils::IsTableCell(rowChild))
- {
- // Skip over textnodes
- nsCOMPtr<nsIDOMNode> nextChild;
- res = rowChild->GetNextSibling(getter_AddRefs(nextChild));
- if (NS_FAILED(res)) return res;
-
- rowChild = nextChild;
- };
- if (rowChild)
- {
- *aCellNode = rowChild.get();
- NS_ADDREF(*aCellNode);
- return NS_OK;
- }
- // If here, cell was not found
- return NS_EDITOR_ELEMENT_NOT_FOUND;
-}
-
-NS_IMETHODIMP
-nsHTMLEditor::GetNextCellInRow(nsIDOMNode* aCurrentCellNode, nsIDOMNode** aCellNode)
-{
- if (!aCellNode) return NS_ERROR_NULL_POINTER;
-
- *aCellNode = nsnull;
-
- if (!aCurrentCellNode) return NS_ERROR_NULL_POINTER;
-
- nsCOMPtr<nsIDOMNode> nextCell;
- nsresult res = aCurrentCellNode->GetNextSibling(getter_AddRefs(nextCell));
- if (NS_FAILED(res)) return res;
-
- while (nextCell && !nsHTMLEditUtils::IsTableCell(nextCell))
- {
- // Skip over textnodes
- nsCOMPtr<nsIDOMNode> nextChild;
- res = nextCell->GetNextSibling(getter_AddRefs(nextChild));
- if (NS_FAILED(res)) return res;
-
- nextCell = nextChild;
- };
- if (nextCell)
- {
- *aCellNode = nextCell.get();
- NS_ADDREF(*aCellNode);
- return NS_OK;
- }
- // If here, cell was not found
- return NS_EDITOR_ELEMENT_NOT_FOUND;
-}
-
-NS_IMETHODIMP
nsHTMLEditor::GetLastCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode)
{
if (!aCellNode) return NS_ERROR_NULL_POINTER;
*aCellNode = nsnull;
if (!aRowNode) return NS_ERROR_NULL_POINTER;
--- a/editor/txtsvc/public/nsITextServicesDocument.h
+++ b/editor/txtsvc/public/nsITextServicesDocument.h
@@ -72,121 +72,71 @@ public:
typedef enum { eBlockNotFound=0, // There is no text block (TB) in or before the selection (S).
eBlockOutside, // No TB in S, but found one before/after S.
eBlockInside, // S extends beyond the start and end of TB.
eBlockContains, // TB contains entire S.
eBlockPartial // S begins or ends in TB but extends outside of TB.
} TSDBlockSelectionStatus;
/**
- * Initializes the text services document to use a particular
- * DOM document.
- * @param aDOMDocument is the document to use. It is AddRef'd
- * by this method.
- * @param aPresShell is the presentation shell to use when
- * setting the selection. It is AddRef'd by this method.
- */
- NS_IMETHOD InitWithDocument(nsIDOMDocument *aDOMDocument, nsIPresShell *aPresShell) = 0;
-
- /**
* Get the DOM document for the document in use.
* @return aDocument the dom document [OUT]
*/
NS_IMETHOD GetDocument(nsIDOMDocument **aDocument) = 0;
/**
* Initializes the text services document to use a particular
* editor. The text services document will use the DOM document
* and presentation shell used by the editor.
* @param aEditor is the editor to use. The editor is AddRef'd
* by this method.
*/
NS_IMETHOD InitWithEditor(nsIEditor *aEditor) = 0;
/**
* Sets the range/extent over which the text services document
- * will iterate. Note that InitWithDocument() or InitWithEditor()
- * should have been called prior to calling this method. If this
- * method is never called, the text services defaults to iterating
- * over the entire document.
+ * will iterate. Note that InitWithEditor() should have been called prior to
+ * calling this method. If this method is never called, the text services
+ * defaults to iterating over the entire document.
*
* @param aDOMRange is the range to use. aDOMRange must point to a
* valid range object.
*/
NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange) = 0;
/**
- * Gets the range that the text services document
- * is currently iterating over. If SetExtent() was never
- * called, this method will return a range that spans the
- * entire body of the document.
- *
- * @param aDOMRange will contain an AddRef'd pointer to the range.
- */
- NS_IMETHOD GetExtent(nsIDOMRange** aDOMRange) = 0;
-
- /**
* Expands the end points of the range so that it spans complete words.
* This call does not change any internal state of the text services document.
*
* @param aDOMRange the range to be expanded/adjusted.
*/
NS_IMETHOD ExpandRangeToWordBoundaries(nsIDOMRange *aRange) = 0;
/**
* Sets the filter to be used while iterating over content.
* @param aFilter filter to be used while iterating over content.
*/
NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter) = 0;
/**
- * Returns true if the document can be modified with calls
- * to DeleteSelection() and InsertText().
- * @param aCanEdit is true if the document can be modified,
- * false if it can't.
- */
- NS_IMETHOD CanEdit(PRBool *aCanEdit) = 0;
-
- /**
* Returns the text in the current text block.
* @param aStr will contain the text.
*/
NS_IMETHOD GetCurrentTextBlock(nsString *aStr) = 0;
/**
* Tells the document to point to the first text block
* in the document. This method does not adjust the current
* cursor position or selection.
*/
NS_IMETHOD FirstBlock() = 0;
/**
- * Tells the document to point to the last text block in the
- * document. This method does not adjust the current cursor
- * position or selection.
- */
-
- NS_IMETHOD LastBlock() = 0;
-
- /**
- * Tells the document to point to the first text block that
- * contains the current selection or caret.
- * @param aSelectionStatus will contain the text block selection status
- * @param aSelectionOffset will contain the offset into the
- * string returned by GetCurrentTextBlock() where the selection
- * begins.
- * @param aLength will contain the number of characters that are
- * selected in the string.
- */
-
- NS_IMETHOD FirstSelectedBlock(TSDBlockSelectionStatus *aSelectionStatus, PRInt32 *aSelectionOffset, PRInt32 *aSelectionLength) = 0;
-
- /**
* Tells the document to point to the last text block that
* contains the current selection or caret.
* @param aSelectionStatus will contain the text block selection status
* @param aSelectionOffset will contain the offset into the
* string returned by GetCurrentTextBlock() where the selection
* begins.
* @param aLength will contain the number of characters that are
* selected in the string.
@@ -254,30 +204,15 @@ public:
/**
* Inserts the given text at the current cursor position.
* If there is a selection, it will be deleted before the
* text is inserted.
*/
NS_IMETHOD InsertText(const nsString *aText) = 0;
-
- /**
- * Sets the display style for the text selected by SetSelection().
- * @param aStyle is the style to apply to the selected text.
- */
-
- NS_IMETHOD SetDisplayStyle(TSDDisplayStyle aStyle) = 0;
-
- /**
- * Returns the DOM range for a given offset and length
- * @param aOffset offset into string returned by GetCurrentTextBlock().
- * @param aLength number characters selected.
- * @return aDOMRange the DOM range that represents the offset and length
- */
- NS_IMETHOD GetDOMRangeFor(PRInt32 aOffset, PRInt32 aLength, nsIDOMRange** aRange) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsITextServicesDocument,
NS_ITEXTSERVICESDOCUMENT_IID)
#endif // nsITextServicesDocument_h__
--- a/editor/txtsvc/src/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/src/nsTextServicesDocument.cpp
@@ -167,56 +167,16 @@ nsrefcnt nsTextServicesDocument::Release
NS_IMPL_ADDREF(nsTextServicesDocument)
NS_IMPL_RELEASE(nsTextServicesDocument)
#endif
NS_IMPL_QUERY_INTERFACE1(nsTextServicesDocument, nsITextServicesDocument)
NS_IMETHODIMP
-nsTextServicesDocument::InitWithDocument(nsIDOMDocument *aDOMDocument, nsIPresShell *aPresShell)
-{
- nsresult result = NS_OK;
-
- if (!aDOMDocument || !aPresShell)
- return NS_ERROR_NULL_POINTER;
-
- NS_ASSERTION(!mSelCon, "mSelCon already initialized!");
-
- if (mSelCon)
- return NS_ERROR_FAILURE;
-
- NS_ASSERTION(!mDOMDocument, "mDOMDocument already initialized!");
-
- if (mDOMDocument)
- return NS_ERROR_FAILURE;
-
- LOCK_DOC(this);
-
- mSelCon = do_QueryInterface(aPresShell);
- mDOMDocument = do_QueryInterface(aDOMDocument);
-
- result = CreateDocumentContentIterator(getter_AddRefs(mIterator));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- mIteratorStatus = nsTextServicesDocument::eIsDone;
-
- result = FirstBlock();
-
- UNLOCK_DOC(this);
-
- return result;
-}
-
-NS_IMETHODIMP
nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
{
nsresult result = NS_OK;
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsIDOMDocument> doc;
if (!aEditor)
return NS_ERROR_NULL_POINTER;
@@ -354,37 +314,16 @@ nsTextServicesDocument::SetExtent(nsIDOM
result = FirstBlock();
UNLOCK_DOC(this);
return result;
}
NS_IMETHODIMP
-nsTextServicesDocument::GetExtent(nsIDOMRange** aDOMRange)
-{
- NS_ENSURE_ARG_POINTER(aDOMRange);
-
- *aDOMRange = nsnull;
-
- if (mExtent)
- {
- // We have an extent range, so just return a
- // copy of it.
-
- return mExtent->CloneRange(aDOMRange);
- }
-
- // We don't have an extent range, so we must be
- // iterating over the entire document.
-
- return CreateDocumentContentRange(aDOMRange);
-}
-
-NS_IMETHODIMP
nsTextServicesDocument::ExpandRangeToWordBoundaries(nsIDOMRange *aRange)
{
NS_ENSURE_ARG_POINTER(aRange);
// Get the end points of the range.
nsCOMPtr<nsIDOMNode> rngStartNode, rngEndNode;
PRInt32 rngStartOffset, rngEndOffset;
@@ -551,29 +490,16 @@ nsTextServicesDocument::SetFilter(nsITex
{
// Hang on to the filter so we can set it into the filtered iterator.
mTxtSvcFilter = aFilter;
return NS_OK;
}
NS_IMETHODIMP
-nsTextServicesDocument::CanEdit(PRBool *aCanEdit)
-{
- if (!aCanEdit)
- return NS_ERROR_NULL_POINTER;
-
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
-
- *aCanEdit = (editor) ? PR_TRUE : PR_FALSE;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
nsTextServicesDocument::GetCurrentTextBlock(nsString *aStr)
{
nsresult result;
if (!aStr)
return NS_ERROR_NULL_POINTER;
aStr->Truncate();
@@ -623,542 +549,16 @@ nsTextServicesDocument::FirstBlock()
}
UNLOCK_DOC(this);
return result;
}
NS_IMETHODIMP
-nsTextServicesDocument::LastBlock()
-{
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
-
- LOCK_DOC(this);
-
- // Position the iterator on the last text node
- // in the tree, then walk backwards over adjacent
- // text nodes until we hit a block boundary:
-
- nsresult result = LastTextNode(mIterator, &mIteratorStatus);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = FirstTextNodeInCurrentBlock(mIterator);
-
- if (NS_FAILED(result))
- mIteratorStatus = nsTextServicesDocument::eIsDone;
-
- // Keep track of prev and next blocks, just in case
- // the text service blows away the current block.
-
- if (mIteratorStatus == nsTextServicesDocument::eValid)
- {
- result = GetFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock));
- mNextTextBlock = nsnull;
- }
- else
- {
- // There's no text block in the document!
-
- mPrevTextBlock = nsnull;
- mNextTextBlock = nsnull;
- }
-
- UNLOCK_DOC(this);
-
- return result;
-}
-
-// XXX: CODE BLOAT ALERT. FirstSelectedBlock() and LastSelectedBlock()
-// are almost identical! Later, when we have time, we should try
-// and combine them into one method.
-
-NS_IMETHODIMP
-nsTextServicesDocument::FirstSelectedBlock(TSDBlockSelectionStatus *aSelStatus, PRInt32 *aSelOffset, PRInt32 *aSelLength)
-{
- nsresult result = NS_OK;
-
- if (!aSelStatus || !aSelOffset || !aSelLength)
- return NS_ERROR_NULL_POINTER;
-
- LOCK_DOC(this);
-
- mIteratorStatus = nsTextServicesDocument::eIsDone;
-
- *aSelStatus = nsITextServicesDocument::eBlockNotFound;
- *aSelOffset = *aSelLength = -1;
-
- if (!mSelCon || !mIterator)
- {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsISelection> selection;
- PRBool isCollapsed = PR_FALSE;
-
- result = mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = selection->GetIsCollapsed( &isCollapsed);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- nsCOMPtr<nsIContentIterator> iter;
- nsCOMPtr<nsIDOMRange> range;
- nsCOMPtr<nsIDOMNode> parent;
- PRInt32 i, rangeCount, offset;
-
- if (isCollapsed)
- {
- // We have a caret. Check if the caret is in a text node.
- // If it is, make the text node's block the current block.
- // If the caret isn't in a text node, search backwards in
- // the document, till we find a text node.
-
- result = selection->GetRangeAt(0, getter_AddRefs(range));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- if (!range)
- {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- result = range->GetStartContainer(getter_AddRefs(parent));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- if (!parent)
- {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- result = range->GetStartOffset(&offset);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- if (IsTextNode(parent))
- {
- // The caret is in a text node. Find the beginning
- // of the text block containing this text node and
- // return.
-
- nsCOMPtr<nsIContent> content = do_QueryInterface(parent);
-
- if (!content)
- {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- result = mIterator->PositionAt(content);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = FirstTextNodeInCurrentBlock(mIterator);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- mIteratorStatus = nsTextServicesDocument::eValid;
-
- result = CreateOffsetTable(&mOffsetTable, mIterator, &mIteratorStatus,
- mExtent, nsnull);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = GetSelection(aSelStatus, aSelOffset, aSelLength);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- if (*aSelStatus == nsITextServicesDocument::eBlockContains)
- result = SetSelectionInternal(*aSelOffset, *aSelLength, PR_FALSE);
- }
- else
- {
- // The caret isn't in a text node. Create an iterator
- // based on a range that extends from the beginning of
- // the document, to the current caret position, then
- // walk backwards till you find a text node, then find
- // the beginning of the block.
-
- result = CreateDocumentContentRootToNodeOffsetRange(parent, offset, PR_TRUE, getter_AddRefs(range));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = range->GetCollapsed(&isCollapsed);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- if (isCollapsed)
- {
- // If we get here, the range is collapsed because there is nothing before
- // the caret! Just return NS_OK;
-
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- result = CreateContentIterator(range, getter_AddRefs(iter));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- iter->Last();
-
- nsCOMPtr<nsIContent> content;
- while (!iter->IsDone())
- {
- content = do_QueryInterface(iter->GetCurrentNode());
-
- if (IsTextNode(content))
- break;
-
- content = nsnull;
-
- iter->Prev();
- }
-
- if (!content)
- {
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- result = mIterator->PositionAt(content);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = FirstTextNodeInCurrentBlock(mIterator);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- mIteratorStatus = nsTextServicesDocument::eValid;
-
- result = CreateOffsetTable(&mOffsetTable, mIterator, &mIteratorStatus,
- mExtent, nsnull);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = GetSelection(aSelStatus, aSelOffset, aSelLength);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
- }
-
- UNLOCK_DOC(this);
-
- return result;
- }
-
- // If we get here, we have an uncollapsed selection!
- // Look through each range in the selection till you
- // find the first text node. If you find one, find the
- // beginning of it's text block, and make it the current
- // block.
-
- result = selection->GetRangeCount(&rangeCount);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- NS_ASSERTION(rangeCount > 0, "Unexpected range count!");
-
- if (rangeCount <= 0)
- {
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- // XXX: We may need to add some code here to make sure
- // the ranges are sorted in document appearance order!
-
- for (i = 0; i < rangeCount; i++)
- {
- // Get the i'th range from the selection.
-
- result = selection->GetRangeAt(i, getter_AddRefs(range));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- // Create an iterator for the range.
-
- result = CreateContentIterator(range, getter_AddRefs(iter));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- iter->First();
-
- // Now walk through the range till we find a text node.
-
- while (!iter->IsDone())
- {
- nsCOMPtr<nsIContent> content = do_QueryInterface(iter->GetCurrentNode());
-
- if (IsTextNode(content))
- {
- // We found a text node, so position the document's
- // iterator at the beginning of the block, then get
- // the selection in terms of the string offset.
-
- result = mIterator->PositionAt(content);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = FirstTextNodeInCurrentBlock(mIterator);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- mIteratorStatus = nsTextServicesDocument::eValid;
-
- result = CreateOffsetTable(&mOffsetTable, mIterator, &mIteratorStatus,
- mExtent, nsnull);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = GetSelection(aSelStatus, aSelOffset, aSelLength);
-
- UNLOCK_DOC(this);
-
- return result;
-
- }
-
- iter->Next();
- }
- }
-
- // If we get here, we didn't find any text node in the selection!
- // Create a range that extends from the beginning of the selection,
- // to the beginning of the document, then iterate backwards through
- // it till you find a text node!
-
- result = selection->GetRangeAt(0, getter_AddRefs(range));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- if (!range)
- {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- result = range->GetStartContainer(getter_AddRefs(parent));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- if (!parent)
- {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- result = range->GetStartOffset(&offset);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = CreateDocumentContentRootToNodeOffsetRange(parent, offset, PR_TRUE, getter_AddRefs(range));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = range->GetCollapsed(&isCollapsed);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- if (isCollapsed)
- {
- // If we get here, the range is collapsed because there is nothing before
- // the current selection! Just return NS_OK;
-
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- result = CreateContentIterator(range, getter_AddRefs(iter));
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- iter->Last();
-
- while (!iter->IsDone())
- {
- nsCOMPtr<nsIContent> content = do_QueryInterface(iter->GetCurrentNode());
-
- if (IsTextNode(content))
- {
- // We found a text node! Adjust the document's iterator to point
- // to the beginning of it's text block, then get the current selection.
-
- result = mIterator->PositionAt(content);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = FirstTextNodeInCurrentBlock(mIterator);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- mIteratorStatus = nsTextServicesDocument::eValid;
-
- result = CreateOffsetTable(&mOffsetTable, mIterator, &mIteratorStatus,
- mExtent, nsnull);
-
- if (NS_FAILED(result))
- {
- UNLOCK_DOC(this);
- return result;
- }
-
- result = GetSelection(aSelStatus, aSelOffset, aSelLength);
-
- UNLOCK_DOC(this);
-
- return result;
- }
-
- iter->Prev();
- }
-
- // If we get here, we didn't find any block before or inside
- // the selection! Just return OK.
-
- UNLOCK_DOC(this);
-
- return NS_OK;
-}
-
-// XXX: CODE BLOAT ALERT. FirstSelectedBlock() and LastSelectedBlock()
-// are almost identical! Later, when we have time, we should try
-// and combine them into one method.
-
-NS_IMETHODIMP
nsTextServicesDocument::LastSelectedBlock(TSDBlockSelectionStatus *aSelStatus,
PRInt32 *aSelOffset,
PRInt32 *aSelLength)
{
nsresult result = NS_OK;
if (!aSelStatus || !aSelOffset || !aSelLength)
return NS_ERROR_NULL_POINTER;
@@ -2411,85 +1811,16 @@ nsTextServicesDocument::InsertText(const
result = editor->EndTransaction();
UNLOCK_DOC(this);
return result;
}
-NS_IMETHODIMP
-nsTextServicesDocument::SetDisplayStyle(TSDDisplayStyle aStyle)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::GetDOMRangeFor(PRInt32 aOffset, PRInt32 aLength, nsIDOMRange** aRange)
-{
- if (!mSelCon || aOffset < 0 || aLength < 0)
- return NS_ERROR_FAILURE;
-
- nsIDOMNode *sNode = 0, *eNode = 0;
- PRInt32 i, sOffset = 0, eOffset = 0;
- OffsetEntry *entry;
-
- // Find the start
- for (i = 0; !sNode && i < mOffsetTable.Count(); i++)
- {
- entry = (OffsetEntry *)mOffsetTable[i];
- if (entry->mIsValid)
- {
- if (entry->mIsInsertedText)
- {
- if (entry->mStrOffset == aOffset)
- {
- sNode = entry->mNode;
- sOffset = entry->mNodeOffset + entry->mLength;
- }
- }
- else if (aOffset >= entry->mStrOffset && aOffset <= entry->mStrOffset + entry->mLength)
- {
- sNode = entry->mNode;
- sOffset = entry->mNodeOffset + aOffset - entry->mStrOffset;
- }
- }
- }
-
- if (!sNode)
- return NS_ERROR_FAILURE;
-
- // Now find the end
- PRInt32 endOffset = aOffset + aLength;
-
- for (i = mOffsetTable.Count() - 1; !eNode && i >= 0; i--)
- {
- entry = (OffsetEntry *)mOffsetTable[i];
-
- if (entry->mIsValid)
- {
- if (entry->mIsInsertedText)
- {
- if (entry->mStrOffset == eOffset)
- {
- eNode = entry->mNode;
- eOffset = entry->mNodeOffset + entry->mLength;
- }
- }
- else if (endOffset >= entry->mStrOffset && endOffset <= entry->mStrOffset + entry->mLength)
- {
- eNode = entry->mNode;
- eOffset = entry->mNodeOffset + endOffset - entry->mStrOffset;
- }
- }
- }
-
- return CreateRange(sNode, sOffset, eNode, eOffset, aRange);
-}
-
nsresult
nsTextServicesDocument::InsertNode(nsIDOMNode *aNode,
nsIDOMNode *aParent,
PRInt32 aPosition)
{
return NS_OK;
}
--- a/editor/txtsvc/src/nsTextServicesDocument.h
+++ b/editor/txtsvc/src/nsTextServicesDocument.h
@@ -133,38 +133,31 @@ public:
/** To be called at module shutdown
*/
static void Shutdown();
/* Macro for AddRef(), Release(), and QueryInterface() */
NS_DECL_ISUPPORTS
/* nsITextServicesDocument method implementations. */
- NS_IMETHOD InitWithDocument(nsIDOMDocument *aDOMDocument, nsIPresShell *aPresShell);
NS_IMETHOD InitWithEditor(nsIEditor *aEditor);
NS_IMETHOD GetDocument(nsIDOMDocument **aDoc);
NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange);
- NS_IMETHOD GetExtent(nsIDOMRange** aDOMRange);
NS_IMETHOD ExpandRangeToWordBoundaries(nsIDOMRange *aRange);
NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter);
- NS_IMETHOD CanEdit(PRBool *aCanEdit);
NS_IMETHOD GetCurrentTextBlock(nsString *aStr);
NS_IMETHOD FirstBlock();
- NS_IMETHOD LastBlock();
- NS_IMETHOD FirstSelectedBlock(TSDBlockSelectionStatus *aSelStatus, PRInt32 *aSelOffset, PRInt32 *aSelLength);
NS_IMETHOD LastSelectedBlock(TSDBlockSelectionStatus *aSelStatus, PRInt32 *aSelOffset, PRInt32 *aSelLength);
NS_IMETHOD PrevBlock();
NS_IMETHOD NextBlock();
NS_IMETHOD IsDone(PRBool *aIsDone);
NS_IMETHOD SetSelection(PRInt32 aOffset, PRInt32 aLength);
NS_IMETHOD ScrollSelectionIntoView();
NS_IMETHOD DeleteSelection();
NS_IMETHOD InsertText(const nsString *aText);
- NS_IMETHOD SetDisplayStyle(TSDDisplayStyle aStyle);
- NS_IMETHOD GetDOMRangeFor(PRInt32 aOffset, PRInt32 aLength, nsIDOMRange** aRange);
/* nsIEditActionListener method implementations. */
nsresult InsertNode(nsIDOMNode * aNode,
nsIDOMNode * aParent,
PRInt32 aPosition);
nsresult DeleteNode(nsIDOMNode * aChild);
nsresult SplitNode(nsIDOMNode * aExistingRightNode,
PRInt32 aOffset,
--- a/gfx/cairo/libpixman/src/Makefile.in
+++ b/gfx/cairo/libpixman/src/Makefile.in
@@ -88,17 +88,18 @@ ifneq ($(MOZ_WIDGET_TOOLKIT),os2)
MMX_CFLAGS+=--param inline-unit-growth=10000 --param large-function-growth=10000
endif
endif
ifeq (arm,$(findstring arm,$(OS_TEST)))
ifdef HAVE_ARM_SIMD
USE_ARM_SIMD_GCC=1
endif
ifdef HAVE_ARM_NEON
-USE_ARM_NEON_GCC=1
+# temporarily disabled to see if it fixes odd mobile build breakage
+#USE_ARM_NEON_GCC=1
endif
endif
endif
CSRCS = \
pixman-access.c \
--- a/gfx/cairo/libpixman/src/pixman-pict.c
+++ b/gfx/cairo/libpixman/src/pixman-pict.c
@@ -2212,18 +2212,18 @@ pixman_bool_t pixman_have_vmx (void) {
}
#endif /* __APPLE__ */
#endif /* USE_VMX */
#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON)
#if defined(_MSC_VER)
+#if defined(USE_ARM_SIMD)
extern int pixman_msvc_try_arm_simd_op();
-extern int pixman_msvc_try_arm_neon_op();
pixman_bool_t
pixman_have_arm_simd (void)
{
static pixman_bool_t initialized = FALSE;
static pixman_bool_t have_arm_simd = FALSE;
if (!initialized) {
@@ -2233,16 +2233,20 @@ pixman_have_arm_simd (void)
} __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) {
have_arm_simd = FALSE;
}
initialized = TRUE;
}
return have_arm_simd;
}
+#endif /* USE_ARM_SIMD */
+
+#if defined(USE_ARM_NEON)
+extern int pixman_msvc_try_arm_neon_op();
pixman_bool_t
pixman_have_arm_neon (void)
{
static pixman_bool_t initialized = FALSE;
static pixman_bool_t have_arm_neon = FALSE;
if (!initialized) {
@@ -2252,16 +2256,17 @@ pixman_have_arm_neon (void)
} __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) {
have_arm_neon = FALSE;
}
initialized = TRUE;
}
return have_arm_neon;
}
+#endif /* USE_ARM_NEON */
#else /* linux ELF */
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
@@ -2312,33 +2317,37 @@ pixman_arm_read_auxv() {
// the env var to trust HWCAP.
if (!getenv("ARM_TRUST_HWCAP") && arm_has_v7)
arm_has_neon = TRUE;
}
arm_tests_initialized = TRUE;
}
+#if defined(USE_ARM_SIMD)
pixman_bool_t
pixman_have_arm_simd (void)
{
if (!arm_tests_initialized)
pixman_arm_read_auxv();
return arm_has_v6;
}
+#endif /* USE_ARM_SIMD */
+#if defined(USE_ARM_NEON)
pixman_bool_t
pixman_have_arm_neon (void)
{
if (!arm_tests_initialized)
pixman_arm_read_auxv();
return arm_has_neon;
}
+#endif /* USE_ARM_NEON */
#endif /* linux */
#endif /* USE_ARM_SIMD || USE_ARM_NEON */
#ifdef USE_MMX
/* The CPU detection code needs to be in a file not compiled with
* "-mmmx -msse", as gcc would generate CMOV instructions otherwise
--- a/gfx/public/Makefile.in
+++ b/gfx/public/Makefile.in
@@ -58,15 +58,14 @@ EXPORTS = \
nsMargin.h \
nsTransform2D.h \
nsIRenderingContext.h \
nsIFontMetrics.h \
nsIDeviceContext.h \
nsIImage.h \
nsGfxCIID.h \
nsIRegion.h \
- nsDeviceContext.h \
nsITheme.h \
nsThemeConstants.h \
$(NULL)
include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/gfx/public/nsDeviceContext.h
+++ /dev/null
@@ -1,159 +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):
- * Roland Mainz <Roland.Mainz@informatik.med.uni-giessen.de>
- *
- * 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 nsDeviceContext_h___
-#define nsDeviceContext_h___
-
-#include "nsIDeviceContext.h"
-#include "nsIDeviceContextSpec.h"
-#include "nsCOMPtr.h"
-#include "nsIAtom.h"
-#include "nsTArray.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
-#include "nsWeakReference.h"
-#include "gfxCore.h"
-
-class nsIImageRequest;
-class nsHashtable;
-
-class NS_GFX nsFontCache
-{
-public:
- nsFontCache();
- virtual ~nsFontCache();
-
- virtual nsresult Init(nsIDeviceContext* aContext);
- virtual nsresult GetDeviceContext(nsIDeviceContext *&aContext) const;
- virtual nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
- gfxUserFontSet* aUserFontSet,
- nsIFontMetrics *&aMetrics);
-
- nsresult FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
- nsresult Compact();
- nsresult Flush();
- /* printer device context classes may create their own
- * subclasses of nsFontCache (and override this method) and override
- * DeviceContextImpl::CreateFontCache (see bug 81311).
- */
- virtual nsresult CreateFontMetricsInstance(nsIFontMetrics** fm);
-
-protected:
- nsTArray<nsIFontMetrics*> mFontMetrics;
- nsIDeviceContext *mContext; // we do not addref this since
- // ownership is implied. MMP.
-};
-
-// inherit visibility from the NS_GFX class declaration
-#undef IMETHOD_VISIBILITY
-#define IMETHOD_VISIBILITY
-
-class NS_GFX DeviceContextImpl : public nsIDeviceContext,
- public nsIObserver,
- public nsSupportsWeakReference
-{
-public:
- DeviceContextImpl();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- NS_IMETHOD Init(nsNativeWidget aWidget);
-
- NS_IMETHOD CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext);
- NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext);
- NS_IMETHOD CreateRenderingContext(nsIRenderingContext *&aContext){return NS_ERROR_NOT_IMPLEMENTED;}
- NS_IMETHOD CreateRenderingContextInstance(nsIRenderingContext *&aContext);
-
- NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
- gfxUserFontSet* aUserFontSet,
- nsIFontMetrics*& aMetrics);
- NS_IMETHOD GetMetricsFor(const nsFont& aFont,
- gfxUserFontSet* aUserFontSet,
- nsIFontMetrics*& aMetrics);
-
- NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName);
-
- NS_IMETHOD GetLocalFontName(const nsString& aFaceName, nsString& aLocalName,
- PRBool& aAliased);
-
- NS_IMETHOD CreateFontCache();
- NS_IMETHOD FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
- NS_IMETHOD FlushFontCache(void);
-
- NS_IMETHOD GetDepth(PRUint32& aDepth);
-
- NS_IMETHOD GetPaletteInfo(nsPaletteInfo& aPaletteInfo);
-
- NS_IMETHOD PrepareDocument(PRUnichar * aTitle,
- PRUnichar* aPrintToFileName) { return NS_OK; }
- NS_IMETHOD AbortDocument(void) { return NS_OK; }
-
- NS_IMETHOD PrepareNativeWidget(nsIWidget *aWidget, void **aOut);
- NS_IMETHOD ClearCachedSystemFonts();
-
-private:
- /* Helper methods for |CreateRenderingContext|&co. */
- nsresult InitRenderingContext(nsIRenderingContext *aContext, nsIWidget *aWindow);
-
-protected:
- virtual ~DeviceContextImpl();
-
- void CommonInit(void);
- nsresult CreateIconILGroupContext();
- virtual nsresult CreateFontAliasTable();
- nsresult AliasFont(const nsString& aFont,
- const nsString& aAlias, const nsString& aAltAlias,
- PRBool aForceAlias);
- void GetLocaleLangGroup(void);
-
- nsFontCache *mFontCache;
- nsCOMPtr<nsIAtom> mLocaleLangGroup; // XXX temp fix for performance bug - erik
- nsHashtable* mFontAliasTable;
-
-public:
- nsNativeWidget mWidget;
-#ifdef NS_DEBUG
- PRBool mInitialized;
-#endif
-};
-
-#undef IMETHOD_VISIBILITY
-#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
-
-#endif /* nsDeviceContext_h___ */
--- a/gfx/src/Makefile.in
+++ b/gfx/src/Makefile.in
@@ -62,17 +62,16 @@ REQUIRES = xpcom \
DIRS = shared thebes
ifdef MOZ_ENABLE_POSTSCRIPT
DIRS += psshared
endif
CPPSRCS = \
nsColor.cpp \
- nsDeviceContext.cpp \
nsFont.cpp \
nsRect.cpp \
nsRegion.cpp \
nsTransform2D.cpp \
nsScriptableRegion.cpp \
$(NULL)
ifeq (,$(filter windows,$(MOZ_WIDGET_TOOLKIT)))
deleted file mode 100644
--- a/gfx/src/nsDeviceContext.cpp
+++ /dev/null
@@ -1,609 +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):
- * Roland Mainz <Roland.Mainz@informatik.med.uni-giessen.de>
- * IBM Corp.
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsDeviceContext.h"
-#include "nsFont.h"
-#include "nsIView.h"
-#include "nsGfxCIID.h"
-#include "nsIFontMetrics.h"
-#include "nsHashtable.h"
-#include "nsILanguageAtomService.h"
-#include "nsIServiceManager.h"
-#include "nsUnicharUtils.h"
-#include "nsCRT.h"
-#include "nsIRenderingContext.h"
-#include "gfxUserFontSet.h"
-#include "nsIThebesFontMetrics.h"
-
-NS_IMPL_ISUPPORTS3(DeviceContextImpl, nsIDeviceContext, nsIObserver, nsISupportsWeakReference)
-
-DeviceContextImpl::DeviceContextImpl()
-{
- mAppUnitsPerDevPixel = -1;
- mAppUnitsPerInch = -1;
- mAppUnitsPerDevNotScaledPixel = -1;
- mPixelScale = 1.0f;
-
- mFontCache = nsnull;
- mWidget = nsnull;
- mFontAliasTable = nsnull;
-
-#ifdef NS_DEBUG
- mInitialized = PR_FALSE;
-#endif
-}
-
-static PRBool DeleteValue(nsHashKey* aKey, void* aValue, void* closure)
-{
- delete ((nsString*)aValue);
- return PR_TRUE;
-}
-
-DeviceContextImpl::~DeviceContextImpl()
-{
- nsCOMPtr<nsIObserverService> obs(do_GetService("@mozilla.org/observer-service;1"));
- if (obs)
- obs->RemoveObserver(this, "memory-pressure");
-
- if (nsnull != mFontCache)
- {
- delete mFontCache;
- mFontCache = nsnull;
- }
-
- if (nsnull != mFontAliasTable) {
- mFontAliasTable->Enumerate(DeleteValue);
- delete mFontAliasTable;
- }
-
-}
-
-NS_IMETHODIMP
-DeviceContextImpl::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aSomeData)
-{
- if (mFontCache && !nsCRT::strcmp(aTopic, "memory-pressure")) {
- mFontCache->Compact();
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP DeviceContextImpl::Init(nsNativeWidget aWidget)
-{
- mWidget = aWidget;
-
- CommonInit();
-
- return NS_OK;
-}
-
-void DeviceContextImpl::CommonInit(void)
-{
-#ifdef NS_DEBUG
- NS_ASSERTION(!mInitialized, "device context is initialized twice!");
- mInitialized = PR_TRUE;
-#endif
-
- // register as a memory-pressure observer to free font resources
- // in low-memory situations.
- nsCOMPtr<nsIObserverService> obs(do_GetService("@mozilla.org/observer-service;1"));
- if (obs)
- obs->AddObserver(this, "memory-pressure", PR_TRUE);
-}
-
-NS_IMETHODIMP DeviceContextImpl::CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext)
-{
- nsresult rv;
-
- aContext = nsnull;
- nsCOMPtr<nsIRenderingContext> pContext;
- rv = CreateRenderingContextInstance(*getter_AddRefs(pContext));
- if (NS_SUCCEEDED(rv)) {
- rv = InitRenderingContext(pContext, aView->GetWidget());
- if (NS_SUCCEEDED(rv)) {
- aContext = pContext;
- NS_ADDREF(aContext);
- }
- }
-
- return rv;
-}
-
-NS_IMETHODIMP DeviceContextImpl::CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext)
-{
- nsresult rv;
-
- aContext = nsnull;
- nsCOMPtr<nsIRenderingContext> pContext;
- rv = CreateRenderingContextInstance(*getter_AddRefs(pContext));
- if (NS_SUCCEEDED(rv)) {
- rv = InitRenderingContext(pContext, aWidget);
- if (NS_SUCCEEDED(rv)) {
- aContext = pContext;
- NS_ADDREF(aContext);
- }
- }
-
- return rv;
-}
-
-NS_IMETHODIMP DeviceContextImpl::CreateRenderingContextInstance(nsIRenderingContext *&aContext)
-{
- static NS_DEFINE_CID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID);
-
- nsresult rv;
- nsCOMPtr<nsIRenderingContext> pContext = do_CreateInstance(kRenderingContextCID, &rv);
- if (NS_SUCCEEDED(rv)) {
- aContext = pContext;
- NS_ADDREF(aContext);
- }
- return rv;
-}
-
-nsresult DeviceContextImpl::InitRenderingContext(nsIRenderingContext *aContext, nsIWidget *aWin)
-{
- return aContext->Init(this, aWin);
-}
-
-NS_IMETHODIMP DeviceContextImpl::CreateFontCache()
-{
- mFontCache = new nsFontCache();
- if (!mFontCache) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- return mFontCache->Init(this);
-}
-
-NS_IMETHODIMP DeviceContextImpl::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics)
-{
- if (mFontCache) {
- mFontCache->FontMetricsDeleted(aFontMetrics);
- }
- return NS_OK;
-}
-
-void
-DeviceContextImpl::GetLocaleLangGroup(void)
-{
- if (!mLocaleLangGroup) {
- nsCOMPtr<nsILanguageAtomService> langService;
- langService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
- if (langService) {
- mLocaleLangGroup = langService->GetLocaleLanguageGroup();
- }
- if (!mLocaleLangGroup) {
- mLocaleLangGroup = do_GetAtom("x-western");
- }
- }
-}
-
-NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont,
- nsIAtom* aLangGroup, gfxUserFontSet *aUserFontSet, nsIFontMetrics*& aMetrics)
-{
- if (nsnull == mFontCache) {
- nsresult rv = CreateFontCache();
- if (NS_FAILED(rv)) {
- aMetrics = nsnull;
- return rv;
- }
- // XXX temporary fix for performance problem -- erik
- GetLocaleLangGroup();
- }
-
- // XXX figure out why aLangGroup is NULL sometimes
- if (!aLangGroup) {
- aLangGroup = mLocaleLangGroup;
- }
-
- return mFontCache->GetMetricsFor(aFont, aLangGroup, aUserFontSet, aMetrics);
-}
-
-NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont,
- gfxUserFontSet *aUserFontSet,
- nsIFontMetrics*& aMetrics)
-{
- if (nsnull == mFontCache) {
- nsresult rv = CreateFontCache();
- if (NS_FAILED(rv)) {
- aMetrics = nsnull;
- return rv;
- }
- // XXX temporary fix for performance problem -- erik
- GetLocaleLangGroup();
- }
- return mFontCache->GetMetricsFor(aFont, mLocaleLangGroup, aUserFontSet,
- aMetrics);
-}
-
-NS_IMETHODIMP DeviceContextImpl::GetDepth(PRUint32& aDepth)
-{
- aDepth = 24;
- return NS_OK;
-}
-
-NS_IMETHODIMP DeviceContextImpl::GetPaletteInfo(nsPaletteInfo& aPaletteInfo)
-{
- aPaletteInfo.isPaletteDevice = PR_FALSE;
- aPaletteInfo.sizePalette = 0;
- aPaletteInfo.numReserved = 0;
- aPaletteInfo.palette = nsnull;
- return NS_OK;
-}
-
-struct FontEnumData {
- FontEnumData(nsIDeviceContext* aDC, nsString& aFaceName)
- : mDC(aDC), mFaceName(aFaceName)
- {}
- nsIDeviceContext* mDC;
- nsString& mFaceName;
-};
-
-static PRBool FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
-{
- FontEnumData* data = (FontEnumData*)aData;
- // XXX for now, all generic fonts are presumed to exist
- // we may want to actually check if there's an installed conversion
- if (aGeneric) {
- data->mFaceName = aFamily;
- return PR_FALSE; // found one, stop.
- }
- else {
- nsAutoString local;
- PRBool aliased;
- data->mDC->GetLocalFontName(aFamily, local, aliased);
- if (aliased || (NS_SUCCEEDED(data->mDC->CheckFontExistence(local)))) {
- data->mFaceName = local;
- return PR_FALSE; // found one, stop.
- }
- }
- return PR_TRUE; // didn't exist, continue looking
-}
-
-NS_IMETHODIMP DeviceContextImpl::FirstExistingFont(const nsFont& aFont, nsString& aFaceName)
-{
- FontEnumData data(this, aFaceName);
- if (aFont.EnumerateFamilies(FontEnumCallback, &data)) {
- return NS_ERROR_FAILURE; // ran out
- }
- return NS_OK;
-}
-
-class FontAliasKey: public nsHashKey
-{
-public:
- FontAliasKey(const nsString& aString)
- {mString.Assign(aString);}
-
- virtual PRUint32 HashCode(void) const;
- virtual PRBool Equals(const nsHashKey *aKey) const;
- virtual nsHashKey *Clone(void) const;
-
- nsString mString;
-};
-
-PRUint32 FontAliasKey::HashCode(void) const
-{
- PRUint32 hash = 0;
- const PRUnichar* string = mString.get();
- PRUnichar ch;
- while ((ch = *string++) != 0) {
- // FYI: hash = hash*37 + ch
- ch = ToUpperCase(ch);
- hash = ((hash << 5) + (hash << 2) + hash) + ch;
- }
- return hash;
-}
-
-PRBool FontAliasKey::Equals(const nsHashKey *aKey) const
-{
- return mString.Equals(((FontAliasKey*)aKey)->mString, nsCaseInsensitiveStringComparator());
-}
-
-nsHashKey* FontAliasKey::Clone(void) const
-{
- return new FontAliasKey(mString);
-}
-nsresult DeviceContextImpl::CreateFontAliasTable()
-{
- nsresult result = NS_OK;
-
- if (nsnull == mFontAliasTable) {
- mFontAliasTable = new nsHashtable();
- if (nsnull != mFontAliasTable) {
-
- nsAutoString times; times.AssignLiteral("Times");
- nsAutoString timesNewRoman; timesNewRoman.AssignLiteral("Times New Roman");
- nsAutoString timesRoman; timesRoman.AssignLiteral("Times Roman");
- nsAutoString arial; arial.AssignLiteral("Arial");
- nsAutoString helvetica; helvetica.AssignLiteral("Helvetica");
- nsAutoString courier; courier.AssignLiteral("Courier");
- nsAutoString courierNew; courierNew.AssignLiteral("Courier New");
- nsAutoString nullStr;
-
- AliasFont(times, timesNewRoman, timesRoman, PR_FALSE);
- AliasFont(timesRoman, timesNewRoman, times, PR_FALSE);
- AliasFont(timesNewRoman, timesRoman, times, PR_FALSE);
- AliasFont(arial, helvetica, nullStr, PR_FALSE);
- AliasFont(helvetica, arial, nullStr, PR_FALSE);
- AliasFont(courier, courierNew, nullStr, PR_TRUE);
- AliasFont(courierNew, courier, nullStr, PR_FALSE);
- }
- else {
- result = NS_ERROR_OUT_OF_MEMORY;
- }
- }
- return result;
-}
-
-nsresult DeviceContextImpl::AliasFont(const nsString& aFont,
- const nsString& aAlias, const nsString& aAltAlias,
- PRBool aForceAlias)
-{
- nsresult result = NS_OK;
-
- if (nsnull != mFontAliasTable) {
- if (aForceAlias || NS_FAILED(CheckFontExistence(aFont))) {
- if (NS_SUCCEEDED(CheckFontExistence(aAlias))) {
- nsString* entry = new nsString(aAlias);
- if (nsnull != entry) {
- FontAliasKey key(aFont);
- mFontAliasTable->Put(&key, entry);
- }
- else {
- result = NS_ERROR_OUT_OF_MEMORY;
- }
- }
- else if (!aAltAlias.IsEmpty() && NS_SUCCEEDED(CheckFontExistence(aAltAlias))) {
- nsString* entry = new nsString(aAltAlias);
- if (nsnull != entry) {
- FontAliasKey key(aFont);
- mFontAliasTable->Put(&key, entry);
- }
- else {
- result = NS_ERROR_OUT_OF_MEMORY;
- }
- }
- }
- }
- else {
- result = NS_ERROR_FAILURE;
- }
- return result;
-}
-
-NS_IMETHODIMP DeviceContextImpl::GetLocalFontName(const nsString& aFaceName, nsString& aLocalName,
- PRBool& aAliased)
-{
- nsresult result = NS_OK;
-
- if (nsnull == mFontAliasTable) {
- result = CreateFontAliasTable();
- }
-
- if (nsnull != mFontAliasTable) {
- FontAliasKey key(aFaceName);
- const nsString* alias = (const nsString*)mFontAliasTable->Get(&key);
- if (nsnull != alias) {
- aLocalName = *alias;
- aAliased = PR_TRUE;
- }
- else {
- aLocalName = aFaceName;
- aAliased = PR_FALSE;
- }
- }
- return result;
-}
-
-NS_IMETHODIMP DeviceContextImpl::FlushFontCache(void)
-{
- if (nsnull != mFontCache)
- mFontCache->Flush();
-
- return NS_OK;
-}
-
-/////////////////////////////////////////////////////////////
-
-nsFontCache::nsFontCache()
-{
- MOZ_COUNT_CTOR(nsFontCache);
- mContext = nsnull;
-}
-
-nsFontCache::~nsFontCache()
-{
- MOZ_COUNT_DTOR(nsFontCache);
- Flush();
-}
-
-nsresult
-nsFontCache::Init(nsIDeviceContext* aContext)
-{
- NS_PRECONDITION(nsnull != aContext, "null ptr");
- // Note: we don't hold a reference to the device context, because it
- // holds a reference to us and we don't want circular references
- mContext = aContext;
- return NS_OK;
-}
-
-nsresult
-nsFontCache::GetDeviceContext(nsIDeviceContext *&aContext) const
-{
- aContext = mContext;
- NS_IF_ADDREF(aContext);
- return NS_OK;
-}
-
-nsresult
-nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
- gfxUserFontSet *aUserFontSet, nsIFontMetrics *&aMetrics)
-{
- // First check our cache
- // start from the end, which is where we put the most-recent-used element
-
- nsIFontMetrics* fm;
- PRInt32 n = mFontMetrics.Length() - 1;
- for (PRInt32 i = n; i >= 0; --i) {
- fm = mFontMetrics[i];
- nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm);
- if (fm->Font().Equals(aFont) && tfm->GetUserFontSet() == aUserFontSet) {
- nsCOMPtr<nsIAtom> langGroup;
- fm->GetLangGroup(getter_AddRefs(langGroup));
- if (aLangGroup == langGroup.get()) {
- if (i != n) {
- // promote it to the end of the cache
- mFontMetrics.RemoveElementAt(i);
- mFontMetrics.AppendElement(fm);
- }
- tfm->GetThebesFontGroup()->UpdateFontList();
- NS_ADDREF(aMetrics = fm);
- return NS_OK;
- }
- }
- }
-
- // It's not in the cache. Get font metrics and then cache them.
-
- aMetrics = nsnull;
- nsresult rv = CreateFontMetricsInstance(&fm);
- if (NS_FAILED(rv)) return rv;
- rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
- if (NS_SUCCEEDED(rv)) {
- // the mFontMetrics list has the "head" at the end, because append is
- // cheaper than insert
- mFontMetrics.AppendElement(fm);
- aMetrics = fm;
- NS_ADDREF(aMetrics);
- return NS_OK;
- }
- fm->Destroy();
- NS_RELEASE(fm);
-
- // One reason why Init() fails is because the system is running out of resources.
- // e.g., on Win95/98 only a very limited number of GDI objects are available.
- // Compact the cache and try again.
-
- Compact();
- rv = CreateFontMetricsInstance(&fm);
- if (NS_FAILED(rv)) return rv;
- rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
- if (NS_SUCCEEDED(rv)) {
- mFontMetrics.AppendElement(fm);
- aMetrics = fm;
- NS_ADDREF(aMetrics);
- return NS_OK;
- }
- fm->Destroy();
- NS_RELEASE(fm);
-
- // could not setup a new one, send an old one (XXX search a "best match"?)
-
- n = mFontMetrics.Length() - 1; // could have changed in Compact()
- if (n >= 0) {
- aMetrics = mFontMetrics[n];
- NS_ADDREF(aMetrics);
- return NS_OK;
- }
-
- NS_POSTCONDITION(NS_SUCCEEDED(rv), "font metrics should not be null - bug 136248");
- return rv;
-}
-
-/* PostScript module may override this method to create
- * nsIFontMetrics objects with their own classes
- */
-nsresult
-nsFontCache::CreateFontMetricsInstance(nsIFontMetrics** fm)
-{
- static NS_DEFINE_CID(kFontMetricsCID, NS_FONT_METRICS_CID);
- return CallCreateInstance(kFontMetricsCID, fm);
-}
-
-nsresult nsFontCache::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics)
-{
- mFontMetrics.RemoveElement(aFontMetrics);
- return NS_OK;
-}
-
-nsresult nsFontCache::Compact()
-{
- // Need to loop backward because the running element can be removed on the way
- for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) {
- nsIFontMetrics* fm = mFontMetrics[i];
- nsIFontMetrics* oldfm = fm;
- // Destroy() isn't here because we want our device context to be notified
- NS_RELEASE(fm); // this will reset fm to nsnull
- // if the font is really gone, it would have called back in
- // FontMetricsDeleted() and would have removed itself
- if (mFontMetrics.IndexOf(oldfm) >= 0) {
- // nope, the font is still there, so let's hold onto it too
- NS_ADDREF(oldfm);
- }
- }
- return NS_OK;
-}
-
-nsresult nsFontCache::Flush()
-{
- for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) {
- nsIFontMetrics* fm = mFontMetrics[i];
- // Destroy() will unhook our device context from the fm so that we won't
- // waste time in triggering the notification of FontMetricsDeleted()
- // in the subsequent release
- fm->Destroy();
- NS_RELEASE(fm);
- }
-
- mFontMetrics.Clear();
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-DeviceContextImpl::PrepareNativeWidget(nsIWidget *aWidget, void **aOut)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-DeviceContextImpl::ClearCachedSystemFonts()
-{
- return NS_OK;
-}
deleted file mode 100644
--- a/gfx/src/nsRenderingContextImpl.h
+++ /dev/null
@@ -1,201 +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 nsRenderingContextImpl_h___
-#define nsRenderingContextImpl_h___
-
-#include "gfxCore.h"
-#include "nsIRenderingContext.h"
-#include "nsPoint.h"
-#include "nsSize.h"
-
-class gfxContext;
-
-class nsRenderingContextImpl : public nsIRenderingContext
-{
-
-// CLASS MEMBERS
-
-public:
- nsRenderingContextImpl();
-
-
-// CLASS METHODS
-
- /**
- * Return the maximum length of a string that can be handled by the platform
- * using the current font metrics.
- * The implementation here is just a stub; classes that don't override
- * the safe string methods need to implement this.
- */
- virtual PRInt32 GetMaxStringLength() = 0;
-
- /**
- * Let the device context know whether we want text reordered with
- * right-to-left base direction
- */
- NS_IMETHOD GetRightToLeftText(PRBool* aIsRTL);
-
- // Safe string method variants: by default, these defer to the more
- // elaborate methods below
- NS_IMETHOD GetWidth(const nsString& aString, nscoord &aWidth,
- PRInt32 *aFontID = nsnull);
- NS_IMETHOD GetWidth(const char* aString, nscoord& aWidth);
- NS_IMETHOD DrawString(const nsString& aString, nscoord aX, nscoord aY,
- PRInt32 aFontID = -1,
- const nscoord* aSpacing = nsnull);
-
- // Safe string methods
- NS_IMETHOD GetWidth(const char* aString, PRUint32 aLength,
- nscoord& aWidth);
- NS_IMETHOD GetWidth(const PRUnichar *aString, PRUint32 aLength,
- nscoord &aWidth, PRInt32 *aFontID = nsnull);
-
- NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength,
- nsTextDimensions& aDimensions);
- NS_IMETHOD GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
- nsTextDimensions& aDimensions, PRInt32* aFontID = nsnull);
-
-#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS)
- NS_IMETHOD GetTextDimensions(const char* aString,
- PRInt32 aLength,
- PRInt32 aAvailWidth,
- PRInt32* aBreaks,
- PRInt32 aNumBreaks,
- nsTextDimensions& aDimensions,
- PRInt32& aNumCharsFit,
- nsTextDimensions& aLastWordDimensions,
- PRInt32* aFontID = nsnull);
-
- NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
- PRInt32 aLength,
- PRInt32 aAvailWidth,
- PRInt32* aBreaks,
- PRInt32 aNumBreaks,
- nsTextDimensions& aDimensions,
- PRInt32& aNumCharsFit,
- nsTextDimensions& aLastWordDimensions,
- PRInt32* aFontID = nsnull);
-#endif
-#ifdef MOZ_MATHML
- NS_IMETHOD
- GetBoundingMetrics(const char* aString,
- PRUint32 aLength,
- nsBoundingMetrics& aBoundingMetrics);
- NS_IMETHOD
- GetBoundingMetrics(const PRUnichar* aString,
- PRUint32 aLength,
- nsBoundingMetrics& aBoundingMetrics,
- PRInt32* aFontID = nsnull);
-#endif
- NS_IMETHOD DrawString(const char *aString, PRUint32 aLength,
- nscoord aX, nscoord aY,
- const nscoord* aSpacing = nsnull);
- NS_IMETHOD DrawString(const PRUnichar *aString, PRUint32 aLength,
- nscoord aX, nscoord aY,
- PRInt32 aFontID = -1,
- const nscoord* aSpacing = nsnull);
-
- // Unsafe platform-specific implementations
- NS_IMETHOD GetWidthInternal(const char* aString, PRUint32 aLength,
- nscoord& aWidth)
- { return NS_ERROR_NOT_IMPLEMENTED; }
- NS_IMETHOD GetWidthInternal(const PRUnichar *aString, PRUint32 aLength,
- nscoord &aWidth, PRInt32 *aFontID = nsnull)
- { return NS_ERROR_NOT_IMPLEMENTED; }
-
- NS_IMETHOD GetTextDimensionsInternal(const char* aString, PRUint32 aLength,
- nsTextDimensions& aDimensions)
- { return NS_ERROR_NOT_IMPLEMENTED; }
- NS_IMETHOD GetTextDimensionsInternal(const PRUnichar* aString, PRUint32 aLength,
- nsTextDimensions& aDimensions, PRInt32* aFontID = nsnull)
- { return NS_ERROR_NOT_IMPLEMENTED; }
-
-#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS)
- NS_IMETHOD GetTextDimensionsInternal(const char* aString,
- PRInt32 aLength,
- PRInt32 aAvailWidth,
- PRInt32* aBreaks,
- PRInt32 aNumBreaks,
- nsTextDimensions& aDimensions,
- PRInt32& aNumCharsFit,
- nsTextDimensions& aLastWordDimensions,
- PRInt32* aFontID = nsnull)
- { return NS_ERROR_NOT_IMPLEMENTED; }
-
- NS_IMETHOD GetTextDimensionsInternal(const PRUnichar* aString,
- PRInt32 aLength,
- PRInt32 aAvailWidth,
- PRInt32* aBreaks,
- PRInt32 aNumBreaks,
- nsTextDimensions& aDimensions,
- PRInt32& aNumCharsFit,
- nsTextDimensions& aLastWordDimensions,
- PRInt32* aFontID = nsnull)
- { return NS_ERROR_NOT_IMPLEMENTED; }
-#endif
-#ifdef MOZ_MATHML
- NS_IMETHOD
- GetBoundingMetricsInternal(const char* aString,
- PRUint32 aLength,
- nsBoundingMetrics& aBoundingMetrics)
- { return NS_ERROR_NOT_IMPLEMENTED; }
- NS_IMETHOD
- GetBoundingMetricsInternal(const PRUnichar* aString,
- PRUint32 aLength,
- nsBoundingMetrics& aBoundingMetrics,
- PRInt32* aFontID = nsnull)
- { return NS_ERROR_NOT_IMPLEMENTED; }
-#endif
- NS_IMETHOD DrawStringInternal(const char *aString, PRUint32 aLength,
- nscoord aX, nscoord aY,
- const nscoord* aSpacing = nsnull)
- { return NS_ERROR_NOT_IMPLEMENTED; }
- NS_IMETHOD DrawStringInternal(const PRUnichar *aString, PRUint32 aLength,
- nscoord aX, nscoord aY,
- PRInt32 aFontID = -1,
- const nscoord* aSpacing = nsnull)
- { return NS_ERROR_NOT_IMPLEMENTED; }
-
- gfxContext *ThebesContext() { return nsnull; }
-
-protected:
- virtual ~nsRenderingContextImpl();
-
-};
-
-#endif /* nsRenderingContextImpl */
--- a/gfx/src/shared/Makefile.in
+++ b/gfx/src/shared/Makefile.in
@@ -52,17 +52,16 @@ REQUIRES= \
xpcom \
string \
imglib2 \
widget \
thebes \
$(NULL)
CPPSRCS = \
- nsRenderingContextImpl.cpp \
gfxImageFrame.cpp \
$(NULL)
LOCAL_INCLUDES = -I$(srcdir)/.. \
$(NULL)
include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/gfx/src/shared/nsRenderingContextImpl.cpp
+++ /dev/null
@@ -1,508 +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 ***** */
-
-#include "nsCOMPtr.h"
-#include "nsRenderingContextImpl.h"
-#include "nsIDeviceContext.h"
-#include "nsIImage.h"
-#include "nsIRegion.h"
-#include "nsIFontMetrics.h"
-#include <stdlib.h>
-
-
-/** ---------------------------------------------------
- * See documentation in nsIRenderingContext.h
- * @update 3/16/00 dwc
- */
-nsRenderingContextImpl :: nsRenderingContextImpl()
-{
-}
-
-/** ---------------------------------------------------
- * See documentation in nsIRenderingContext.h
- * @update 3/16/00 dwc
- */
-nsRenderingContextImpl :: ~nsRenderingContextImpl()
-{
-
-
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::GetRightToLeftText(PRBool* aIsRTL)
-{
- *aIsRTL = PR_FALSE;
- return NS_OK;
-}
-
-#include "imgIContainer.h"
-#include "gfxIImageFrame.h"
-#include "nsIInterfaceRequestor.h"
-#include "nsIInterfaceRequestorUtils.h"
-
-// Hard limit substring lengths to 8000 characters ... this lets us statically
-// size the cluster buffer array in FindSafeLength
-#define MAX_GFX_TEXT_BUF_SIZE 8000
-static PRInt32 GetMaxChunkLength(nsRenderingContextImpl* aContext)
-{
- PRInt32 len = aContext->GetMaxStringLength();
- return PR_MIN(len, MAX_GFX_TEXT_BUF_SIZE);
-}
-
-static PRInt32 FindSafeLength(nsRenderingContextImpl* aContext,
- const PRUnichar *aString, PRUint32 aLength,
- PRUint32 aMaxChunkLength)
-{
- if (aLength <= aMaxChunkLength)
- return aLength;
-
- PRInt32 len = aMaxChunkLength;
-
- // Ensure that we don't break inside a surrogate pair
- while (len > 0 && NS_IS_LOW_SURROGATE(aString[len])) {
- len--;
- }
- if (len == 0) {
- // We don't want our caller to go into an infinite loop, so don't return
- // zero. It's hard to imagine how we could actually get here unless there
- // are languages that allow clusters of arbitrary size. If there are and
- // someone feeds us a 500+ character cluster, too bad.
- return aMaxChunkLength;
- }
- return len;
-}
-
-static PRInt32 FindSafeLength(nsRenderingContextImpl* aContext,
- const char *aString, PRUint32 aLength,
- PRUint32 aMaxChunkLength)
-{
- // Since it's ASCII, we don't need to worry about clusters or RTL
- return PR_MIN(aLength, aMaxChunkLength);
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::GetWidth(const nsString& aString, nscoord &aWidth,
- PRInt32 *aFontID)
-{
- return GetWidth(aString.get(), aString.Length(), aWidth, aFontID);
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::GetWidth(const char* aString, nscoord& aWidth)
-{
- return GetWidth(aString, strlen(aString), aWidth);
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::DrawString(const nsString& aString, nscoord aX, nscoord aY,
- PRInt32 aFontID, const nscoord* aSpacing)
-{
- return DrawString(aString.get(), aString.Length(), aX, aY, aFontID, aSpacing);
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::GetWidth(const char* aString, PRUint32 aLength,
- nscoord& aWidth)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- aWidth = 0;
- while (aLength > 0) {
- PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
- nscoord width;
- nsresult rv = GetWidthInternal(aString, len, width);
- if (NS_FAILED(rv))
- return rv;
- aWidth += width;
- aLength -= len;
- aString += len;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::GetWidth(const PRUnichar *aString, PRUint32 aLength,
- nscoord &aWidth, PRInt32 *aFontID)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- aWidth = 0;
-
- if (aFontID) {
- *aFontID = 0;
- }
-
- while (aLength > 0) {
- PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
- nscoord width;
- nsresult rv = GetWidthInternal(aString, len, width);
- if (NS_FAILED(rv))
- return rv;
- aWidth += width;
- aLength -= len;
- aString += len;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::GetTextDimensions(const char* aString, PRUint32 aLength,
- nsTextDimensions& aDimensions)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- if (aLength <= maxChunkLength)
- return GetTextDimensionsInternal(aString, aLength, aDimensions);
-
- PRBool firstIteration = PR_TRUE;
- while (aLength > 0) {
- PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
- nsTextDimensions dimensions;
- nsresult rv = GetTextDimensionsInternal(aString, len, dimensions);
- if (NS_FAILED(rv))
- return rv;
- if (firstIteration) {
- // Instead of combining with a Clear()ed nsTextDimensions, we assign
- // directly in the first iteration. This ensures that negative ascent/
- // descent can be returned.
- aDimensions = dimensions;
- } else {
- aDimensions.Combine(dimensions);
- }
- aLength -= len;
- aString += len;
- firstIteration = PR_FALSE;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
- nsTextDimensions& aDimensions, PRInt32* aFontID)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- if (aLength <= maxChunkLength)
- return GetTextDimensionsInternal(aString, aLength, aDimensions);
-
- if (aFontID) {
- *aFontID = nsnull;
- }
-
- PRBool firstIteration = PR_TRUE;
- while (aLength > 0) {
- PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
- nsTextDimensions dimensions;
- nsresult rv = GetTextDimensionsInternal(aString, len, dimensions);
- if (NS_FAILED(rv))
- return rv;
- if (firstIteration) {
- // Instead of combining with a Clear()ed nsTextDimensions, we assign
- // directly in the first iteration. This ensures that negative ascent/
- // descent can be returned.
- aDimensions = dimensions;
- } else {
- aDimensions.Combine(dimensions);
- }
- aLength -= len;
- aString += len;
- firstIteration = PR_FALSE;
- }
- return NS_OK;
-}
-
-#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS)
-NS_IMETHODIMP
-nsRenderingContextImpl::GetTextDimensions(const char* aString,
- PRInt32 aLength,
- PRInt32 aAvailWidth,
- PRInt32* aBreaks,
- PRInt32 aNumBreaks,
- nsTextDimensions& aDimensions,
- PRInt32& aNumCharsFit,
- nsTextDimensions& aLastWordDimensions,
- PRInt32* aFontID)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- if (aLength <= PRInt32(maxChunkLength))
- return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks, aNumBreaks,
- aDimensions, aNumCharsFit, aLastWordDimensions, aFontID);
-
- if (aFontID) {
- *aFontID = 0;
- }
-
- // Do a naive implementation based on 3-arg GetTextDimensions
- PRInt32 x = 0;
- PRInt32 wordCount;
- for (wordCount = 0; wordCount < aNumBreaks; ++wordCount) {
- PRInt32 lastBreak = wordCount > 0 ? aBreaks[wordCount - 1] : 0;
- nsTextDimensions dimensions;
-
- NS_ASSERTION(aBreaks[wordCount] > lastBreak, "Breaks must be monotonically increasing");
- NS_ASSERTION(aBreaks[wordCount] <= aLength, "Breaks can't exceed string length");
-
- // Call safe method
-
- nsresult rv =
- GetTextDimensions(aString + lastBreak, aBreaks[wordCount] - lastBreak,
- dimensions);
- if (NS_FAILED(rv))
- return rv;
- x += dimensions.width;
- // The first word always "fits"
- if (x > aAvailWidth && wordCount > 0)
- break;
- // aDimensions ascent/descent should exclude the last word (unless there
- // is only one word) so we let it run one word behind
- if (wordCount == 0) {
- aDimensions = dimensions;
- } else {
- aDimensions.Combine(aLastWordDimensions);
- }
- aNumCharsFit = aBreaks[wordCount];
- aLastWordDimensions = dimensions;
- }
- // aDimensions width should include all the text
- aDimensions.width = x;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::GetTextDimensions(const PRUnichar* aString,
- PRInt32 aLength,
- PRInt32 aAvailWidth,
- PRInt32* aBreaks,
- PRInt32 aNumBreaks,
- nsTextDimensions& aDimensions,
- PRInt32& aNumCharsFit,
- nsTextDimensions& aLastWordDimensions,
- PRInt32* aFontID)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- if (aLength <= PRInt32(maxChunkLength))
- return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks, aNumBreaks,
- aDimensions, aNumCharsFit, aLastWordDimensions, aFontID);
-
- if (aFontID) {
- *aFontID = 0;
- }
-
- // Do a naive implementation based on 3-arg GetTextDimensions
- PRInt32 x = 0;
- PRInt32 wordCount;
- for (wordCount = 0; wordCount < aNumBreaks; ++wordCount) {
- PRInt32 lastBreak = wordCount > 0 ? aBreaks[wordCount - 1] : 0;
-
- NS_ASSERTION(aBreaks[wordCount] > lastBreak, "Breaks must be monotonically increasing");
- NS_ASSERTION(aBreaks[wordCount] <= aLength, "Breaks can't exceed string length");
-
- nsTextDimensions dimensions;
- // Call safe method
- nsresult rv =
- GetTextDimensions(aString + lastBreak, aBreaks[wordCount] - lastBreak,
- dimensions);
- if (NS_FAILED(rv))
- return rv;
- x += dimensions.width;
- // The first word always "fits"
- if (x > aAvailWidth && wordCount > 0)
- break;
- // aDimensions ascent/descent should exclude the last word (unless there
- // is only one word) so we let it run one word behind
- if (wordCount == 0) {
- aDimensions = dimensions;
- } else {
- aDimensions.Combine(aLastWordDimensions);
- }
- aNumCharsFit = aBreaks[wordCount];
- aLastWordDimensions = dimensions;
- }
- // aDimensions width should include all the text
- aDimensions.width = x;
- return NS_OK;
-}
-#endif
-
-#ifdef MOZ_MATHML
-NS_IMETHODIMP
-nsRenderingContextImpl::GetBoundingMetrics(const char* aString,
- PRUint32 aLength,
- nsBoundingMetrics& aBoundingMetrics)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- if (aLength <= maxChunkLength)
- return GetBoundingMetricsInternal(aString, aLength, aBoundingMetrics);
-
- PRBool firstIteration = PR_TRUE;
- while (aLength > 0) {
- PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
- nsBoundingMetrics metrics;
- nsresult rv = GetBoundingMetricsInternal(aString, len, metrics);
- if (NS_FAILED(rv))
- return rv;
- if (firstIteration) {
- // Instead of combining with a Clear()ed nsBoundingMetrics, we assign
- // directly in the first iteration. This ensures that negative ascent/
- // descent can be returned and the left bearing is properly initialized.
- aBoundingMetrics = metrics;
- } else {
- aBoundingMetrics += metrics;
- }
- aLength -= len;
- aString += len;
- firstIteration = PR_FALSE;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::GetBoundingMetrics(const PRUnichar* aString,
- PRUint32 aLength,
- nsBoundingMetrics& aBoundingMetrics,
- PRInt32* aFontID)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- if (aLength <= maxChunkLength)
- return GetBoundingMetricsInternal(aString, aLength, aBoundingMetrics, aFontID);
-
- if (aFontID) {
- *aFontID = 0;
- }
-
- PRBool firstIteration = PR_TRUE;
- while (aLength > 0) {
- PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
- nsBoundingMetrics metrics;
- nsresult rv = GetBoundingMetricsInternal(aString, len, metrics);
- if (NS_FAILED(rv))
- return rv;
- if (firstIteration) {
- // Instead of combining with a Clear()ed nsBoundingMetrics, we assign
- // directly in the first iteration. This ensures that negative ascent/
- // descent can be returned and the left bearing is properly initialized.
- aBoundingMetrics = metrics;
- } else {
- aBoundingMetrics += metrics;
- }
- aLength -= len;
- aString += len;
- firstIteration = PR_FALSE;
- }
- return NS_OK;
-}
-#endif
-
-NS_IMETHODIMP
-nsRenderingContextImpl::DrawString(const char *aString, PRUint32 aLength,
- nscoord aX, nscoord aY,
- const nscoord* aSpacing)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- while (aLength > 0) {
- PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
- nsresult rv = DrawStringInternal(aString, len, aX, aY);
- if (NS_FAILED(rv))
- return rv;
- aLength -= len;
-
- if (aLength > 0) {
- nscoord width;
- rv = GetWidthInternal(aString, len, width);
- if (NS_FAILED(rv))
- return rv;
- aX += width;
- aString += len;
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsRenderingContextImpl::DrawString(const PRUnichar *aString, PRUint32 aLength,
- nscoord aX, nscoord aY,
- PRInt32 aFontID,
- const nscoord* aSpacing)
-{
- PRUint32 maxChunkLength = GetMaxChunkLength(this);
- if (aLength <= maxChunkLength) {
- return DrawStringInternal(aString, aLength, aX, aY, aFontID, aSpacing);
- }
-
- PRBool isRTL = PR_FALSE;
- GetRightToLeftText(&isRTL);
-
- if (isRTL) {
- nscoord totalWidth = 0;
- if (aSpacing) {
- for (PRUint32 i = 0; i < aLength; ++i) {
- totalWidth += aSpacing[i];
- }
- } else {
- nsresult rv = GetWidth(aString, aLength, totalWidth);
- if (NS_FAILED(rv))
- return rv;
- }
- aX += totalWidth;
- }
-
- while (aLength > 0) {
- PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
- nscoord width = 0;
- if (aSpacing) {
- for (PRInt32 i = 0; i < len; ++i) {
- width += aSpacing[i];
- }
- } else {
- nsresult rv = GetWidthInternal(aString, len, width);
- if (NS_FAILED(rv))
- return rv;
- }
-
- if (isRTL) {
- aX -= width;
- }
- nsresult rv = DrawStringInternal(aString, len, aX, aY, aFontID, aSpacing);
- if (NS_FAILED(rv))
- return rv;
- aLength -= len;
- if (!isRTL) {
- aX += width;
- }
- aString += len;
- if (aSpacing) {
- aSpacing += len;
- }
- }
- return NS_OK;
-}
--- a/gfx/src/thebes/Makefile.in
+++ b/gfx/src/thebes/Makefile.in
@@ -52,24 +52,29 @@ IS_COMPONENT = 1
MODULE_NAME = nsGfxModule
GRE_MODULE = 1
LIBXUL_LIBRARY = 1
REQUIRES = xpcom \
string \
thebes \
widget \
+ locale \
view \
pref \
unicharutil \
imglib2 \
$(ZLIB_REQUIRES) \
qcms \
$(NULL)
+ifeq (,$(filter windows,$(MOZ_WIDGET_TOOLKIT)))
+REQUIRES += uconv
+endif
+
CPPSRCS = \
nsThebesDeviceContext.cpp \
nsThebesImage.cpp \
nsThebesRegion.cpp \
nsThebesGfxFactory.cpp \
nsThebesRenderingContext.cpp \
nsThebesFontMetrics.cpp \
nsThebesFontEnumerator.cpp \
--- a/gfx/src/thebes/nsThebesDeviceContext.cpp
+++ b/gfx/src/thebes/nsThebesDeviceContext.cpp
@@ -32,22 +32,30 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+#include "nsFont.h"
+#include "nsGfxCIID.h"
+#include "nsIFontMetrics.h"
+#include "nsHashtable.h"
+#include "nsILanguageAtomService.h"
+#include "nsUnicharUtils.h"
+
#include "nsIServiceManager.h"
#include "nsIPrefService.h"
#include "nsCRT.h"
#include "nsThebesDeviceContext.h"
#include "nsThebesRenderingContext.h"
+#include "gfxUserFontSet.h"
#include "nsIWidget.h"
#include "nsIView.h"
#include "nsILookAndFeel.h"
#ifdef MOZ_ENABLE_GTK2
// for getenv
#include <cstdlib>
@@ -109,42 +117,495 @@ static int x11_error_handler (Display *d
}
}
#endif
#ifdef PR_LOGGING
PRLogModuleInfo* gThebesGFXLog = nsnull;
#endif
-NS_IMPL_ISUPPORTS_INHERITED0(nsThebesDeviceContext, DeviceContextImpl)
+class nsFontCache
+{
+public:
+ nsFontCache();
+ ~nsFontCache();
+
+ nsresult Init(nsIDeviceContext* aContext);
+ nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
+ gfxUserFontSet* aUserFontSet,
+ nsIFontMetrics*& aMetrics);
+
+ nsresult FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
+ nsresult Compact();
+ nsresult Flush();
+ nsresult CreateFontMetricsInstance(nsIFontMetrics** fm);
+
+protected:
+ nsTArray<nsIFontMetrics*> mFontMetrics;
+ nsIDeviceContext *mContext; // we do not addref this since
+ // ownership is implied. MMP.
+};
+
+nsFontCache::nsFontCache()
+{
+ MOZ_COUNT_CTOR(nsFontCache);
+ mContext = nsnull;
+}
+
+nsFontCache::~nsFontCache()
+{
+ MOZ_COUNT_DTOR(nsFontCache);
+ Flush();
+}
+
+nsresult
+nsFontCache::Init(nsIDeviceContext* aContext)
+{
+ NS_PRECONDITION(nsnull != aContext, "null ptr");
+ // Note: we don't hold a reference to the device context, because it
+ // holds a reference to us and we don't want circular references
+ mContext = aContext;
+ return NS_OK;
+}
+
+nsresult
+nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
+ gfxUserFontSet* aUserFontSet, nsIFontMetrics*& aMetrics)
+{
+ // First check our cache
+ // start from the end, which is where we put the most-recent-used element
+
+ nsIFontMetrics* fm;
+ PRInt32 n = mFontMetrics.Length() - 1;
+ for (PRInt32 i = n; i >= 0; --i) {
+ fm = mFontMetrics[i];
+ nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm);
+ if (fm->Font().Equals(aFont) && tfm->GetUserFontSet() == aUserFontSet) {
+ nsCOMPtr<nsIAtom> langGroup;
+ fm->GetLangGroup(getter_AddRefs(langGroup));
+ if (aLangGroup == langGroup.get()) {
+ if (i != n) {
+ // promote it to the end of the cache
+ mFontMetrics.RemoveElementAt(i);
+ mFontMetrics.AppendElement(fm);
+ }
+ tfm->GetThebesFontGroup()->UpdateFontList();
+ NS_ADDREF(aMetrics = fm);
+ return NS_OK;
+ }
+ }
+ }
+
+ // It's not in the cache. Get font metrics and then cache them.
+
+ aMetrics = nsnull;
+ nsresult rv = CreateFontMetricsInstance(&fm);
+ if (NS_FAILED(rv)) return rv;
+ rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
+ if (NS_SUCCEEDED(rv)) {
+ // the mFontMetrics list has the "head" at the end, because append
+ // is cheaper than insert
+ mFontMetrics.AppendElement(fm);
+ aMetrics = fm;
+ NS_ADDREF(aMetrics);
+ return NS_OK;
+ }
+ fm->Destroy();
+ NS_RELEASE(fm);
+
+ // One reason why Init() fails is because the system is running out of
+ // resources. e.g., on Win95/98 only a very limited number of GDI
+ // objects are available. Compact the cache and try again.
+
+ Compact();
+ rv = CreateFontMetricsInstance(&fm);
+ if (NS_FAILED(rv)) return rv;
+ rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
+ if (NS_SUCCEEDED(rv)) {
+ mFontMetrics.AppendElement(fm);
+ aMetrics = fm;
+ NS_ADDREF(aMetrics);
+ return NS_OK;
+ }
+ fm->Destroy();
+ NS_RELEASE(fm);
+
+ // could not setup a new one, send an old one (XXX search a "best
+ // match"?)
+
+ n = mFontMetrics.Length() - 1; // could have changed in Compact()
+ if (n >= 0) {
+ aMetrics = mFontMetrics[n];
+ NS_ADDREF(aMetrics);
+ return NS_OK;
+ }
+
+ NS_POSTCONDITION(NS_SUCCEEDED(rv), "font metrics should not be null - bug 136248");
+ return rv;
+}
+
+nsresult
+nsFontCache::CreateFontMetricsInstance(nsIFontMetrics** fm)
+{
+ static NS_DEFINE_CID(kFontMetricsCID, NS_FONT_METRICS_CID);
+ return CallCreateInstance(kFontMetricsCID, fm);
+}
+
+nsresult nsFontCache::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics)
+{
+ mFontMetrics.RemoveElement(aFontMetrics);
+ return NS_OK;
+}
+
+nsresult nsFontCache::Compact()
+{
+ // Need to loop backward because the running element can be removed on
+ // the way
+ for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) {
+ nsIFontMetrics* fm = mFontMetrics[i];
+ nsIFontMetrics* oldfm = fm;
+ // Destroy() isn't here because we want our device context to be
+ // notified
+ NS_RELEASE(fm); // this will reset fm to nsnull
+ // if the font is really gone, it would have called back in
+ // FontMetricsDeleted() and would have removed itself
+ if (mFontMetrics.IndexOf(oldfm) >= 0) {
+ // nope, the font is still there, so let's hold onto it too
+ NS_ADDREF(oldfm);
+ }
+ }
+ return NS_OK;
+}
+
+nsresult nsFontCache::Flush()
+{
+ for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) {
+ nsIFontMetrics* fm = mFontMetrics[i];
+ // Destroy() will unhook our device context from the fm so that we
+ // won't waste time in triggering the notification of
+ // FontMetricsDeleted() in the subsequent release
+ fm->Destroy();
+ NS_RELEASE(fm);
+ }
+
+ mFontMetrics.Clear();
+
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS3(nsThebesDeviceContext, nsIDeviceContext, nsIObserver, nsISupportsWeakReference)
nsThebesDeviceContext::nsThebesDeviceContext()
{
#ifdef PR_LOGGING
if (!gThebesGFXLog)
gThebesGFXLog = PR_NewLogModule("thebesGfx");
#endif
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("#### Creating DeviceContext %p\n", this));
+ mAppUnitsPerDevPixel = nscoord(-1);
+ mAppUnitsPerInch = nscoord(-1);
+ mAppUnitsPerDevNotScaledPixel = nscoord(-1);
+ mPixelScale = 1.0f;
+
+ mFontCache = nsnull;
+ mWidget = nsnull;
+ mFontAliasTable = nsnull;
+
+#ifdef NS_DEBUG
+ mInitialized = PR_FALSE;
+#endif
+
mDepth = 0;
mWidth = 0;
mHeight = 0;
mPrintingScale = 1.0f;
- mWidgetSurfaceCache.Init();
-
#if defined(XP_WIN) && !defined(WINCE)
SCRIPT_DIGITSUBSTITUTE sds;
ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &sds);
#endif
}
+static PRBool DeleteValue(nsHashKey* aKey, void* aValue, void* closure)
+{
+ delete ((nsString*)aValue);
+ return PR_TRUE;
+}
+
nsThebesDeviceContext::~nsThebesDeviceContext()
{
+ nsCOMPtr<nsIObserverService> obs(do_GetService("@mozilla.org/observer-service;1"));
+ if (obs)
+ obs->RemoveObserver(this, "memory-pressure");
+
+ if (nsnull != mFontCache) {
+ delete mFontCache;
+ mFontCache = nsnull;
+ }
+
+ if (nsnull != mFontAliasTable) {
+ mFontAliasTable->Enumerate(DeleteValue);
+ delete mFontAliasTable;
+ }
+}
+
+NS_IMETHODIMP
+nsThebesDeviceContext::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aSomeData)
+{
+ if (mFontCache && !nsCRT::strcmp(aTopic, "memory-pressure")) {
+ mFontCache->Compact();
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsThebesDeviceContext::CreateFontCache()
+{
+ mFontCache = new nsFontCache();
+ if (!mFontCache) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return mFontCache->Init(this);
+}
+
+NS_IMETHODIMP nsThebesDeviceContext::FontMetricsDeleted(const nsIFontMetrics* aFontMetrics)
+{
+ if (mFontCache) {
+ mFontCache->FontMetricsDeleted(aFontMetrics);
+ }
+ return NS_OK;
+}
+
+void
+nsThebesDeviceContext::GetLocaleLangGroup(void)
+{
+ if (!mLocaleLangGroup) {
+ nsCOMPtr<nsILanguageAtomService> langService;
+ langService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
+ if (langService) {
+ mLocaleLangGroup = langService->GetLocaleLanguageGroup();
+ }
+ if (!mLocaleLangGroup) {
+ mLocaleLangGroup = do_GetAtom("x-western");
+ }
+ }
+}
+
+NS_IMETHODIMP nsThebesDeviceContext::GetMetricsFor(const nsFont& aFont,
+ nsIAtom* aLangGroup, gfxUserFontSet* aUserFontSet, nsIFontMetrics*& aMetrics)
+{
+ if (nsnull == mFontCache) {
+ nsresult rv = CreateFontCache();
+ if (NS_FAILED(rv)) {
+ aMetrics = nsnull;
+ return rv;
+ }
+ // XXX temporary fix for performance problem -- erik
+ GetLocaleLangGroup();
+ }
+
+ // XXX figure out why aLangGroup is NULL sometimes
+ if (!aLangGroup) {
+ aLangGroup = mLocaleLangGroup;
+ }
+
+ return mFontCache->GetMetricsFor(aFont, aLangGroup, aUserFontSet, aMetrics);
+}
+
+NS_IMETHODIMP nsThebesDeviceContext::GetMetricsFor(const nsFont& aFont,
+ gfxUserFontSet* aUserFontSet,
+ nsIFontMetrics*& aMetrics)
+{
+ if (nsnull == mFontCache) {
+ nsresult rv = CreateFontCache();
+ if (NS_FAILED(rv)) {
+ aMetrics = nsnull;
+ return rv;
+ }
+ // XXX temporary fix for performance problem -- erik
+ GetLocaleLangGroup();
+ }
+ return mFontCache->GetMetricsFor(aFont, mLocaleLangGroup, aUserFontSet,
+ aMetrics);
+}
+
+struct FontEnumData {
+ FontEnumData(nsIDeviceContext* aDC, nsString& aFaceName)
+ : mDC(aDC), mFaceName(aFaceName)
+ {}
+ nsIDeviceContext* mDC;
+ nsString& mFaceName;
+};
+
+static PRBool FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
+{
+ FontEnumData* data = (FontEnumData*)aData;
+ // XXX for now, all generic fonts are presumed to exist
+ // we may want to actually check if there's an installed conversion
+ if (aGeneric) {
+ data->mFaceName = aFamily;
+ return PR_FALSE; // found one, stop.
+ }
+ else {
+ nsAutoString local;
+ PRBool aliased;
+ data->mDC->GetLocalFontName(aFamily, local, aliased);
+ if (aliased || (NS_SUCCEEDED(data->mDC->CheckFontExistence(local)))) {
+ data->mFaceName = local;
+ return PR_FALSE; // found one, stop.
+ }
+ }
+ return PR_TRUE; // didn't exist, continue looking
+}
+
+NS_IMETHODIMP nsThebesDeviceContext::FirstExistingFont(const nsFont& aFont, nsString& aFaceName)
+{
+ FontEnumData data(this, aFaceName);
+ if (aFont.EnumerateFamilies(FontEnumCallback, &data)) {
+ return NS_ERROR_FAILURE; // ran out
+ }
+ return NS_OK;
+}
+
+class FontAliasKey: public nsHashKey
+{
+public:
+ FontAliasKey(const nsString& aString)
+ { mString.Assign(aString); }
+
+ virtual PRUint32 HashCode(void) const;
+ virtual PRBool Equals(const nsHashKey *aKey) const;
+ virtual nsHashKey *Clone(void) const;
+
+ nsString mString;
+};
+
+PRUint32 FontAliasKey::HashCode(void) const
+{
+ PRUint32 hash = 0;
+ const PRUnichar* string = mString.get();
+ PRUnichar ch;
+ while ((ch = *string++) != 0) {
+ // FYI: hash = hash*37 + ch
+ ch = ToUpperCase(ch);
+ hash = ((hash << 5) + (hash << 2) + hash) + ch;
+ }
+ return hash;
+}
+
+PRBool FontAliasKey::Equals(const nsHashKey *aKey) const
+{
+ return mString.Equals(((FontAliasKey*)aKey)->mString, nsCaseInsensitiveStringComparator());
+}
+
+nsHashKey* FontAliasKey::Clone(void) const
+{
+ return new FontAliasKey(mString);
+}
+
+nsresult nsThebesDeviceContext::CreateFontAliasTable()
+{
+ nsresult result = NS_OK;
+
+ if (nsnull == mFontAliasTable) {
+ mFontAliasTable = new nsHashtable();
+ if (nsnull != mFontAliasTable) {
+
+ nsAutoString times; times.AssignLiteral("Times");
+ nsAutoString timesNewRoman; timesNewRoman.AssignLiteral("Times New Roman");
+ nsAutoString timesRoman; timesRoman.AssignLiteral("Times Roman");
+ nsAutoString arial; arial.AssignLiteral("Arial");
+ nsAutoString helvetica; helvetica.AssignLiteral("Helvetica");
+ nsAutoString courier; courier.AssignLiteral("Courier");
+ nsAutoString courierNew; courierNew.AssignLiteral("Courier New");
+ nsAutoString nullStr;
+
+ AliasFont(times, timesNewRoman, timesRoman, PR_FALSE);
+ AliasFont(timesRoman, timesNewRoman, times, PR_FALSE);
+ AliasFont(timesNewRoman, timesRoman, times, PR_FALSE);
+ AliasFont(arial, helvetica, nullStr, PR_FALSE);
+ AliasFont(helvetica, arial, nullStr, PR_FALSE);
+ AliasFont(courier, courierNew, nullStr, PR_TRUE);
+ AliasFont(courierNew, courier, nullStr, PR_FALSE);
+ }
+ else {
+ result = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ return result;
+}
+
+nsresult nsThebesDeviceContext::AliasFont(const nsString& aFont,
+ const nsString& aAlias,
+ const nsString& aAltAlias,
+ PRBool aForceAlias)
+{
+ nsresult result = NS_OK;
+
+ if (nsnull != mFontAliasTable) {
+ if (aForceAlias || NS_FAILED(CheckFontExistence(aFont))) {
+ if (NS_SUCCEEDED(CheckFontExistence(aAlias))) {
+ nsString* entry = new nsString(aAlias);
+ if (nsnull != entry) {
+ FontAliasKey key(aFont);
+ mFontAliasTable->Put(&key, entry);
+ }
+ else {
+ result = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else if (!aAltAlias.IsEmpty() && NS_SUCCEEDED(CheckFontExistence(aAltAlias))) {
+ nsString* entry = new nsString(aAltAlias);
+ if (nsnull != entry) {
+ FontAliasKey key(aFont);
+ mFontAliasTable->Put(&key, entry);
+ }
+ else {
+ result = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ }
+ }
+ else {
+ result = NS_ERROR_FAILURE;
+ }
+ return result;
+}
+
+NS_IMETHODIMP nsThebesDeviceContext::GetLocalFontName(const nsString& aFaceName,
+ nsString& aLocalName,
+ PRBool& aAliased)
+{
+ nsresult result = NS_OK;
+
+ if (nsnull == mFontAliasTable) {
+ result = CreateFontAliasTable();
+ }
+
+ if (nsnull != mFontAliasTable) {
+ FontAliasKey key(aFaceName);
+ const nsString* alias = (const nsString*)mFontAliasTable->Get(&key);
+ if (nsnull != alias) {
+ aLocalName = *alias;
+ aAliased = PR_TRUE;
+ }
+ else {
+ aLocalName = aFaceName;
+ aAliased = PR_FALSE;
+ }
+ }
+ return result;
+}
+
+NS_IMETHODIMP nsThebesDeviceContext::FlushFontCache(void)
+{
+ if (nsnull != mFontCache)
+ mFontCache->Flush();
+ return NS_OK;
}
/* static */ void
nsThebesDeviceContext::Shutdown()
{
delete gSystemFonts;
gSystemFonts = nsnull;
}
@@ -283,16 +744,26 @@ nsThebesDeviceContext::SetDPI()
NS_IMETHODIMP
nsThebesDeviceContext::Init(nsNativeWidget aWidget)
{
mWidget = aWidget;
SetDPI();
+#ifdef NS_DEBUG
+ //NS_ASSERTION(!mInitialized, "device context is initialized twice!");
+ mInitialized = PR_TRUE;
+#endif
+
+ // register as a memory-pressure observer to free font resources
+ // in low-memory situations.
+ nsCOMPtr<nsIObserverService> obs(do_GetService("@mozilla.org/observer-service;1"));
+ if (obs)
+ obs->AddObserver(this, "memory-pressure", PR_TRUE);
#if defined(MOZ_ENABLE_GTK2) && defined(MOZ_X11)
if (getenv ("MOZ_X_SYNC")) {
PR_LOG (gThebesGFXLog, PR_LOG_DEBUG, ("+++ Enabling XSynchronize\n"));
XSynchronize (gdk_x11_get_default_xdisplay(), True);
XSetErrorHandler(x11_error_handler);
}
@@ -462,17 +933,16 @@ nsThebesDeviceContext::GetPaletteInfo(ns
{
aPaletteInfo.isPaletteDevice = PR_FALSE;
aPaletteInfo.sizePalette = 0;
aPaletteInfo.numReserved = 0;
aPaletteInfo.palette = nsnull;
return NS_OK;
}
-
NS_IMETHODIMP
nsThebesDeviceContext::ConvertPixel(nscolor aColor, PRUint32 & aPixel)
{
aPixel = aColor;
return NS_OK;
}
NS_IMETHODIMP
@@ -549,27 +1019,27 @@ nsThebesDeviceContext::InitForPrinting(n
CalcPrintingSize();
return NS_OK;
}
NS_IMETHODIMP
-nsThebesDeviceContext::PrepareDocument(PRUnichar * aTitle,
+nsThebesDeviceContext::PrepareDocument(PRUnichar * aTitle,
PRUnichar* aPrintToFileName)
{
return NS_OK;
}
NS_IMETHODIMP
-nsThebesDeviceContext::BeginDocument(PRUnichar* aTitle,
+nsThebesDeviceContext::BeginDocument(PRUnichar* aTitle,
PRUnichar* aPrintToFileName,
- PRInt32 aStartPage,
+ PRInt32 aStartPage,
PRInt32 aEndPage)
{
static const PRUnichar kEmpty[] = { '\0' };
nsresult rv;
rv = mPrintingSurface->BeginPrinting(nsDependentString(aTitle ? aTitle : kEmpty),
nsDependentString(aPrintToFileName ? aPrintToFileName : kEmpty));
@@ -656,17 +1126,17 @@ nsThebesDeviceContext::ComputeClientRect
// because the window may have moved onto a different screen. In the single
// monitor case, we only need to do the computation if we haven't done it
// once already, and remember that we have because we're assured it won't change.
nsCOMPtr<nsIScreen> screen;
FindScreen (getter_AddRefs(screen));
if (screen) {
PRInt32 x, y, width, height;
screen->GetAvailRect(&x, &y, &width, &height);
-
+
// convert to device units
outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
outRect->width = NSIntPixelsToAppUnits(width, AppUnitsPerDevPixel());
outRect->height = NSIntPixelsToAppUnits(height, AppUnitsPerDevPixel());
}
}
@@ -677,30 +1147,28 @@ nsThebesDeviceContext::ComputeFullAreaUs
// because the window may have moved onto a different screen. In the single
// monitor case, we only need to do the computation if we haven't done it
// once already, and remember that we have because we're assured it won't change.
nsCOMPtr<nsIScreen> screen;
FindScreen ( getter_AddRefs(screen) );
if ( screen ) {
PRInt32 x, y, width, height;
screen->GetRect ( &x, &y, &width, &height );
-
+
// convert to device units
outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
outRect->width = NSIntPixelsToAppUnits(width, AppUnitsPerDevPixel());
outRect->height = NSIntPixelsToAppUnits(height, AppUnitsPerDevPixel());
-
+
mWidth = outRect->width;
mHeight = outRect->height;
}
-
}
-
//
// FindScreen
//
// Determines which screen intersects the largest area of the given surface.
//
void
nsThebesDeviceContext::FindScreen(nsIScreen** outScreen)
{
--- a/gfx/src/thebes/nsThebesDeviceContext.h
+++ b/gfx/src/thebes/nsThebesDeviceContext.h
@@ -36,69 +36,94 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _NS_THEBESDEVICECONTEXT_H_
#define _NS_THEBESDEVICECONTEXT_H_
#include "nsIScreenManager.h"
-
-#include "nsDeviceContext.h"
+#include "nsIDeviceContext.h"
+#include "nsIDeviceContextSpec.h"
+#include "nsCOMPtr.h"
+#include "nsIAtom.h"
+#include "nsIObserver.h"
+#include "nsIObserverService.h"
+#include "nsWeakReference.h"
+#include "gfxContext.h"
#include "nsRefPtrHashtable.h"
#include "nsHashKeys.h"
#include "prlog.h"
-#include "gfxContext.h"
-
#ifdef PR_LOGGING
extern PRLogModuleInfo* gThebesGFXLog;
#endif
#ifdef XP_WIN
#include "gfxWindowsSurface.h"
#elif defined(XP_OS2)
#include "gfxOS2Surface.h"
#endif
-class nsThebesDeviceContext : public DeviceContextImpl
+class nsHashtable;
+class nsFontCache;
+
+class nsThebesDeviceContext : public nsIDeviceContext,
+ public nsIObserver,
+ public nsSupportsWeakReference
{
public:
nsThebesDeviceContext();
virtual ~nsThebesDeviceContext();
static void Shutdown();
- NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
NS_IMETHOD Init(nsNativeWidget aWidget);
NS_IMETHOD InitForPrinting(nsIDeviceContextSpec *aDevSpec);
NS_IMETHOD CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext);
-
NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext);
NS_IMETHOD CreateRenderingContext(nsIRenderingContext *&aContext);
NS_IMETHOD CreateRenderingContextInstance(nsIRenderingContext *&aContext);
+ NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
+ gfxUserFontSet* aUserFontSet,
+ nsIFontMetrics*& aMetrics);
+ NS_IMETHOD GetMetricsFor(const nsFont& aFont,
+ gfxUserFontSet* aUserFontSet,
+ nsIFontMetrics*& aMetrics);
+
+ NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName);
+
+ NS_IMETHOD GetLocalFontName(const nsString& aFaceName, nsString& aLocalName,
+ PRBool& aAliased);
+
+ NS_IMETHOD CreateFontCache();
+ NS_IMETHOD FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
+ NS_IMETHOD FlushFontCache(void);
+
NS_IMETHOD SupportsNativeWidgets(PRBool& aSupportsWidgets);
NS_IMETHOD PrepareNativeWidget(nsIWidget *aWidget, void **aOut);
NS_IMETHOD GetSystemFont(nsSystemFontID aID, nsFont *aFont) const;
NS_IMETHOD ClearCachedSystemFonts();
NS_IMETHOD CheckFontExistence(const nsString& aFaceName);
NS_IMETHOD GetDepth(PRUint32& aDepth);
NS_IMETHOD GetPaletteInfo(nsPaletteInfo& aPaletteInfo);
NS_IMETHOD ConvertPixel(nscolor aColor, PRUint32& aPixel);
- NS_IMETHOD GetDeviceSurfaceDimensions(PRInt32& aWidth, PRInt32& aHeight);
+ NS_IMETHOD GetDeviceSurfaceDimensions(nscoord& aWidth, nscoord& aHeight);
NS_IMETHOD GetRect(nsRect& aRect);
NS_IMETHOD GetClientRect(nsRect& aRect);
/* printing goop */
NS_IMETHOD PrepareDocument(PRUnichar *aTitle,
PRUnichar *aPrintToFileName);
NS_IMETHOD BeginDocument(PRUnichar *aTitle,
@@ -121,32 +146,42 @@ public:
PRBool IsPrinterSurface(void);
nsNativeWidget GetWidget() { return mWidget; }
#if defined(XP_WIN) || defined(XP_OS2)
HDC GetPrintHDC();
#endif
protected:
+ virtual nsresult CreateFontAliasTable();
+ nsresult AliasFont(const nsString& aFont,
+ const nsString& aAlias, const nsString& aAltAlias,
+ PRBool aForceAlias);
+ void GetLocaleLangGroup(void);
nsresult SetDPI();
void ComputeClientRectUsingScreen(nsRect *outRect);
void ComputeFullAreaUsingScreen(nsRect *outRect);
void FindScreen(nsIScreen **outScreen);
void CalcPrintingSize();
void UpdateScaledAppUnits();
- PRUint32 mDepth;
+ PRUint32 mDepth;
+ nsFontCache* mFontCache;
+ nsCOMPtr<nsIAtom> mLocaleLangGroup; // XXX temp fix for performance bug - erik
+ nsHashtable* mFontAliasTable;
+ nsNativeWidget mWidget;
+#ifdef NS_DEBUG
+ PRBool mInitialized;
+#endif
private:
nsCOMPtr<nsIScreenManager> mScreenManager;
nscoord mWidth;
nscoord mHeight;
- nsRefPtrHashtable<nsISupportsHashKey, gfxASurface> mWidgetSurfaceCache;
-
nsRefPtr<gfxASurface> mPrintingSurface;
float mPrintingScale;
nsCOMPtr<nsIDeviceContextSpec> mDeviceContextSpec;
};
#endif /* _NS_CAIRODEVICECONTEXT_H_ */
--- a/gfx/src/thebes/nsThebesRenderingContext.cpp
+++ b/gfx/src/thebes/nsThebesRenderingContext.cpp
@@ -35,32 +35,30 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsThebesRenderingContext.h"
#include "nsThebesDeviceContext.h"
-#include "nsRect.h"
#include "nsString.h"
#include "nsTransform2D.h"
-#include "nsIRegion.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsGfxCIID.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
-#include "nsIThebesFontMetrics.h"
#include "nsThebesRegion.h"
#include "nsThebesImage.h"
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "gfxPlatform.h"
#ifdef XP_WIN
#include "gfxWindowsSurface.h"
@@ -76,16 +74,57 @@ static NS_DEFINE_CID(kRegionCID, NS_REGI
#define FROM_TWIPS_INT(_x) (NSToIntRound((gfxFloat)((_x)/(mP2A))))
#define TO_TWIPS(_x) ((nscoord)((_x)*(mP2A)))
#define GFX_RECT_FROM_TWIPS_RECT(_r) (gfxRect(FROM_TWIPS((_r).x), FROM_TWIPS((_r).y), FROM_TWIPS((_r).width), FROM_TWIPS((_r).height)))
//////////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS1(nsThebesRenderingContext, nsIRenderingContext)
+// Hard limit substring lengths to 8000 characters ... this lets us statically
+// size the cluster buffer array in FindSafeLength
+#define MAX_GFX_TEXT_BUF_SIZE 8000
+static PRInt32 GetMaxChunkLength(nsThebesRenderingContext* aContext)
+{
+ PRInt32 len = aContext->GetMaxStringLength();
+ return PR_MIN(len, MAX_GFX_TEXT_BUF_SIZE);
+}
+
+static PRInt32 FindSafeLength(nsThebesRenderingContext* aContext,
+ const PRUnichar *aString, PRUint32 aLength,
+ PRUint32 aMaxChunkLength)
+{
+ if (aLength <= aMaxChunkLength)
+ return aLength;
+
+ PRInt32 len = aMaxChunkLength;
+
+ // Ensure that we don't break inside a surrogate pair
+ while (len > 0 && NS_IS_LOW_SURROGATE(aString[len])) {
+ len--;
+ }
+ if (len == 0) {
+ // We don't want our caller to go into an infinite loop, so don't
+ // return zero. It's hard to imagine how we could actually get here
+ // unless there are languages that allow clusters of arbitrary size.
+ // If there are and someone feeds us a 500+ character cluster, too
+ // bad.
+ return aMaxChunkLength;
+ }
+ return len;
+}
+
+static PRInt32 FindSafeLength(nsThebesRenderingContext* aContext,
+ const char *aString, PRUint32 aLength,
+ PRUint32 aMaxChunkLength)
+{
+ // Since it's ASCII, we don't need to worry about clusters or RTL
+ return PR_MIN(aLength, aMaxChunkLength);
+}
+
nsThebesRenderingContext::nsThebesRenderingContext()
: mLineStyle(nsLineStyle_kNone)
, mColor(NS_RGB(0,0,0))
{
}
nsThebesRenderingContext::~nsThebesRenderingContext()
{
@@ -154,17 +193,17 @@ nsThebesRenderingContext::CommonInit(voi
NS_IMETHODIMP
nsThebesRenderingContext::GetDeviceContext(nsIDeviceContext *& aDeviceContext)
{
aDeviceContext = mDeviceContext;
NS_IF_ADDREF(aDeviceContext);
return NS_OK;
}
-NS_IMETHODIMP
+NS_IMETHODIMP
nsThebesRenderingContext::PushTranslation(PushedTranslation* aState)
{
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::PushTranslation\n", this));
// XXX this is slow!
PushState();
return NS_OK;
}
@@ -293,16 +332,17 @@ nsThebesRenderingContext::SetClipRegion(
evilPxRegion->FreeRects (rects);
}
mThebes->SetMatrix(mat);
return NS_OK;
}
+
//
// other junk
//
NS_IMETHODIMP
nsThebesRenderingContext::SetLineStyle(nsLineStyle aLineStyle)
{
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::SetLineStyle %d\n", this, aLineStyle));
@@ -331,17 +371,17 @@ nsThebesRenderingContext::SetLineStyle(n
NS_IMETHODIMP
nsThebesRenderingContext::SetColor(nscolor aColor)
{
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::SetColor 0x%08x\n", this, aColor));
/* This sets the color assuming the sRGB color space, since that's what all
* CSS colors are defined to be in by the spec.
*/
mThebes->SetColor(gfxRGBA(aColor));
-
+
mColor = aColor;
return NS_OK;
}
NS_IMETHODIMP
nsThebesRenderingContext::GetColor(nscolor &aColor) const
{
aColor = mColor;
@@ -775,17 +815,17 @@ nsThebesRenderingContext::GetRightToLeft
{
*aIsRTL = mFontMetrics->GetRightToLeftText();
return NS_OK;
}
void
nsThebesRenderingContext::SetTextRunRTL(PRBool aIsRTL)
{
- mFontMetrics->SetTextRunRTL(aIsRTL);
+ mFontMetrics->SetTextRunRTL(aIsRTL);
}
NS_IMETHODIMP
nsThebesRenderingContext::SetFont(const nsFont& aFont, nsIAtom* aLangGroup,
gfxUserFontSet *aUserFontSet)
{
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::SetFont %p\n", this, &aFont));
@@ -811,19 +851,19 @@ nsThebesRenderingContext::GetFontMetrics
aFontMetrics = mFontMetrics;
NS_IF_ADDREF(aFontMetrics);
return NS_OK;
}
PRInt32
nsThebesRenderingContext::GetMaxStringLength()
{
- if (!mFontMetrics)
- return 1;
- return mFontMetrics->GetMaxStringLength();
+ if (!mFontMetrics)
+ return 1;
+ return mFontMetrics->GetMaxStringLength();
}
NS_IMETHODIMP
nsThebesRenderingContext::GetWidth(char aC, nscoord &aWidth)
{
if (aC == ' ' && mFontMetrics)
return mFontMetrics->GetSpaceWidth(aWidth);
@@ -832,131 +872,532 @@ nsThebesRenderingContext::GetWidth(char
NS_IMETHODIMP
nsThebesRenderingContext::GetWidth(PRUnichar aC, nscoord &aWidth, PRInt32 *aFontID)
{
return GetWidth(&aC, 1, aWidth, aFontID);
}
NS_IMETHODIMP
+nsThebesRenderingContext::GetWidth(const nsString& aString, nscoord &aWidth,
+ PRInt32 *aFontID)
+{
+ return GetWidth(aString.get(), aString.Length(), aWidth, aFontID);
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::GetWidth(const char* aString, nscoord& aWidth)
+{
+ return GetWidth(aString, strlen(aString), aWidth);
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::DrawString(const nsString& aString, nscoord aX, nscoord aY,
+ PRInt32 aFontID, const nscoord* aSpacing)
+{
+ return DrawString(aString.get(), aString.Length(), aX, aY, aFontID, aSpacing);
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::GetWidth(const char* aString,
+ PRUint32 aLength,
+ nscoord& aWidth)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ aWidth = 0;
+ while (aLength > 0) {
+ PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
+ nscoord width;
+ nsresult rv = GetWidthInternal(aString, len, width);
+ if (NS_FAILED(rv))
+ return rv;
+ aWidth += width;
+ aLength -= len;
+ aString += len;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::GetWidth(const PRUnichar *aString,
+ PRUint32 aLength,
+ nscoord &aWidth,
+ PRInt32 *aFontID)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ aWidth = 0;
+
+ if (aFontID) {
+ *aFontID = 0;
+ }
+
+ while (aLength > 0) {
+ PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
+ nscoord width;
+ nsresult rv = GetWidthInternal(aString, len, width);
+ if (NS_FAILED(rv))
+ return rv;
+ aWidth += width;
+ aLength -= len;
+ aString += len;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::GetTextDimensions(const char* aString,
+ PRUint32 aLength,
+ nsTextDimensions& aDimensions)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ if (aLength <= maxChunkLength)
+ return GetTextDimensionsInternal(aString, aLength, aDimensions);
+
+ PRBool firstIteration = PR_TRUE;
+ while (aLength > 0) {
+ PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
+ nsTextDimensions dimensions;
+ nsresult rv = GetTextDimensionsInternal(aString, len, dimensions);
+ if (NS_FAILED(rv))
+ return rv;
+ if (firstIteration) {
+ // Instead of combining with a Clear()ed nsTextDimensions, we
+ // assign directly in the first iteration. This ensures that
+ // negative ascent/ descent can be returned.
+ aDimensions = dimensions;
+ } else {
+ aDimensions.Combine(dimensions);
+ }
+ aLength -= len;
+ aString += len;
+ firstIteration = PR_FALSE;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::GetTextDimensions(const PRUnichar* aString,
+ PRUint32 aLength,
+ nsTextDimensions& aDimensions,
+ PRInt32* aFontID)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ if (aLength <= maxChunkLength)
+ return GetTextDimensionsInternal(aString, aLength, aDimensions);
+
+ if (aFontID) {
+ *aFontID = nsnull;
+ }
+
+ PRBool firstIteration = PR_TRUE;
+ while (aLength > 0) {
+ PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
+ nsTextDimensions dimensions;
+ nsresult rv = GetTextDimensionsInternal(aString, len, dimensions);
+ if (NS_FAILED(rv))
+ return rv;
+ if (firstIteration) {
+ // Instead of combining with a Clear()ed nsTextDimensions, we
+ // assign directly in the first iteration. This ensures that
+ // negative ascent/ descent can be returned.
+ aDimensions = dimensions;
+ } else {
+ aDimensions.Combine(dimensions);
+ }
+ aLength -= len;
+ aString += len;
+ firstIteration = PR_FALSE;
+ }
+ return NS_OK;
+}
+
+#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS)
+NS_IMETHODIMP
+nsThebesRenderingContext::GetTextDimensions(const char* aString,
+ PRInt32 aLength,
+ PRInt32 aAvailWidth,
+ PRInt32* aBreaks,
+ PRInt32 aNumBreaks,
+ nsTextDimensions& aDimensions,
+ PRInt32& aNumCharsFit,
+ nsTextDimensions& aLastWordDimensions,
+ PRInt32* aFontID)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ if (aLength <= PRInt32(maxChunkLength))
+ return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks, aNumBreaks,
+ aDimensions, aNumCharsFit, aLastWordDimensions, aFontID);
+
+ if (aFontID) {
+ *aFontID = 0;
+ }
+
+ // Do a naive implementation based on 3-arg GetTextDimensions
+ PRInt32 x = 0;
+ PRInt32 wordCount;
+ for (wordCount = 0; wordCount < aNumBreaks; ++wordCount) {
+ PRInt32 lastBreak = wordCount > 0 ? aBreaks[wordCount - 1] : 0;
+ nsTextDimensions dimensions;
+
+ NS_ASSERTION(aBreaks[wordCount] > lastBreak, "Breaks must be monotonically increasing");
+ NS_ASSERTION(aBreaks[wordCount] <= aLength, "Breaks can't exceed string length");
+
+ // Call safe method
+
+ nsresult rv =
+ GetTextDimensions(aString + lastBreak, aBreaks[wordCount] - lastBreak,
+ dimensions);
+ if (NS_FAILED(rv))
+ return rv;
+ x += dimensions.width;
+ // The first word always "fits"
+ if (x > aAvailWidth && wordCount > 0)
+ break;
+ // aDimensions ascent/descent should exclude the last word (unless there
+ // is only one word) so we let it run one word behind
+ if (wordCount == 0) {
+ aDimensions = dimensions;
+ } else {
+ aDimensions.Combine(aLastWordDimensions);
+ }
+ aNumCharsFit = aBreaks[wordCount];
+ aLastWordDimensions = dimensions;
+ }
+ // aDimensions width should include all the text
+ aDimensions.width = x;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::GetTextDimensions(const PRUnichar* aString,
+ PRInt32 aLength,
+ PRInt32 aAvailWidth,
+ PRInt32* aBreaks,
+ PRInt32 aNumBreaks,
+ nsTextDimensions& aDimensions,
+ PRInt32& aNumCharsFit,
+ nsTextDimensions& aLastWordDimensions,
+ PRInt32* aFontID)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ if (aLength <= PRInt32(maxChunkLength))
+ return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks, aNumBreaks,
+ aDimensions, aNumCharsFit, aLastWordDimensions, aFontID);
+
+ if (aFontID) {
+ *aFontID = 0;
+ }
+
+ // Do a naive implementation based on 3-arg GetTextDimensions
+ PRInt32 x = 0;
+ PRInt32 wordCount;
+ for (wordCount = 0; wordCount < aNumBreaks; ++wordCount) {
+ PRInt32 lastBreak = wordCount > 0 ? aBreaks[wordCount - 1] : 0;
+
+ NS_ASSERTION(aBreaks[wordCount] > lastBreak, "Breaks must be monotonically increasing");
+ NS_ASSERTION(aBreaks[wordCount] <= aLength, "Breaks can't exceed string length");
+
+ nsTextDimensions dimensions;
+ // Call safe method
+ nsresult rv =
+ GetTextDimensions(aString + lastBreak, aBreaks[wordCount] - lastBreak,
+ dimensions);
+ if (NS_FAILED(rv))
+ return rv;
+ x += dimensions.width;
+ // The first word always "fits"
+ if (x > aAvailWidth && wordCount > 0)
+ break;
+ // aDimensions ascent/descent should exclude the last word (unless there
+ // is only one word) so we let it run one word behind
+ if (wordCount == 0) {
+ aDimensions = dimensions;
+ } else {
+ aDimensions.Combine(aLastWordDimensions);
+ }
+ aNumCharsFit = aBreaks[wordCount];
+ aLastWordDimensions = dimensions;
+ }
+ // aDimensions width should include all the text
+ aDimensions.width = x;
+ return NS_OK;
+}
+#endif
+
+#ifdef MOZ_MATHML
+NS_IMETHODIMP
+nsThebesRenderingContext::GetBoundingMetrics(const char* aString,
+ PRUint32 aLength,
+ nsBoundingMetrics& aBoundingMetrics)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ if (aLength <= maxChunkLength)
+ return GetBoundingMetricsInternal(aString, aLength, aBoundingMetrics);
+
+ PRBool firstIteration = PR_TRUE;
+ while (aLength > 0) {
+ PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
+ nsBoundingMetrics metrics;
+ nsresult rv = GetBoundingMetricsInternal(aString, len, metrics);
+ if (NS_FAILED(rv))
+ return rv;
+ if (firstIteration) {
+ // Instead of combining with a Clear()ed nsBoundingMetrics, we
+ // assign directly in the first iteration. This ensures that
+ // negative ascent/ descent can be returned and the left bearing
+ // is properly initialized.
+ aBoundingMetrics = metrics;
+ } else {
+ aBoundingMetrics += metrics;
+ }
+ aLength -= len;
+ aString += len;
+ firstIteration = PR_FALSE;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::GetBoundingMetrics(const PRUnichar* aString,
+ PRUint32 aLength,
+ nsBoundingMetrics& aBoundingMetrics,
+ PRInt32* aFontID)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ if (aLength <= maxChunkLength)
+ return GetBoundingMetricsInternal(aString, aLength, aBoundingMetrics, aFontID);
+
+ if (aFontID) {
+ *aFontID = 0;
+ }
+
+ PRBool firstIteration = PR_TRUE;
+ while (aLength > 0) {
+ PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
+ nsBoundingMetrics metrics;
+ nsresult rv = GetBoundingMetricsInternal(aString, len, metrics);
+ if (NS_FAILED(rv))
+ return rv;
+ if (firstIteration) {
+ // Instead of combining with a Clear()ed nsBoundingMetrics, we
+ // assign directly in the first iteration. This ensures that
+ // negative ascent/ descent can be returned and the left bearing
+ // is properly initialized.
+ aBoundingMetrics = metrics;
+ } else {
+ aBoundingMetrics += metrics;
+ }
+ aLength -= len;
+ aString += len;
+ firstIteration = PR_FALSE;
+ }
+ return NS_OK;
+}
+#endif
+
+NS_IMETHODIMP
+nsThebesRenderingContext::DrawString(const char *aString, PRUint32 aLength,
+ nscoord aX, nscoord aY,
+ const nscoord* aSpacing)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ while (aLength > 0) {
+ PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
+ nsresult rv = DrawStringInternal(aString, len, aX, aY);
+ if (NS_FAILED(rv))
+ return rv;
+ aLength -= len;
+
+ if (aLength > 0) {
+ nscoord width;
+ rv = GetWidthInternal(aString, len, width);
+ if (NS_FAILED(rv))
+ return rv;
+ aX += width;
+ aString += len;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::DrawString(const PRUnichar *aString, PRUint32 aLength,
+ nscoord aX, nscoord aY,
+ PRInt32 aFontID,
+ const nscoord* aSpacing)
+{
+ PRUint32 maxChunkLength = GetMaxChunkLength(this);
+ if (aLength <= maxChunkLength) {
+ return DrawStringInternal(aString, aLength, aX, aY, aFontID, aSpacing);
+ }
+
+ PRBool isRTL = PR_FALSE;
+ GetRightToLeftText(&isRTL);
+
+ if (isRTL) {
+ nscoord totalWidth = 0;
+ if (aSpacing) {
+ for (PRUint32 i = 0; i < aLength; ++i) {
+ totalWidth += aSpacing[i];
+ }
+ } else {
+ nsresult rv = GetWidth(aString, aLength, totalWidth);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ aX += totalWidth;
+ }
+
+ while (aLength > 0) {
+ PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
+ nscoord width = 0;
+ if (aSpacing) {
+ for (PRInt32 i = 0; i < len; ++i) {
+ width += aSpacing[i];
+ }
+ } else {
+ nsresult rv = GetWidthInternal(aString, len, width);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ if (isRTL) {
+ aX -= width;
+ }
+ nsresult rv = DrawStringInternal(aString, len, aX, aY, aFontID, aSpacing);
+ if (NS_FAILED(rv))
+ return rv;
+ aLength -= len;
+ if (!isRTL) {
+ aX += width;
+ }
+ aString += len;
+ if (aSpacing) {
+ aSpacing += len;
+ }
+ }
+ return NS_OK;
+}
+
+nsresult
nsThebesRenderingContext::GetWidthInternal(const char* aString, PRUint32 aLength, nscoord& aWidth)
{
#ifdef DISABLE_TEXT
aWidth = (8 * aLength);
return NS_OK;
#endif
if (aLength == 0) {
aWidth = 0;
return NS_OK;
}
return mFontMetrics->GetWidth(aString, aLength, aWidth, this);
}
-NS_IMETHODIMP
+nsresult
nsThebesRenderingContext::GetWidthInternal(const PRUnichar *aString, PRUint32 aLength,
nscoord &aWidth, PRInt32 *aFontID)
{
#ifdef DISABLE_TEXT
aWidth = (8 * aLength);
return NS_OK;
#endif
if (aLength == 0) {
aWidth = 0;
return NS_OK;
}
return mFontMetrics->GetWidth(aString, aLength, aWidth, aFontID, this);
}
-NS_IMETHODIMP
+nsresult
nsThebesRenderingContext::GetTextDimensionsInternal(const char* aString, PRUint32 aLength,
nsTextDimensions& aDimensions)
{
- mFontMetrics->GetMaxAscent(aDimensions.ascent);
- mFontMetrics->GetMaxDescent(aDimensions.descent);
- return GetWidth(aString, aLength, aDimensions.width);
+ mFontMetrics->GetMaxAscent(aDimensions.ascent);
+ mFontMetrics->GetMaxDescent(aDimensions.descent);
+ return GetWidth(aString, aLength, aDimensions.width);
}
-NS_IMETHODIMP
+nsresult
nsThebesRenderingContext::GetTextDimensionsInternal(const PRUnichar* aString,
PRUint32 aLength,
nsTextDimensions& aDimensions,
PRInt32* aFontID)
{
- mFontMetrics->GetMaxAscent(aDimensions.ascent);
- mFontMetrics->GetMaxDescent(aDimensions.descent);
- return GetWidth(aString, aLength, aDimensions.width, aFontID);
+ mFontMetrics->GetMaxAscent(aDimensions.ascent);
+ mFontMetrics->GetMaxDescent(aDimensions.descent);
+ return GetWidth(aString, aLength, aDimensions.width, aFontID);
}
#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS) || defined(XP_MACOSX) || defined (MOZ_DFB)
-NS_IMETHODIMP
+nsresult
nsThebesRenderingContext::GetTextDimensionsInternal(const char* aString,
PRInt32 aLength,
PRInt32 aAvailWidth,
PRInt32* aBreaks,
PRInt32 aNumBreaks,
nsTextDimensions& aDimensions,
PRInt32& aNumCharsFit,
nsTextDimensions& aLastWordDimensions,
PRInt32* aFontID)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
-NS_IMETHODIMP
+nsresult
nsThebesRenderingContext::GetTextDimensionsInternal(const PRUnichar* aString,
PRInt32 aLength,
PRInt32 aAvailWidth,
PRInt32* aBreaks,
PRInt32 aNumBreaks,
nsTextDimensions& aDimensions,
PRInt32& aNumCharsFit,
nsTextDimensions& aLastWordDimensions,
PRInt32* aFontID)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
#endif
#ifdef MOZ_MATHML
-NS_IMETHODIMP
+nsresult
nsThebesRenderingContext::GetBoundingMetricsInternal(const char* aString,
PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics)
{
return mFontMetrics->GetBoundingMetrics(aString, aLength, this, aBoundingMetrics);
}
-NS_IMETHODIMP
+nsresult
nsThebesRenderingContext::GetBoundingMetricsInternal(const PRUnichar* aString,
PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics,
PRInt32* aFontID)
{
return mFontMetrics->GetBoundingMetrics(aString, aLength, this, aBoundingMetrics);
}
#endif // MOZ_MATHML
-NS_IMETHODIMP
+nsresult
nsThebesRenderingContext::DrawStringInternal(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
const nscoord* aSpacing)
{
#ifdef DISABLE_TEXT
return NS_OK;
#endif
return mFontMetrics->DrawString(aString, aLength, aX, aY, aSpacing,
this);
}
-NS_IMETHODIMP
+nsresult
nsThebesRenderingContext::DrawStringInternal(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
PRInt32 aFontID,
const nscoord* aSpacing)
{
#ifdef DISABLE_TEXT
return NS_OK;
#endif
--- a/gfx/src/thebes/nsThebesRenderingContext.h
+++ b/gfx/src/thebes/nsThebesRenderingContext.h
@@ -37,39 +37,106 @@
* ***** END LICENSE BLOCK ***** */
#ifndef NSTHEBESRENDERINGCONTEXT__H__
#define NSTHEBESRENDERINGCONTEXT__H__
#include "nsCOMPtr.h"
#include "nsTArray.h"
#include "nsIRenderingContext.h"
-#include "nsRenderingContextImpl.h"
#include "nsIDeviceContext.h"
#include "nsIFontMetrics.h"
#include "nsIWidget.h"
#include "nsPoint.h"
#include "nsSize.h"
#include "nsColor.h"
#include "nsRect.h"
#include "nsIRegion.h"
#include "nsTransform2D.h"
#include "nsIThebesFontMetrics.h"
#include "gfxContext.h"
class nsIImage;
-class nsThebesRenderingContext : public nsRenderingContextImpl
+class nsThebesRenderingContext : public nsIRenderingContext
{
public:
nsThebesRenderingContext();
virtual ~nsThebesRenderingContext();
NS_DECL_ISUPPORTS
+
+ /**
+ * Return the maximum length of a string that can be handled by the platform
+ * using the current font metrics.
+ */
+ virtual PRInt32 GetMaxStringLength();
+
+ // Safe string method variants: by default, these defer to the more
+ // elaborate methods below
+ NS_IMETHOD GetWidth(const nsString& aString, nscoord &aWidth,
+ PRInt32 *aFontID = nsnull);
+ NS_IMETHOD GetWidth(const char* aString, nscoord& aWidth);
+ NS_IMETHOD DrawString(const nsString& aString, nscoord aX, nscoord aY,
+ PRInt32 aFontID = -1,
+ const nscoord* aSpacing = nsnull);
+
+ // Safe string methods
+ NS_IMETHOD GetWidth(const char* aString, PRUint32 aLength,
+ nscoord& aWidth);
+ NS_IMETHOD GetWidth(const PRUnichar *aString, PRUint32 aLength,
+ nscoord &aWidth, PRInt32 *aFontID = nsnull);
+ NS_IMETHOD GetWidth(char aC, nscoord &aWidth);
+ NS_IMETHOD GetWidth(PRUnichar aC, nscoord &aWidth,
+ PRInt32 *aFontID);
+
+ NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength,
+ nsTextDimensions& aDimensions);
+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
+ nsTextDimensions& aDimensions, PRInt32* aFontID = nsnull);
+
+#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS)
+ NS_IMETHOD GetTextDimensions(const char* aString,
+ PRInt32 aLength,
+ PRInt32 aAvailWidth,
+ PRInt32* aBreaks,
+ PRInt32 aNumBreaks,
+ nsTextDimensions& aDimensions,
+ PRInt32& aNumCharsFit,
+ nsTextDimensions& aLastWordDimensions,
+ PRInt32* aFontID = nsnull);
+
+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
+ PRInt32 aLength,
+ PRInt32 aAvailWidth,
+ PRInt32* aBreaks,
+ PRInt32 aNumBreaks,
+ nsTextDimensions& aDimensions,
+ PRInt32& aNumCharsFit,
+ nsTextDimensions& aLastWordDimensions,
+ PRInt32* aFontID = nsnull);
+#endif
+#ifdef MOZ_MATHML
+ NS_IMETHOD GetBoundingMetrics(const char* aString,
+ PRUint32 aLength,
+ nsBoundingMetrics& aBoundingMetrics);
+ NS_IMETHOD GetBoundingMetrics(const PRUnichar* aString,
+ PRUint32 aLength,
+ nsBoundingMetrics& aBoundingMetrics,
+ PRInt32* aFontID = nsnull);
+#endif
+ NS_IMETHOD DrawString(const char *aString, PRUint32 aLength,
+ nscoord aX, nscoord aY,
+ const nscoord* aSpacing = nsnull);
+ NS_IMETHOD DrawString(const PRUnichar *aString, PRUint32 aLength,
+ nscoord aX, nscoord aY,
+ PRInt32 aFontID = -1,
+ const nscoord* aSpacing = nsnull);
+
NS_IMETHOD Init(nsIDeviceContext* aContext, gfxASurface* aThebesSurface);
NS_IMETHOD Init(nsIDeviceContext* aContext, gfxContext* aThebesContext);
NS_IMETHOD Init(nsIDeviceContext* aContext, nsIWidget *aWidget);
NS_IMETHOD CommonInit(void);
NS_IMETHOD GetDeviceContext(nsIDeviceContext *& aDeviceContext);
NS_IMETHOD PushState(void);
NS_IMETHOD PopState(void);
@@ -94,100 +161,29 @@ public:
NS_IMETHOD InvertRect(const nsRect& aRect);
NS_IMETHOD InvertRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
NS_IMETHOD FillPolygon(const nsPoint aPoints[], PRInt32 aNumPoints);
NS_IMETHOD DrawEllipse(const nsRect& aRect);
NS_IMETHOD DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
NS_IMETHOD FillEllipse(const nsRect& aRect);
NS_IMETHOD FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
- NS_IMETHOD GetWidth(const nsString& aString, nscoord &aWidth,
- PRInt32 *aFontID = nsnull)
- { return nsRenderingContextImpl::GetWidth(aString, aWidth, aFontID); }
- NS_IMETHOD GetWidth(const char* aString, nscoord& aWidth)
- { return nsRenderingContextImpl::GetWidth(aString, aWidth); }
- NS_IMETHOD GetWidth(const char* aString, PRUint32 aLength,
- nscoord& aWidth)
- { return nsRenderingContextImpl::GetWidth(aString, aLength, aWidth); }
- NS_IMETHOD GetWidth(const PRUnichar *aString, PRUint32 aLength,
- nscoord &aWidth, PRInt32 *aFontID = nsnull)
- { return nsRenderingContextImpl::GetWidth(aString, aLength, aWidth, aFontID); }
- NS_IMETHOD DrawString(const nsString& aString, nscoord aX, nscoord aY,
- PRInt32 aFontID = -1,
- const nscoord* aSpacing = nsnull)
- { return nsRenderingContextImpl::DrawString(aString, aX, aY, aFontID, aSpacing); }
-
- NS_IMETHOD GetWidth(char aC, nscoord &aWidth);
- NS_IMETHOD GetWidth(PRUnichar aC, nscoord &aWidth,
- PRInt32 *aFontID);
-
- NS_IMETHOD GetWidthInternal(const char *aString, PRUint32 aLength, nscoord &aWidth);
- NS_IMETHOD GetWidthInternal(const PRUnichar *aString, PRUint32 aLength, nscoord &aWidth,
- PRInt32 *aFontID);
-
- NS_IMETHOD DrawStringInternal(const char *aString, PRUint32 aLength,
- nscoord aX, nscoord aY,
- const nscoord* aSpacing);
- NS_IMETHOD DrawStringInternal(const PRUnichar *aString, PRUint32 aLength,
- nscoord aX, nscoord aY,
- PRInt32 aFontID,
- const nscoord* aSpacing);
-
- NS_IMETHOD GetTextDimensionsInternal(const char* aString, PRUint32 aLength,
- nsTextDimensions& aDimensions);
- NS_IMETHOD GetTextDimensionsInternal(const PRUnichar *aString, PRUint32 aLength,
- nsTextDimensions& aDimensions,PRInt32 *aFontID);
- NS_IMETHOD GetTextDimensionsInternal(const char* aString,
- PRInt32 aLength,
- PRInt32 aAvailWidth,
- PRInt32* aBreaks,
- PRInt32 aNumBreaks,
- nsTextDimensions& aDimensions,
- PRInt32& aNumCharsFit,
- nsTextDimensions& aLastWordDimensions,
- PRInt32* aFontID);
- NS_IMETHOD GetTextDimensionsInternal(const PRUnichar* aString,
- PRInt32 aLength,
- PRInt32 aAvailWidth,
- PRInt32* aBreaks,
- PRInt32 aNumBreaks,
- nsTextDimensions& aDimensions,
- PRInt32& aNumCharsFit,
- nsTextDimensions& aLastWordDimensions,
- PRInt32* aFontID);
-
-#ifdef MOZ_MATHML
- /**
- * Returns metrics (in app units) of an 8-bit character string
- */
- NS_IMETHOD GetBoundingMetricsInternal(const char* aString,
- PRUint32 aLength,
- nsBoundingMetrics& aBoundingMetrics);
-
- /**
- * Returns metrics (in app units) of a Unicode character string
- */
- NS_IMETHOD GetBoundingMetricsInternal(const PRUnichar* aString,
- PRUint32 aLength,
- nsBoundingMetrics& aBoundingMetrics,
- PRInt32* aFontID = nsnull);
-
-#endif /* MOZ_MATHML */
-
- virtual PRInt32 GetMaxStringLength();
-
NS_IMETHOD PushFilter(const nsRect& aRect, PRBool aAreaIsOpaque, float aOpacity);
NS_IMETHOD PopFilter();
virtual void* GetNativeGraphicData(GraphicDataType aType);
NS_IMETHOD PushTranslation(PushedTranslation* aState);
NS_IMETHOD PopTranslation(PushedTranslation* aState);
NS_IMETHOD SetTranslation(nscoord aX, nscoord aY);
+ /**
+ * Let the device context know whether we want text reordered with
+ * right-to-left base direction
+ */
NS_IMETHOD SetRightToLeftText(PRBool aIsRTL);
NS_IMETHOD GetRightToLeftText(PRBool* aIsRTL);
virtual void SetTextRunRTL(PRBool aIsRTL);
virtual PRInt32 GetPosition(const PRUnichar *aText,
PRUint32 aLength,
nsPoint aPt);
NS_IMETHOD GetRangeWidth(const PRUnichar *aText,
@@ -207,18 +203,74 @@ public:
gfxContext *ThebesContext() { return mThebes; }
nsTransform2D& CurrentTransform();
void TransformCoord (nscoord *aX, nscoord *aY);
protected:
+ nsresult GetWidthInternal(const char *aString, PRUint32 aLength, nscoord &aWidth);
+ nsresult GetWidthInternal(const PRUnichar *aString, PRUint32 aLength, nscoord &aWidth,
+ PRInt32 *aFontID = nsnull);
+
+ nsresult DrawStringInternal(const char *aString, PRUint32 aLength,
+ nscoord aX, nscoord aY,
+ const nscoord* aSpacing = nsnull);
+ nsresult DrawStringInternal(const PRUnichar *aString, PRUint32 aLength,
+ nscoord aX, nscoord aY,
+ PRInt32 aFontID = -1,
+ const nscoord* aSpacing = nsnull);
+
+ nsresult GetTextDimensionsInternal(const char* aString,
+ PRUint32 aLength,
+ nsTextDimensions& aDimensions);
+ nsresult GetTextDimensionsInternal(const PRUnichar* aString,
+ PRUint32 aLength,
+ nsTextDimensions& aDimensions,
+ PRInt32* aFontID = nsnull);
+ nsresult GetTextDimensionsInternal(const char* aString,
+ PRInt32 aLength,
+ PRInt32 aAvailWidth,
+ PRInt32* aBreaks,
+ PRInt32 aNumBreaks,
+ nsTextDimensions& aDimensions,
+ PRInt32& aNumCharsFit,
+ nsTextDimensions& aLastWordDimensions,
+ PRInt32* aFontID = nsnull);
+ nsresult GetTextDimensionsInternal(const PRUnichar* aString,
+ PRInt32 aLength,
+ PRInt32 aAvailWidth,
+ PRInt32* aBreaks,
+ PRInt32 aNumBreaks,
+ nsTextDimensions& aDimensions,
+ PRInt32& aNumCharsFit,
+ nsTextDimensions& aLastWordDimensions,
+ PRInt32* aFontID = nsnull);
+
+#ifdef MOZ_MATHML
+ /**
+ * Returns metrics (in app units) of an 8-bit character string
+ */
+ nsresult GetBoundingMetricsInternal(const char* aString,
+ PRUint32 aLength,
+ nsBoundingMetrics& aBoundingMetrics);
+
+ /**
+ * Returns metrics (in app units) of a Unicode character string
+ */
+ nsresult GetBoundingMetricsInternal(const PRUnichar* aString,
+ PRUint32 aLength,
+ nsBoundingMetrics& aBoundingMetrics,
+ PRInt32* aFontID = nsnull);
+
+#endif /* MOZ_MATHML */
+
nsCOMPtr<nsIDeviceContext> mDeviceContext;
- // cached pixels2twips, twips2pixels values
+ // cached app units per device pixel value
double mP2A;
nsCOMPtr<nsIWidget> mWidget;
// we need to manage our own clip region (since we can't get at
// the old one from cairo)
nsCOMPtr<nsIThebesFontMetrics> mFontMetrics;
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -644,28 +644,31 @@ ifdef HAVE_DTRACE
javascript-trace.h.in > javascript-trace.h
# We can't automatically generate dependencies on auto-generated headers;
# we have to list them explicitly.
$(addsuffix .$(OBJ_SUFFIX),jsdtracef jsinterp jsobj): $(CURDIR)/javascript-trace.h
endif
ifdef GNU_CC
+ifndef CROSS_COMPILE
+# If we don't have run-mozilla.sh *and* we're linking against NSPR, we don't
+# know how to run the JS binary. Oh well
+
imacro_asm.js: imacro_asm.js.in jsopcode.tbl
$(CC) -c -x c -E -P -I$(srcdir) $< > $@
-GARBAGE += imacros.c.out imacro_asm.js
-
-ifndef CROSS_COMPILE
-# Obsolete comment: if you replace update-imacros with libs, this would apply
-# but then parallel gmake would sometimes try to run $(DIST)/bin/js before it
-# had been built and installed. Want a fix for this, de-automating for now.
+GARBAGE += imacros.c.tmp imacro_asm.js
-# Build imacros.c.out after descending into DIRS and building the js shell.
-# This may result in an updated imacros.c.out file that requires a re-build
-# to stabilize.
-update-imacros:: imacros.c.out
- @cmp -s imacros.c.out $(srcdir)/$< || cp imacros.c.out $(srcdir)
+ifneq (,$(wildcard $(RUN_TEST_PROGRAM))$(if $(NSPR_LIBS),,1))
+libs:: imacro_asm.js $(srcdir)/imacros.jsasm
+ $(wildcard $(RUN_TEST_PROGRAM)) $(DIST)/bin/js$(BIN_SUFFIX) $< $(srcdir)/imacros.jsasm > imacros.c.tmp
+ @cmp -s imacros.c.tmp $(srcdir)/imacros.c.out || \
+ (echo "imacros.c.out is out of date. Run 'make update-imacros' to copy it to your source tree."; diff -U 4 $(srcdir)/imacros.c.out imacros.c.out; exit 1)
+ @echo "imacros.c.out is up to date"
-%.c.out: %.jsasm imacro_asm.js
- $(DIST)/bin/js imacro_asm.js $< > $@
+update-imacros: imacros.c.tmp
+ cp $< $(srcdir)/imacros.c.out
+
+.PHONY: update-imacros
endif
endif
+endif
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2501,62 +2501,80 @@ nsLayoutUtils::GetStringWidth(const nsIF
nscoord width;
aContext->GetWidth(aString, aLength, width);
return width;
}
/* static */ PRBool
nsLayoutUtils::GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult)
{
+ LinePosition position;
+ if (!GetFirstLinePosition(aFrame, &position))
+ return PR_FALSE;
+ *aResult = position.mBaseline;
+ return PR_TRUE;
+}
+
+/* static */ PRBool
+nsLayoutUtils::GetFirstLinePosition(const nsIFrame* aFrame,
+ LinePosition* aResult)
+{
const nsBlockFrame* block = nsLayoutUtils::GetAsBlock(const_cast<nsIFrame*>(aFrame));
if (!block) {
// For the first-line baseline we also have to check for a table, and if
// so, use the baseline of its first row.
nsIAtom* fType = aFrame->GetType();
if (fType == nsGkAtoms::tableOuterFrame) {
- *aResult = aFrame->GetBaseline();
+ aResult->mTop = 0;
+ aResult->mBaseline = aFrame->GetBaseline();
+ // This is what we want for the list bullet caller; not sure if
+ // other future callers will want the same.
+ aResult->mBottom = aFrame->GetSize().height;
return PR_TRUE;
}
// For first-line baselines, we have to consider scroll frames.
if (fType == nsGkAtoms::scrollFrame) {
nsIScrollableFrame *sFrame = do_QueryFrame(const_cast<nsIFrame*>(aFrame));
if (!sFrame) {
NS_NOTREACHED("not scroll frame");
}
- nscoord kidBaseline;
- if (GetFirstLineBaseline(sFrame->GetScrolledFrame(), &kidBaseline)) {
+ LinePosition kidPosition;
+ if (GetFirstLinePosition(sFrame->GetScrolledFrame(), &kidPosition)) {
// Consider only the border and padding that contributes to the
// kid's position, not the scrolling, so we get the initial
// position.
- *aResult = kidBaseline + aFrame->GetUsedBorderAndPadding().top;
+ *aResult = kidPosition + aFrame->GetUsedBorderAndPadding().top;
return PR_TRUE;
}
return PR_FALSE;
}
// No baseline.
return PR_FALSE;
}
for (nsBlockFrame::const_line_iterator line = block->begin_lines(),
line_end = block->end_lines();
line != line_end; ++line) {
if (line->IsBlock()) {
nsIFrame *kid = line->mFirstChild;
- nscoord kidBaseline;
- if (GetFirstLineBaseline(kid, &kidBaseline)) {
- *aResult = kidBaseline + kid->GetPosition().y;
+ LinePosition kidPosition;
+ if (GetFirstLinePosition(kid, &kidPosition)) {
+ *aResult = kidPosition + kid->GetPosition().y;
return PR_TRUE;
}
} else {
// XXX Is this the right test? We have some bogus empty lines
// floating around, but IsEmpty is perhaps too weak.
if (line->GetHeight() != 0 || !line->IsEmpty()) {
- *aResult = line->mBounds.y + line->GetAscent();
+ nscoord top = line->mBounds.y;
+ aResult->mTop = top;
+ aResult->mBaseline = top + line->GetAscent();
+ aResult->mBottom = top + line->GetHeight();
return PR_TRUE;
}
}
}
return PR_FALSE;
}
/* static */ PRBool
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -771,16 +771,38 @@ public:
* 'overflow' not 'visible', potentially including aFrame itself).
*
* Returns true if a baseline was found (and fills in aResult).
* Otherwise returns false.
*/
static PRBool GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult);
/**
+ * Just like GetFirstLineBaseline, except also returns the top and
+ * bottom of the line with the baseline.
+ *
+ * Returns true if a line was found (and fills in aResult).
+ * Otherwise returns false.
+ */
+ struct LinePosition {
+ nscoord mTop, mBaseline, mBottom;
+
+ LinePosition operator+(nscoord aOffset) const {
+ LinePosition result;
+ result.mTop = mTop + aOffset;
+ result.mBaseline = mBaseline + aOffset;
+ result.mBottom = mBottom + aOffset;
+ return result;
+ }
+ };
+ static PRBool GetFirstLinePosition(const nsIFrame* aFrame,
+ LinePosition* aResult);
+
+
+ /**
* Derive a baseline of |aFrame| (measured from its top border edge)
* from its last in-flow line box (not descending into anything with
* 'overflow' not 'visible', potentially including aFrame itself).
*
* Returns true if a baseline was found (and fills in aResult).
* Otherwise returns false.
*/
static PRBool GetLastLineBaseline(const nsIFrame* aFrame, nscoord* aResult);
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -5098,18 +5098,16 @@ PresShell::RenderDocument(const nsRect&
// we want the window to be composited as a single image using
// whatever operator was set; set OPERATOR_OVER here, which is
// either already the case, or overrides the operator in a group.
// the original operator will be present when we PopGroup.
aThebesContext->SetOperator(gfxContext::OPERATOR_OVER);
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
if (rootFrame) {
- nsAutoDisableGetUsedXAssertions disableAssert;
-
nsDisplayListBuilder builder(rootFrame, PR_FALSE,
(aFlags & RENDER_CARET) != 0);
nsDisplayList list;
nsRect rect(aRect);
nsIFrame* rootScrollFrame = GetRootScrollFrame();
if ((aFlags & RENDER_IGNORE_VIEWPORT_SCROLLING) && rootScrollFrame) {
nsPoint pos = GetRootScrollFrameAsScrollable()->GetScrollPosition();
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -38,17 +38,16 @@
#include "nsLayoutStatics.h"
#include "nsContentCID.h"
#include "nsContentDLF.h"
#include "nsContentPolicyUtils.h"
#include "nsDataDocumentContentPolicy.h"
#include "nsNoDataProtocolContentPolicy.h"
#include "nsDOMCID.h"
-#include "nsCSSOMFactory.h"
#include "nsInspectorCSSUtils.h"
#include "nsHTMLContentSerializer.h"
#include "nsHTMLParts.h"
#include "nsGenericHTMLElement.h"
#include "nsICSSLoader.h"
#include "nsICSSParser.h"
#include "nsICSSStyleSheet.h"
#include "nsICategoryManager.h"
@@ -517,17 +516,16 @@ MAKE_CTOR(CreateXULDocument,
// NS_NewXULPrototypeCache
MAKE_CTOR(CreateXULPopupManager, nsISupports, NS_NewXULPopupManager)
#endif
#ifdef MOZ_XTF
MAKE_CTOR(CreateXTFService, nsIXTFService, NS_NewXTFService)
MAKE_CTOR(CreateXMLContentBuilder, nsIXMLContentBuilder, NS_NewXMLContentBuilder)
#endif
MAKE_CTOR(CreateContentDLF, nsIDocumentLoaderFactory, NS_NewContentDocumentLoaderFactory)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsCSSOMFactory)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsInspectorCSSUtils)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWyciwygProtocolHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsContentAreaDragDrop)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDataDocumentContentPolicy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsNoDataProtocolContentPolicy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSyncLoadService)
MAKE_CTOR(CreatePluginDocument, nsIDocument, NS_NewPluginDocument)
#ifdef MOZ_MEDIA
@@ -990,21 +988,16 @@ static const nsModuleComponentInfo gComp
"@mozilla.org/content/pre-content-iterator;1",
CreatePreContentIterator },
{ "Subtree iterator",
NS_SUBTREEITERATOR_CID,
"@mozilla.org/content/subtree-content-iterator;1",
CreateSubtreeIterator },
- { "CSS Object Model Factory",
- NS_CSSOMFACTORY_CID,
- nsnull,
- nsCSSOMFactoryConstructor },
-
{ "Inspector CSS Utils",
NS_INSPECTORCSSUTILS_CID,
nsnull,
nsInspectorCSSUtilsConstructor },
// Needed to support "new Option;" and "new Image;" in JavaScript
{ "HTML img element",
NS_HTMLIMAGEELEMENT_CID,
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -54,17 +54,16 @@
#include "nsCSSRendering.h"
#include "nsCSSScanner.h"
#include "nsICSSStyleSheet.h"
#include "nsDOMAttribute.h"
#include "nsDOMClassInfo.h"
#include "nsEventListenerManager.h"
#include "nsFrame.h"
#include "nsGenericElement.h" // for nsDOMEventRTTearoff
-#include "nsStyledElement.h"
#include "nsGlobalWindow.h"
#include "nsGkAtoms.h"
#include "nsImageFrame.h"
#include "nsLayoutStylesheetCache.h"
#include "nsNodeInfo.h"
#include "nsRange.h"
#include "nsRepeatService.h"
#include "nsFloatManager.h"
@@ -316,17 +315,16 @@ nsLayoutStatics::Shutdown()
nsCSSFrameConstructor::ReleaseGlobals();
nsFloatManager::Shutdown();
nsImageFrame::ReleaseGlobals();
nsCSSScanner::ReleaseGlobals();
NS_IF_RELEASE(nsRuleNode::gLangService);
- nsStyledElement::Shutdown();
nsTextFragment::Shutdown();
nsAttrValue::Shutdown();
nsContentUtils::Shutdown();
nsNodeInfo::ClearCache();
nsLayoutStylesheetCache::Shutdown();
NS_NameSpaceManagerShutdown();
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1070,32 +1070,32 @@ nsBlockFrame::Reflow(nsPresContext*
// the second case can happen.
if (mBullet && HaveOutsideBullet() && !mLines.empty() &&
(mLines.front()->IsBlock() ||
(0 == mLines.front()->mBounds.height &&
mLines.front() != mLines.back() &&
mLines.begin().next()->IsBlock()))) {
// Reflow the bullet
nsHTMLReflowMetrics metrics;
- // FIXME: aReflowState.mComputedBorderPadding.top isn't even the
- // right place -- we really want the top of the line whose baseline
- // we're using (or, actually, the entire line, once we fix bug
- // 25888)
- ReflowBullet(state, metrics, aReflowState.mComputedBorderPadding.top);
-
- nscoord baseline;
- if (nsLayoutUtils::GetFirstLineBaseline(this, &baseline)) {
+ // XXX Use the entire line when we fix bug 25888.
+ nsLayoutUtils::LinePosition position;
+ PRBool havePosition = nsLayoutUtils::GetFirstLinePosition(this, &position);
+ nscoord lineTop = havePosition ? position.mTop
+ : aReflowState.mComputedBorderPadding.top;
+ ReflowBullet(state, metrics, lineTop);
+
+ if (havePosition) {
// We have some lines to align the bullet with.
// Doing the alignment using the baseline will also cater for
// bullets that are placed next to a child block (bug 92896)
// Tall bullets won't look particularly nice here...
nsRect bbox = mBullet->GetRect();
- bbox.y = baseline - metrics.ascent;
+ bbox.y = position.mBaseline - metrics.ascent;
mBullet->SetRect(bbox);
}
// Otherwise just leave the bullet where it is, up against our top padding.
}
// Compute our final size
nscoord bottomEdgeOfChildren;
ComputeFinalSize(aReflowState, state, aMetrics, &bottomEdgeOfChildren);
@@ -1652,29 +1652,29 @@ nsBlockFrame::PropagateFloatDamage(nsBlo
// Unconditionally reflow sliding blocks; we only really need to reflow
// if there's a float impacting this block, but the current float manager
// makes it difficult to check that. Therefore, we let the child block
// decide what it needs to reflow.
aLine->MarkDirty();
} else {
// Note that this check will become incorrect once bug 25888 is fixed
// because we are only checking the top of the line
- aState.GetAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE);
PRBool wasImpactedByFloat = aLine->IsImpactedByFloat();
- PRBool isImpactedByFloat = aState.IsImpactedByFloat();
+ nsFlowAreaRect floatAvailableSpace =
+ aState.GetFloatAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropagateFloatDamage %p was = %d, is=%d\n",
- this, wasImpactedByFloat, isImpactedByFloat);
+ this, wasImpactedByFloat, floatAvailableSpace.mHasFloats);
#endif
// Mark the line dirty if it was or is affected by a float
// We actually only really need to reflow if the amount of impact
// changes, but that's not straightforward to check
- if (wasImpactedByFloat || isImpactedByFloat) {
+ if (wasImpactedByFloat || floatAvailableSpace.mHasFloats) {
aLine->MarkDirty();
}
}
}
}
static void PlaceFrameView(nsIFrame* aFrame);
@@ -2946,25 +2946,25 @@ nsBlockFrame::ReflowBlockFrame(nsBlockRe
} else {
// Advance aState.mY to the top border-edge of the frame.
aState.mY += topMargin;
}
}
// Here aState.mY is the top border-edge of the block.
// Compute the available space for the block
- aState.GetAvailableSpace();
+ nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace();
#ifdef REALLY_NOISY_REFLOW
- printf("setting line %p isImpacted to %s\n", aLine.get(), aState.IsImpactedByFloat()?"true":"false");
+ printf("setting line %p isImpacted to %s\n",
+ aLine.get(), floatAvailableSpace.mHasFloats?"true":"false");
#endif
- PRBool isImpacted = aState.IsImpactedByFloat() ? PR_TRUE : PR_FALSE;
- aLine->SetLineIsImpactedByFloat(isImpacted);
+ aLine->SetLineIsImpactedByFloat(floatAvailableSpace.mHasFloats);
nsRect availSpace;
- aState.ComputeBlockAvailSpace(frame, display, replacedBlock != nsnull,
- availSpace);
+ aState.ComputeBlockAvailSpace(frame, display, floatAvailableSpace,
+ replacedBlock != nsnull, availSpace);
// Now put the Y coordinate back to the top of the top-margin +
// clearance, and flow the block.
aState.mY -= topMargin;
availSpace.y -= topMargin;
if (NS_UNCONSTRAINEDSIZE != availSpace.height) {
availSpace.height += topMargin;
}
@@ -3034,17 +3034,17 @@ nsBlockFrame::ReflowBlockFrame(nsBlockRe
// Try to place the child block.
// Don't force the block to fit if we have positive clearance, because
// pushing it to the next page would give it more room.
// Don't force the block to fit if it's impacted by a float. If it is,
// then pushing it to the next page would give it more room. Note that
// isImpacted doesn't include impact from the block's own floats.
PRBool forceFit = aState.IsAdjacentWithTop() && clearance <= 0 &&
- !isImpacted;
+ !floatAvailableSpace.mHasFloats;
nsCollapsingMargin collapsedBottomMargin;
nsRect combinedArea(0,0,0,0);
*aKeepReflowGoing = brc.PlaceBlock(blockHtmlRS, forceFit, aLine.get(),
collapsedBottomMargin,
aLine->mBounds, combinedArea, frameReflowStatus);
if (aLine->SetCarriedOutBottomMargin(collapsedBottomMargin)) {
line_iterator nextLine = aLine;
++nextLine;
@@ -3342,43 +3342,42 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
aLine->FreeFloats(aState.mFloatCacheFreeList);
aState.mFloatCombinedArea.SetRect(0, 0, 0, 0);
// Setup initial coordinate system for reflowing the inline frames
// into. Apply a previous block frame's bottom margin first.
if (ShouldApplyTopMargin(aState, aLine)) {
aState.mY += aState.mPrevBottomMargin.get();
}
- aState.GetAvailableSpace();
- PRBool impactedByFloats = aState.IsImpactedByFloat() ? PR_TRUE : PR_FALSE;
- aLine->SetLineIsImpactedByFloat(impactedByFloats);
+ nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace();
+ aLine->SetLineIsImpactedByFloat(floatAvailableSpace.mHasFloats);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
- this, impactedByFloats);
+ this, floatAvailableSpace.mHasFloats);
#endif
const nsMargin& borderPadding = aState.BorderPadding();
- nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
- nscoord availWidth = aState.mAvailSpaceRect.width;
+ nscoord x = floatAvailableSpace.mRect.x + borderPadding.left;
+ nscoord availWidth = floatAvailableSpace.mRect.width;
nscoord availHeight;
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
availHeight = NS_UNCONSTRAINEDSIZE;
}
else {
/* XXX get the height right! */
- availHeight = aState.mAvailSpaceRect.height;
+ availHeight = floatAvailableSpace.mRect.height;
}
// Make sure to enable resize optimization before we call BeginLineReflow
// because it might get disabled there
aLine->EnableResizeReflowOptimization();
aLineLayout.BeginLineReflow(x, aState.mY,
availWidth, availHeight,
- impactedByFloats,
+ floatAvailableSpace.mHasFloats,
PR_FALSE /*XXX isTopOfPage*/);
aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, PR_FALSE);
// XXX Unfortunately we need to know this before reflowing the first
// inline frame in the line. FIX ME.
if ((0 == aLineLayout.GetLineNumber()) &&
(NS_BLOCK_HAS_FIRST_LETTER_CHILD & mState) &&
@@ -3391,17 +3390,17 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
LineReflowStatus lineReflowStatus = LINE_REFLOW_OK;
PRInt32 i;
nsIFrame* frame = aLine->mFirstChild;
// Determine whether this is a line of placeholders for out-of-flow
// continuations
PRBool isContinuingPlaceholders = PR_FALSE;
- if (impactedByFloats) {
+ if (floatAvailableSpace.mHasFloats) {
// There is a soft break opportunity at the start of the line, because
// we can always move this line down below float(s).
if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0, PR_TRUE, eNormalBreak)) {
lineReflowStatus = LINE_REFLOW_REDO_NEXT_BAND;
}
}
// need to repeatedly call GetChildCount here, because the child
@@ -3496,24 +3495,24 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
if (LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
// This happens only when we have a line that is impacted by
// floats and the first element in the line doesn't fit with
// the floats.
//
// What we do is to advance past the first float we find and
// then reflow the line all over again.
- NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aState.mAvailSpaceRect.height,
+ NS_ASSERTION(NS_UNCONSTRAINEDSIZE != floatAvailableSpace.mRect.height,
"unconstrained height on totally empty line");
// See the analogous code for blocks in nsBlockReflowState::ClearFloats.
- if (aState.mAvailSpaceRect.height > 0) {
- NS_ASSERTION(aState.IsImpactedByFloat(),
+ if (floatAvailableSpace.mRect.height > 0) {
+ NS_ASSERTION(floatAvailableSpace.mHasFloats,
"redo line on totally empty line with non-empty band...");
- aState.mY += aState.mAvailSpaceRect.height;
+ aState.mY += floatAvailableSpace.mRect.height;
} else {
NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight,
"We shouldn't be running out of height here");
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableHeight) {
// just move it down a bit to try to get out of this mess
aState.mY += 1;
} else {
// There's nowhere to retry placing the line. Just treat it as if
@@ -5641,34 +5640,35 @@ nsBlockFrame::DeleteNextInFlowChild(nsPr
aDeletingEmptyFrames ? FRAMES_ARE_EMPTY : 0);
}
}
////////////////////////////////////////////////////////////////////////
// Float support
nsRect
-nsBlockFrame::ComputeFloatAvailableSpace(nsBlockReflowState& aState,
- nsIFrame* aFloatFrame)
+nsBlockFrame::AdjustFloatAvailableSpace(nsBlockReflowState& aState,
+ const nsRect& aFloatAvailableSpace,
+ nsIFrame* aFloatFrame)
{
// Compute the available width. By default, assume the width of the
// containing block.
nscoord availWidth;
const nsStyleDisplay* floatDisplay = aFloatFrame->GetStyleDisplay();
if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
eCompatibility_NavQuirks != aState.mPresContext->CompatibilityMode() ) {
availWidth = aState.mContentArea.width;
}
else {
// This quirk matches the one in nsBlockReflowState::FlowAndPlaceFloat
// give tables only the available space
// if they can shrink we may not be constrained to place
// them in the next line
- availWidth = aState.mAvailSpaceRect.width;
+ availWidth = aFloatAvailableSpace.width;
// round down to twips per pixel so that we fit
// needed when prev. float has procentage width
// (maybe is a table flaw that makes table chose to round up
// but I don't want to change that, too risky)
nscoord twp = nsPresContext::CSSPixelsToAppUnits(1);
availWidth -= availWidth % twp;
}
@@ -5691,49 +5691,53 @@ nsBlockFrame::ComputeFloatAvailableSpace
return nsRect(aState.BorderPadding().left,
aState.BorderPadding().top,
availWidth, availHeight);
}
nscoord
nsBlockFrame::ComputeFloatWidth(nsBlockReflowState& aState,
+ const nsRect& aFloatAvailableSpace,
nsPlaceholderFrame* aPlaceholder)
{
// Reflow the float.
nsIFrame* floatFrame = aPlaceholder->GetOutOfFlowFrame();
- nsRect availSpace = ComputeFloatAvailableSpace(aState, floatFrame);
+ nsRect availSpace = AdjustFloatAvailableSpace(aState, aFloatAvailableSpace,
+ floatFrame);
nsHTMLReflowState floatRS(aState.mPresContext, aState.mReflowState,
floatFrame,
nsSize(availSpace.width, availSpace.height));
return floatRS.ComputedWidth() + floatRS.mComputedBorderPadding.LeftRight() +
floatRS.mComputedMargin.LeftRight();
}
nsresult
nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
+ const nsRect& aFloatAvailableSpace,
nsPlaceholderFrame* aPlaceholder,
nsMargin& aFloatMargin,
nsReflowStatus& aReflowStatus)
{
// Reflow the float.
nsIFrame* floatFrame = aPlaceholder->GetOutOfFlowFrame();
aReflowStatus = NS_FRAME_COMPLETE;
#ifdef NOISY_FLOAT
printf("Reflow Float %p in parent %p, availSpace(%d,%d,%d,%d)\n",
aPlaceholder->GetOutOfFlowFrame(), this,
- aState.mAvailSpaceRect.x, aState.mAvailSpaceRect.y,
- aState.mAvailSpaceRect.width, aState.mAvailSpaceRect.height
+ aFloatAvailableSpace.x, aFloatAvailableSpace.y,
+ aFloatAvailableSpace.width, aFloatAvailableSpace.height
);
#endif
- nsRect availSpace = ComputeFloatAvailableSpace(aState, floatFrame);
+ nsRect availSpace = AdjustFloatAvailableSpace(aState, aFloatAvailableSpace,
+ floatFrame);
nsHTMLReflowState floatRS(aState.mPresContext, aState.mReflowState,
floatFrame,
nsSize(availSpace.width, availSpace.height));
// Setup a block reflow state to reflow the float.
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState);
@@ -6645,32 +6649,53 @@ nsBlockFrame::ReflowBullet(nsBlockReflow
// XXXwaterson Should this look just like the logic in
// nsBlockReflowContext::ReflowBlock and nsLineLayout::ReflowFrame?
nsHTMLReflowState reflowState(aState.mPresContext, rs,
mBullet, availSize);
nsReflowStatus status;
mBullet->WillReflow(aState.mPresContext);
mBullet->Reflow(aState.mPresContext, aMetrics, reflowState, status);
- // Place the bullet now, separate it from mOutsideBulletX by its margin.
- // If the mAvailSpaceRect position is outside the mOutsideBulletX
- // position it means the line didn't care about the float edge and we
- // use that position instead (there cannot be any floats at the start
- // of the line this case since that would violate CSS 2.1 float rules).
- // XXX we need to take floats inside the principal block that clears
- // outside floats into account also (bug 428810).
- nscoord x = rs.mStyleVisibility->mDirection == NS_STYLE_DIRECTION_LTR ?
- PR_MIN(aState.mOutsideBulletX, aState.mAvailSpaceRect.x)
- - reflowState.mComputedMargin.right - aMetrics.width :
- PR_MAX(aState.mOutsideBulletX, aState.mAvailSpaceRect.XMost())
- + reflowState.mComputedMargin.left;
-
- // FIXME: come up with rules for when mAvailSpaceRect is valid so we
- // don't need to do this.
- aState.GetAvailableSpace();
+ // Get the float available space using our saved state from before we
+ // started reflowing the block, so that we ignore any floats inside
+ // the block.
+ // FIXME: aLineTop isn't actually set correctly by some callers, since
+ // they reposition the line.
+ nsRect floatAvailSpace =
+ aState.GetFloatAvailableSpaceWithState(aLineTop, PR_FALSE,
+ &aState.mFloatManagerStateBefore)
+ .mRect;
+ // FIXME (bug 25888): need to check the entire region that the first
+ // line overlaps, not just the top pixel.
+
+ // Place the bullet now. We want to place the bullet relative to the
+ // border-box of the associated block (using the right/left margin of
+ // the bullet frame as separation). However, if a line box would be
+ // displaced by floats that are *outside* the associated block, we
+ // want to displace it by the same amount. That is, we act as though
+ // the edge of the floats is the content-edge of the block, and place
+ // the bullet at a position offset from there by the block's padding,
+ // the block's border, and the bullet frame's margin.
+ nscoord x;
+ if (rs.mStyleVisibility->mDirection == NS_STYLE_DIRECTION_LTR) {
+ // Note: floatAvailSpace.x is relative to the content box and never
+ // less than zero. Converting to frame coordinates and subtracting
+ // the padding and border cancel each other out, and the PR_MAX()
+ // with 0 (or with the left border+padding) is even implied in the
+ // right place.
+ x = floatAvailSpace.x - reflowState.mComputedMargin.right - aMetrics.width;
+ } else {
+ // The XMost() of the available space and the computed width both
+ // give us offsets from the left content edge. Then we add the left
+ // border/padding to get into frame coordinates, and the right
+ // border/padding and the bullet's margin to offset the position.
+ x = PR_MIN(rs.ComputedWidth(), floatAvailSpace.XMost())
+ + rs.mComputedBorderPadding.LeftRight()
+ + reflowState.mComputedMargin.left;
+ }
// Approximate the bullets position; vertical alignment will provide
// the final vertical location.
const nsMargin& bp = aState.BorderPadding();
nscoord y = bp.top;
mBullet->SetRect(nsRect(x, y, aMetrics.width, aMetrics.height));
mBullet->DidReflow(aState.mPresContext, &aState.mReflowState, NS_FRAME_REFLOW_FINISHED);
}
@@ -6819,16 +6844,17 @@ nsBlockFrame::BlockCanIntersectFloats(ns
// Note that this width can vary based on the vertical position.
// However, the cases where it varies are the cases where the width fits
// in the available space given, which means that variation shouldn't
// matter.
/* static */
nsBlockFrame::ReplacedElementWidthToClear
nsBlockFrame::WidthToClearPastFloats(nsBlockReflowState& aState,
+ const nsRect& aFloatAvailableSpace,
nsIFrame* aFrame)
{
nscoord leftOffset, rightOffset;
nsCSSOffsetState offsetState(aFrame, aState.mReflowState.rendContext,
aState.mContentArea.width);
ReplacedElementWidthToClear result;
// A table outer frame is an exception in that it is a block child
@@ -6872,17 +6898,18 @@ nsBlockFrame::WidthToClearPastFloats(nsB
result.marginLeft = captionMargin.left;
result.marginRight = tableMargin.right;
} else {
result.marginLeft = tableMargin.left;
result.marginRight = captionMargin.right;
}
}
- aState.ComputeReplacedBlockOffsetsForFloats(aFrame, leftOffset, rightOffset,
+ aState.ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace,
+ leftOffset, rightOffset,
&result);
// result.marginLeft has already been subtracted from leftOffset (etc.)
nscoord availWidth = aState.mContentArea.width - leftOffset - rightOffset;
// Force the outer frame to shrink-wrap (otherwise it just sizes to
// the available width unconditionally).
result.borderBoxWidth =
aFrame->ComputeSize(aState.mReflowState.rendContext,
@@ -6896,17 +6923,18 @@ nsBlockFrame::WidthToClearPastFloats(nsB
offsetState.mComputedBorderPadding.TopBottom() -
offsetState.mComputedPadding.TopBottom()),
nsSize(offsetState.mComputedPadding.LeftRight(),
offsetState.mComputedPadding.TopBottom()),
PR_TRUE).width +
offsetState.mComputedBorderPadding.LeftRight() -
(result.marginLeft + result.marginRight);
} else {
- aState.ComputeReplacedBlockOffsetsForFloats(aFrame, leftOffset, rightOffset);
+ aState.ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace,
+ leftOffset, rightOffset);
nscoord availWidth = aState.mContentArea.width - leftOffset - rightOffset;
// We actually don't want the min width here; see bug 427782; we only
// want to displace if the width won't compute to a value small enough
// to fit.
// All we really need here is the result of ComputeSize, and we
// could *almost* get that from an nsCSSOffsetState, except for the
// last argument.
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -299,17 +299,19 @@ public:
* care about (which need not be its current mY)
*/
struct ReplacedElementWidthToClear {
nscoord marginLeft, borderBoxWidth, marginRight;
nscoord MarginBoxWidth() const
{ return marginLeft + borderBoxWidth + marginRight; }
};
static ReplacedElementWidthToClear
- WidthToClearPastFloats(nsBlockReflowState& aState, nsIFrame* aFrame);
+ WidthToClearPastFloats(nsBlockReflowState& aState,
+ const nsRect& aFloatAvailableSpace,
+ nsIFrame* aFrame);
/**
* Walks up the frame tree, starting with aCandidate, and returns the first
* block frame that it encounters.
*/
static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate);
protected:
@@ -524,24 +526,27 @@ protected:
nsresult ReflowInlineFrame(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
line_iterator aLine,
nsIFrame* aFrame,
LineReflowStatus* aLineReflowStatus);
// Compute the available width for a float.
- nsRect ComputeFloatAvailableSpace(nsBlockReflowState& aState,
- nsIFrame* aFloatFrame);
+ nsRect AdjustFloatAvailableSpace(nsBlockReflowState& aState,
+ const nsRect& aFloatAvailableSpace,
+ nsIFrame* aFloatFrame);
// Computes the border-box width of the float
nscoord ComputeFloatWidth(nsBlockReflowState& aState,
+ const nsRect& aFloatAvailableSpace,
nsPlaceholderFrame* aPlaceholder);
// An incomplete aReflowStatus indicates the float should be split
// but only if the available height is constrained.
nsresult ReflowFloat(nsBlockReflowState& aState,
+ const nsRect& aFloatAvailableSpace,
nsPlaceholderFrame* aPlaceholder,
nsMargin& aFloatMargin,
nsReflowStatus& aReflowStatus);
//----------------------------------------
// Methods for pushing/pulling lines/frames
virtual nsresult CreateContinuationFor(nsBlockReflowState& aState,
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -97,16 +97,17 @@ nsBlockReflowState::nsBlockReflowState(c
NS_ASSERTION(mFloatManager,
"FloatManager should be set in nsBlockReflowState" );
if (mFloatManager) {
// Translate into our content area and then save the
// coordinate system origin for later.
mFloatManager->Translate(borderPadding.left, borderPadding.top);
mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY);
+ mFloatManager->PushState(&mFloatManagerStateBefore); // never popped
}
mReflowStatus = NS_FRAME_COMPLETE;
mPresContext = aPresContext;
mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow());
NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedWidth(),
@@ -134,26 +135,16 @@ nsBlockReflowState::nsBlockReflowState(c
}
mY = borderPadding.top;
mPrevChild = nsnull;
mCurrentLine = aFrame->end_lines();
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(aReflowState.frame);
-
- // Calculate mOutsideBulletX
- GetAvailableSpace();
- // FIXME (bug 25888): need to check the entire region that the first
- // line overlaps, not just the top pixel.
- mOutsideBulletX =
- mReflowState.mStyleVisibility->mDirection == NS_STYLE_DIRECTION_LTR ?
- mAvailSpaceRect.x :
- PR_MIN(mReflowState.ComputedWidth(), mAvailSpaceRect.XMost()) +
- mReflowState.mComputedBorderPadding.LeftRight();
}
void
nsBlockReflowState::SetupOverflowPlaceholdersProperty()
{
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE ||
!mOverflowPlaceholders.IsEmpty()) {
mBlock->SetProperty(nsGkAtoms::overflowPlaceholdersProperty,
@@ -193,75 +184,79 @@ nsBlockReflowState::FreeLineBox(nsLineBo
{
if (aLine) {
aLine->Destroy(mPresContext->PresShell());
}
}
void
nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
+ const nsRect& aFloatAvailableSpace,
nscoord& aLeftResult,
nscoord& aRightResult,
nsBlockFrame::
ReplacedElementWidthToClear
*aReplacedWidth)
{
// The frame is clueless about the float manager and therefore we
// only give it free space. An example is a table frame - the
// tables do not flow around floats.
// However, we can let its margins intersect floats.
- NS_ASSERTION(mAvailSpaceRect.x >= 0, "bad avail space rect x");
- NS_ASSERTION(mAvailSpaceRect.width == 0 ||
- mAvailSpaceRect.XMost() <= mContentArea.width,
+ NS_ASSERTION(aFloatAvailableSpace.x >= 0, "bad avail space rect x");
+ NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
+ aFloatAvailableSpace.XMost() <= mContentArea.width,
"bad avail space rect width");
nscoord leftOffset, rightOffset;
- if (mAvailSpaceRect.width == mContentArea.width) {
+ if (aFloatAvailableSpace.width == mContentArea.width) {
// We don't need to compute margins when there are no floats around.
leftOffset = 0;
rightOffset = 0;
} else {
// We pass in aReplacedWidth to make handling outer table frames
// work correctly. For outer table frames, we need to subtract off
// the margin that's going to be at the edge of them, since we're
// dealing with margin that it's really the child's responsibility
// to place.
nsCSSOffsetState os(aFrame, mReflowState.rendContext, mContentArea.width);
NS_ASSERTION(!aReplacedWidth ||
aFrame->GetType() == nsGkAtoms::tableOuterFrame ||
(aReplacedWidth->marginLeft == os.mComputedMargin.left &&
aReplacedWidth->marginRight == os.mComputedMargin.right),
"unexpected aReplacedWidth");
- nscoord leftFloatXOffset = mAvailSpaceRect.x;
+ nscoord leftFloatXOffset = aFloatAvailableSpace.x;
leftOffset = PR_MAX(leftFloatXOffset, os.mComputedMargin.left) -
(aReplacedWidth ? aReplacedWidth->marginLeft
: os.mComputedMargin.left);
leftOffset = PR_MAX(leftOffset, 0); // in case of negative margin
- nscoord rightFloatXOffset = mContentArea.width - mAvailSpaceRect.XMost();
+ nscoord rightFloatXOffset =
+ mContentArea.width - aFloatAvailableSpace.XMost();
rightOffset = PR_MAX(rightFloatXOffset, os.mComputedMargin.right) -
(aReplacedWidth ? aReplacedWidth->marginRight
: os.mComputedMargin.right);
rightOffset = PR_MAX(rightOffset, 0); // in case of negative margin
}
aLeftResult = leftOffset;
aRightResult = rightOffset;
}
// Compute the amount of available space for reflowing a block frame
// at the current Y coordinate. This method assumes that
// GetAvailableSpace has already been called.
void
nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsStyleDisplay* aDisplay,
+ const nsFlowAreaRect& aFloatAvailableSpace,
PRBool aBlockAvoidsFloats,
nsRect& aResult)
{
#ifdef REALLY_NOISY_REFLOW
- printf("CBAS frame=%p has floats %d\n", aFrame, mBandHasFloats);
+ printf("CBAS frame=%p has floats %d\n",
+ aFrame, aFloatAvailableSpace.mHasFloats);
#endif
aResult.y = mY;
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
? NS_UNCONSTRAINEDSIZE
: PR_MAX(0, mReflowState.availableHeight - mY);
// mY might be greater than mBottomEdge if the block's top margin pushes
// it off the page/column. Negative available height can confuse other code
// and is nonsense in principle.
@@ -279,34 +274,34 @@ nsBlockReflowState::ComputeBlockAvailSpa
// true but nsBlockFrame::BlockCanIntersectFloats is false,
// nsBlockFrame::WidthToClearPastFloats would need to use the
// shrink-wrap formula, max(MIN_WIDTH, min(avail width, PREF_WIDTH))
// rather than just using MIN_WIDTH.
NS_ASSERTION(nsBlockFrame::BlockCanIntersectFloats(aFrame) ==
!aBlockAvoidsFloats,
"unexpected replaced width");
if (!aBlockAvoidsFloats) {
- if (mBandHasFloats) {
+ if (aFloatAvailableSpace.mHasFloats) {
// Use the float-edge property to determine how the child block
// will interact with the float.
const nsStyleBorder* borderStyle = aFrame->GetStyleBorder();
switch (borderStyle->mFloatEdge) {
default:
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floats
// The child block will flow around the float. Therefore
// give it all of the available space.
aResult.x = borderPadding.left;
aResult.width = mContentArea.width;
break;
case NS_STYLE_FLOAT_EDGE_MARGIN:
{
// The child block's margins should be placed adjacent to,
// but not overlap the float.
- aResult.x = mAvailSpaceRect.x + borderPadding.left;
- aResult.width = mAvailSpaceRect.width;
+ aResult.x = aFloatAvailableSpace.mRect.x + borderPadding.left;
+ aResult.width = aFloatAvailableSpace.mRect.width;
}
break;
}
}
else {
// Since there are no floats present the float-edge property
// doesn't matter therefore give the block element all of the
// available space since it will flow around the float itself.
@@ -314,63 +309,65 @@ nsBlockReflowState::ComputeBlockAvailSpa
aResult.width = mContentArea.width;
}
}
else {
nsBlockFrame::ReplacedElementWidthToClear replacedWidthStruct;
nsBlockFrame::ReplacedElementWidthToClear *replacedWidth = nsnull;
if (aFrame->GetType() == nsGkAtoms::tableOuterFrame) {
replacedWidth = &replacedWidthStruct;
- replacedWidthStruct = nsBlockFrame::WidthToClearPastFloats(*this, aFrame);
+ replacedWidthStruct =
+ nsBlockFrame::WidthToClearPastFloats(*this, aFloatAvailableSpace.mRect,
+ aFrame);
}
nscoord leftOffset, rightOffset;
- ComputeReplacedBlockOffsetsForFloats(aFrame, leftOffset, rightOffset,
+ ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect,
+ leftOffset, rightOffset,
replacedWidth);
aResult.x = borderPadding.left + leftOffset;
aResult.width = mContentArea.width - leftOffset - rightOffset;
}
#ifdef REALLY_NOISY_REFLOW
printf(" CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
#endif
}
-void
-nsBlockReflowState::GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint)
+nsFlowAreaRect
+nsBlockReflowState::GetFloatAvailableSpaceWithState(
+ nscoord aY, PRBool aRelaxHeightConstraint,
+ nsFloatManager::SavedState *aState) const
{
#ifdef DEBUG
// Verify that the caller setup the coordinate system properly
nscoord wx, wy;
mFloatManager->GetTranslation(wx, wy);
NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
"bad coord system");
#endif
- PRBool hasFloats;
- mAvailSpaceRect =
+ nsFlowAreaRect result =
mFloatManager->GetBand(aY - BorderPadding().top,
aRelaxHeightConstraint ? nscoord_MAX
: mContentArea.height,
- mContentArea.width,
- &hasFloats);
- mBandHasFloats = hasFloats;
+ mContentArea.width, aState);
// Keep the width >= 0 for compatibility with nsSpaceManager.
- if (mAvailSpaceRect.width < 0)
- mAvailSpaceRect.width = 0;
+ if (result.mRect.width < 0)
+ result.mRect.width = 0;
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n",
- mAvailSpaceRect.x, mAvailSpaceRect.y,
- mAvailSpaceRect.width, mAvailSpaceRect.height,
- mBandHasFloats);
+ result.mRect.x, result.mRect.y, result.mRect.width,
+ result.mRect.height, result.mHasFloats);
}
#endif
+ return result;
}
/*
* Reconstruct the vertical margin before the line |aLine| in order to
* do an incremental reflow that begins with |aLine| without reflowing
* the line before it. |aLine| may point to the fencepost at the end of
* the line list, and it is used this way since we (for now, anyway)
* always need to recover margins at the end of a block.
@@ -520,27 +517,16 @@ nsBlockReflowState::RecoverStateFrom(nsL
}
#endif
// And then put the translation back again
mFloatManager->Translate(bp.left, bp.top);
}
}
PRBool
-nsBlockReflowState::IsImpactedByFloat() const
-{
-#ifdef REALLY_NOISY_REFLOW
- printf("nsBlockReflowState::IsImpactedByFloat %p returned %d\n",
- this, mBandHasFloats);
-#endif
- return mBandHasFloats;
-}
-
-
-PRBool
nsBlockReflowState::InitFloat(nsLineLayout& aLineLayout,
nsPlaceholderFrame* aPlaceholder,
nscoord aAvailableWidth,
nsReflowStatus& aReflowStatus)
{
// Set the geometric parent of the float
nsIFrame* floatFrame = aPlaceholder->GetOutOfFlowFrame();
floatFrame->SetParent(mBlock);
@@ -570,50 +556,54 @@ nsBlockReflowState::AddFloat(nsLineLayou
{
NS_PRECONDITION(mBlock->end_lines() != mCurrentLine, "null ptr");
aReflowStatus = NS_FRAME_COMPLETE;
// Allocate a nsFloatCache for the float
nsFloatCache* fc = mFloatCacheFreeList.Alloc();
fc->mPlaceholder = aPlaceholder;
+ // Because we are in the middle of reflowing a placeholder frame
+ // within a line (and possibly nested in an inline frame or two
+ // that's a child of our block) we need to restore the space
+ // manager's translation to the space that the block resides in
+ // before placing the float.
+ nscoord ox, oy;
+ mFloatManager->GetTranslation(ox, oy);
+ nscoord dx = ox - mFloatManagerX;
+ nscoord dy = oy - mFloatManagerY;
+ mFloatManager->Translate(-dx, -dy);
+
PRBool placed;
// Now place the float immediately if possible. Otherwise stash it
// away in mPendingFloats and place it later.
// If one or more floats has already been pushed to the next line,
// don't let this one go on the current line, since that would violate
// float ordering.
+ nsRect floatAvailableSpace = GetFloatAvailableSpace().mRect;
if (mBelowCurrentLineFloats.IsEmpty() &&
(aLineLayout.LineIsEmpty() ||
- mBlock->ComputeFloatWidth(*this, aPlaceholder) <= aAvailableWidth)) {
- // Because we are in the middle of reflowing a placeholder frame
- // within a line (and possibly nested in an inline frame or two
- // that's a child of our block) we need to restore the space
- // manager's translation to the space that the block resides in
- // before placing the float.
- nscoord ox, oy;
- mFloatManager->GetTranslation(ox, oy);
- nscoord dx = ox - mFloatManagerX;
- nscoord dy = oy - mFloatManagerY;
- mFloatManager->Translate(-dx, -dy);
-
+ mBlock->ComputeFloatWidth(*this, floatAvailableSpace, aPlaceholder) <=
+ aAvailableWidth)) {
// And then place it
PRBool isLeftFloat;
// force it to fit if we're at the top of the block and we can't
// break before this
PRBool forceFit = IsAdjacentWithTop() && !aLineLayout.LineIsBreakable();
placed = FlowAndPlaceFloat(fc, &isLeftFloat, aReflowStatus, forceFit);
NS_ASSERTION(placed || !forceFit,
"If we asked for force-fit, it should have been placed");
if (forceFit || (placed && !NS_FRAME_IS_TRUNCATED(aReflowStatus))) {
// Pass on updated available space to the current inline reflow engine
- GetAvailableSpace(mY, forceFit);
- nsRect availSpace(nsPoint(mAvailSpaceRect.x + BorderPadding().left, mY),
- mAvailSpaceRect.Size());
+ nsFlowAreaRect floatAvailSpace =
+ GetFloatAvailableSpace(mY, forceFit);
+ nsRect availSpace(nsPoint(floatAvailSpace.mRect.x + BorderPadding().left,
+ mY),
+ floatAvailSpace.mRect.Size());
aLineLayout.UpdateBand(availSpace, isLeftFloat,
aPlaceholder->GetOutOfFlowFrame());
// Record this float in the current-line list
mCurrentLineFloats.Append(fc);
// If we can't break here, hide the fact that it's truncated
// XXX We can probably do this more cleanly
aReflowStatus &= ~NS_FRAME_TRUNCATED;
@@ -627,19 +617,16 @@ nsBlockReflowState::AddFloat(nsLineLayou
aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
} else {
// Make sure we propagate the truncated status; this signals the
// block to push the line to the next page.
aReflowStatus |= NS_FRAME_TRUNCATED;
}
delete fc;
}
-
- // Restore coordinate system
- mFloatManager->Translate(dx, dy);
}
else {
// Always claim to be placed; we don't know whether we fit yet, so we
// deal with this in PlaceBelowCurrentLineFloats
placed = PR_TRUE;
// This float will be placed after the line is done (it is a
// below-current-line float).
mBelowCurrentLineFloats.Append(fc);
@@ -651,62 +638,68 @@ nsBlockReflowState::AddFloat(nsLineLayou
// Note that we could have unconstrained height and yet have
// a next-in-flow placeholder --- for example columns can switch
// from constrained height to unconstrained height.
if (aPlaceholder->GetSplittableType() != NS_FRAME_NOT_SPLITTABLE) {
aReflowStatus = NS_FRAME_NOT_COMPLETE;
}
}
}
+
+ // Restore coordinate system
+ mFloatManager->Translate(dx, dy);
+
return placed;
}
PRBool
-nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
- PRUint8 aFloats, PRBool aForceFit)
+nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats,
+ const nsFlowAreaRect& aFloatAvailableSpace,
+ PRBool aForceFit)
{
// If the current Y coordinate is not impacted by any floats
// then by definition the float fits.
PRBool result = PR_TRUE;
- if (mBandHasFloats) {
+ if (aFloatAvailableSpace.mHasFloats) {
// XXX We should allow overflow by up to half a pixel here (bug 21193).
- if (mAvailSpaceRect.width < aFloatSize.width) {
+ if (aFloatAvailableSpace.mRect.width < aFloatSize.width) {
// The available width is too narrow (and its been impacted by a
// prior float)
result = PR_FALSE;
}
}
if (!result)
return result;
// At this point we know that there is enough horizontal space for
// the float (somewhere). Lets see if there is enough vertical
// space.
- if (NSCoordGreaterThan(aFloatSize.height, mAvailSpaceRect.height)) {
+ if (NSCoordGreaterThan(aFloatSize.height,
+ aFloatAvailableSpace.mRect.height)) {
// The available height is too short. However, its possible that
// there is enough open space below which is not impacted by a
// float.
//
// Compute the X coordinate for the float based on its float
// type, assuming its placed on the current line. This is
// where the float will be placed horizontally if it can go
// here.
nscoord xa;
if (NS_STYLE_FLOAT_LEFT == aFloats) {
- xa = mAvailSpaceRect.x;
+ xa = aFloatAvailableSpace.mRect.x;
}
else {
- xa = mAvailSpaceRect.XMost() - aFloatSize.width;
+ xa = aFloatAvailableSpace.mRect.XMost() - aFloatSize.width;
// In case the float is too big, don't go past the left edge
// XXXldb This seems wrong, but we might want to fix bug 6976
// first.
- if (xa < mAvailSpaceRect.x) {
- xa = mAvailSpaceRect.x;
+ if (xa < aFloatAvailableSpace.mRect.x) {
+ xa = aFloatAvailableSpace.mRect.x;
}
}
nscoord xb = xa + aFloatSize.width;
// Calculate the top and bottom y coordinates, again assuming
// that the float is placed on the current line.
const nsMargin& borderPadding = BorderPadding();
nscoord ya = mY - borderPadding.top;
@@ -716,47 +709,47 @@ nsBlockReflowState::CanPlaceFloat(const
// containing block is the content edge of the block box, this
// means the margin edge of the float can't be higher than the
// content edge of the block that contains it.)
ya = 0;
}
nscoord yb = ya + aFloatSize.height;
nscoord saveY = mY;
+ nsFlowAreaRect floatAvailableSpace(aFloatAvailableSpace);
for (;;) {
// Get the available space at the new Y coordinate
- if (mAvailSpaceRect.height <= 0) {
+ if (floatAvailableSpace.mRect.height <= 0) {
// there is no more available space. We lose.
result = PR_FALSE;
break;
}
- mY += mAvailSpaceRect.height;
- GetAvailableSpace(mY, aForceFit);
+ mY += floatAvailableSpace.mRect.height;
+ floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
- if (mBandHasFloats) {
- if ((xa < mAvailSpaceRect.x) || (xb > mAvailSpaceRect.XMost())) {
+ if (floatAvailableSpace.mHasFloats) {
+ if (xa < floatAvailableSpace.mRect.x ||
+ xb > floatAvailableSpace.mRect.XMost()) {
// The float can't go here.
result = PR_FALSE;
break;
}
}
// See if there is now enough height for the float.
- if (yb <= mY + mAvailSpaceRect.height) {
+ if (yb <= mY + floatAvailableSpace.mRect.height) {
// Winner. The bottom Y coordinate of the float is in
// this band.
break;
}
}
- // Restore Y coordinate and available space information
- // regardless of the outcome.
+ // Restore Y coordinate
mY = saveY;
- GetAvailableSpace(mY, aForceFit);
}
return result;
}
PRBool
nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
PRBool* aIsLeftFloat,
@@ -787,24 +780,25 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
// See if the float should clear any preceding floats...
// XXX We need to mark this float somehow so that it gets reflowed
// when floats are inserted before it.
if (NS_STYLE_CLEAR_NONE != floatDisplay->mBreakType) {
// XXXldb Does this handle vertical margins correctly?
mY = ClearFloats(mY, floatDisplay->mBreakType);
}
// Get the band of available space
- GetAvailableSpace(mY, aForceFit);
+ nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
NS_ASSERTION(floatFrame->GetParent() == mBlock,
"Float frame has wrong parent");
// Reflow the float
nsMargin floatMargin;
- mBlock->ReflowFloat(*this, placeholder, floatMargin, aReflowStatus);
+ mBlock->ReflowFloat(*this, floatAvailableSpace.mRect, placeholder,
+ floatMargin, aReflowStatus);
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsRect region = floatFrame->GetRect();
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("flowed float: ");
nsFrame::ListTag(stdout, floatFrame);
printf(" (%d,%d,%d,%d)\n",
@@ -820,29 +814,30 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
// block if possible (CSS2 spec section 9.5.1, see the rule list).
NS_ASSERTION((NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) ||
(NS_STYLE_FLOAT_RIGHT == floatDisplay->mFloats),
"invalid float type");
// Can the float fit here?
PRBool keepFloatOnSameLine = PR_FALSE;
- while (!CanPlaceFloat(floatSize, floatDisplay->mFloats, aForceFit)) {
- if (mAvailSpaceRect.height <= 0) {
+ while (!CanPlaceFloat(floatSize, floatDisplay->mFloats, floatAvailableSpace,
+ aForceFit)) {
+ if (floatAvailableSpace.mRect.height <= 0) {
// No space, nowhere to put anything.
mY = saveY;
return PR_FALSE;
}
// Nope. try to advance to the next band.
if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
- mY += mAvailSpaceRect.height;
- GetAvailableSpace(mY, aForceFit);
+ mY += floatAvailableSpace.mRect.height;
+ floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
} else {
// This quirk matches the one in nsBlockFrame::ReflowFloat
// IE handles float tables in a very special way
// see if the previous float is also a table and has "align"
nsFloatCache* fc = mCurrentLineFloats.Head();
nsIFrame* prevFrame = nsnull;
while (fc) {
@@ -870,23 +865,24 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
// since we cannot evangelize the world
break;
}
}
}
}
// the table does not fit anymore in this line so advance to next band
- mY += mAvailSpaceRect.height;
- GetAvailableSpace(mY, aForceFit);
+ mY += floatAvailableSpace.mRect.height;
+ floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
// reflow the float again now since we have more space
// XXXldb We really don't need to Reflow in a loop, we just need
// to ComputeSize in a loop (once ComputeSize depends on
// availableWidth, which should make this work again).
- mBlock->ReflowFloat(*this, placeholder, floatMargin, aReflowStatus);
+ mBlock->ReflowFloat(*this, floatAvailableSpace.mRect, placeholder,
+ floatMargin, aReflowStatus);
// Get the floats bounding box and margin information
floatSize = floatFrame->GetSize() +
nsSize(floatMargin.LeftRight(), floatMargin.TopBottom());
}
}
// If the float is continued, it will get the same absolute x value as its prev-in-flow
// We don't worry about the geometry of the prev in flow, let the continuation
@@ -895,28 +891,28 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
// Assign an x and y coordinate to the float. Note that the x,y
// coordinates are computed <b>relative to the translation in the
// spacemanager</b> which means that the impacted region will be
// <b>inside</b> the border/padding area.
PRBool isLeftFloat;
nscoord floatX, floatY;
if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
isLeftFloat = PR_TRUE;
- floatX = mAvailSpaceRect.x;
+ floatX = floatAvailableSpace.mRect.x;
}
else {
isLeftFloat = PR_FALSE;
if (!keepFloatOnSameLine) {
- floatX = mAvailSpaceRect.XMost() - floatSize.width;
+ floatX = floatAvailableSpace.mRect.XMost() - floatSize.width;
}
else {
// this is the IE quirk (see few lines above)
// the table is kept in the same line: don't let it overlap the
// previous float
- floatX = mAvailSpaceRect.x;
+ floatX = floatAvailableSpace.mRect.x;
}
}
*aIsLeftFloat = isLeftFloat;
const nsMargin& borderPadding = BorderPadding();
floatY = mY - borderPadding.top;
if (floatY < 0) {
// CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
// be higher than the top of its containing block." (Since the
@@ -1100,47 +1096,45 @@ nsBlockReflowState::ClearFloats(nscoord
nscoord newY = aY;
if (aBreakType != NS_STYLE_CLEAR_NONE) {
newY = bp.top + mFloatManager->ClearFloats(newY - bp.top, aBreakType);
}
if (aReplacedBlock) {
for (;;) {
- GetAvailableSpace(newY, PR_FALSE);
+ nsFlowAreaRect floatAvailableSpace =
+ GetFloatAvailableSpace(newY, PR_FALSE);
nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
- nsBlockFrame::WidthToClearPastFloats(*this, aReplacedBlock);
- if (!mBandHasFloats ||
- PR_MAX(mAvailSpaceRect.x, replacedWidth.marginLeft) +
+ nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
+ aReplacedBlock);
+ if (!floatAvailableSpace.mHasFloats ||
+ PR_MAX(floatAvailableSpace.mRect.x, replacedWidth.marginLeft) +
replacedWidth.borderBoxWidth +
PR_MAX(mContentArea.width -
- PR_MIN(mContentArea.width, mAvailSpaceRect.XMost()),
+ PR_MIN(mContentArea.width,
+ floatAvailableSpace.mRect.XMost()),
replacedWidth.marginRight) <=
mContentArea.width) {
break;
}
// See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames
- if (mAvailSpaceRect.height > 0) {
+ if (floatAvailableSpace.mRect.height > 0) {
// See if there's room in the next band.
- newY += mAvailSpaceRect.height;
+ newY += floatAvailableSpace.mRect.height;
} else {
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
// Stop trying to clear here; we'll just get pushed to the
// next column or page and try again there.
break;
}
NS_NOTREACHED("avail space rect with zero height!");
newY += 1;
}
}
- // Restore mBandHasFloats and mAvailSpaceRect to the way they were.
- // This may well not be needed, and we should probably come up with
- // well-defined rules about when these members are valid so that
- // it's clearly not needed.
- GetAvailableSpace();
}
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("clear floats: out: y=%d(%d)\n", newY, newY - bp.top);
}
#endif
--- a/layout/generic/nsBlockReflowState.h
+++ b/layout/generic/nsBlockReflowState.h
@@ -78,38 +78,51 @@ public:
// Set up a property on the block that points to our temporary mOverflowPlaceholders
// list, if that list is or could become non-empty during this reflow. Must be
// called after the block has done DrainOverflowLines because DrainOverflowLines
// can setup mOverflowPlaceholders even if the block is in unconstrained height
// reflow (it may have previously been reflowed with constrained height).
void SetupOverflowPlaceholdersProperty();
/**
- * Get the available reflow space for the current y coordinate. The
- * available space is relative to our coordinate system (0,0) is our
- * upper left corner.
+ * Get the available reflow space (the area not occupied by floats)
+ * for the current y coordinate. The available space is relative to
+ * our coordinate system, which is the content box, with (0, 0) in the
+ * upper left.
+ *
+ * Returns whether there are floats present at the given vertical
+ * coordinate and within the width of the content rect.
*/
- void GetAvailableSpace() { GetAvailableSpace(mY, PR_FALSE); }
- void GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint);
+ nsFlowAreaRect GetFloatAvailableSpace() const
+ { return GetFloatAvailableSpace(mY, PR_FALSE); }
+ nsFlowAreaRect GetFloatAvailableSpace(nscoord aY,
+ PRBool aRelaxHeightConstraint) const
+ { return GetFloatAvailableSpaceWithState(aY, aRelaxHeightConstraint,
+ nsnull); }
+ nsFlowAreaRect
+ GetFloatAvailableSpaceWithState(nscoord aY, PRBool aRelaxHeightConstraint,
+ nsFloatManager::SavedState *aState) const;
/*
* The following functions all return PR_TRUE if they were able to
* place the float, PR_FALSE if the float did not fit in available
* space.
*/
PRBool InitFloat(nsLineLayout& aLineLayout,
nsPlaceholderFrame* aPlaceholderFrame,
nscoord aAvailableWidth,
nsReflowStatus& aReflowStatus);
PRBool AddFloat(nsLineLayout& aLineLayout,
nsPlaceholderFrame* aPlaceholderFrame,
PRBool aInitialReflow,
nscoord aAvailableWidth,
nsReflowStatus& aReflowStatus);
- PRBool CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats, PRBool aForceFit);
+ PRBool CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats,
+ const nsFlowAreaRect& aFloatAvailableSpace,
+ PRBool aForceFit);
PRBool FlowAndPlaceFloat(nsFloatCache* aFloatCache,
PRBool* aIsLeftFloat,
nsReflowStatus& aReflowStatus,
PRBool aForceFit);
PRBool PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aFloats, PRBool aForceFit);
// Returns the first coordinate >= aY that clears the
// floats indicated by aBreakType and has enough width between floats
@@ -144,24 +157,26 @@ public:
// Reconstruct the previous bottom margin that goes above |aLine|.
void ReconstructMarginAbove(nsLineList::iterator aLine);
// Caller must have called GetAvailableSpace for the correct position
// (which need not be the current mY). Callers need only pass
// aReplacedWidth for outer table frames.
void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
+ const nsRect& aFloatAvailableSpace,
nscoord& aLeftResult,
nscoord& aRightResult,
nsBlockFrame::ReplacedElementWidthToClear
*aReplacedWidth = nsnull);
// Caller must have called GetAvailableSpace for the current mY
void ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsStyleDisplay* aDisplay,
+ const nsFlowAreaRect& aFloatAvailableSpace,
PRBool aBlockAvoidsFloats,
nsRect& aResult);
protected:
void RecoverFloats(nsLineList::iterator aLine, nscoord aDeltaY);
public:
void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaY);
@@ -169,18 +184,16 @@ public:
void AdvanceToNextLine() {
if (GetFlag(BRS_LINE_LAYOUT_EMPTY)) {
SetFlag(BRS_LINE_LAYOUT_EMPTY, PR_FALSE);
} else {
mLineNumber++;
}
}
- PRBool IsImpactedByFloat() const;
-
nsLineBox* NewLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock);
void FreeLineBox(nsLineBox* aLine);
//----------------------------------------
// This state is the "global" state computed once for the reflow of
// the block.
@@ -199,22 +212,21 @@ public:
// padding. This, therefore, represents the inner "content area" (in
// spacemanager coordinates) where child frames will be placed,
// including child blocks and floats.
nscoord mFloatManagerX, mFloatManagerY;
// XXX get rid of this
nsReflowStatus mReflowStatus;
- // The x-position we should place an outside bullet relative to.
- // This is the border-box edge of the principal box. However, if a line box
- // would be displaced by floats, we want to displace it by the same amount.
- // That is, we act as though the edge of the floats is the content-edge of
- // the block, displaced by the block's padding and border.
- nscoord mOutsideBulletX;
+ // The float manager state as it was before the contents of this
+ // block. This is needed for positioning bullets, since we only want
+ // to move the bullet to flow around floats that were before this
+ // block, not floats inside of it.
+ nsFloatManager::SavedState mFloatManagerStateBefore;
nscoord mBottomEdge;
// The content area to reflow child frames within. The x/y
// coordinates are known to be mBorderPadding.left and
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
// if the container reflowing this frame has given the frame an
// unconstrained area.
@@ -245,20 +257,16 @@ public:
// which we know is adjacent to the top of the block (in other words,
// all lines before it are empty and do not have clearance. This line is
// always before the current line.
nsLineList::iterator mLineAdjacentToTop;
// The current Y coordinate in the block
nscoord mY;
- // The available space within the current band.
- // (relative to the *content*-rect of the block)
- nsRect mAvailSpaceRect;
-
// The combined area of all floats placed so far
nsRect mFloatCombinedArea;
nsFloatCacheFreeList mFloatCacheFreeList;
// Previous child. This is used when pulling up a frame to update
// the sibling list.
nsIFrame* mPrevChild;
@@ -291,21 +299,16 @@ public:
nscoord mMinLineHeight;
PRInt32 mLineNumber;
PRInt16 mFlags;
PRUint8 mFloatBreakType;
- // The number of floats on the sides of mAvailSpaceRect, including
- // floats that do not reduce mAvailSpaceRect because they are in the
- // margins.
- PRPackedBool mBandHasFloats;
-
void SetFlag(PRUint32 aFlag, PRBool aValue)
{
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
if (aValue) { // set flag
mFlags |= aFlag;
}
else { // unset flag
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -130,39 +130,48 @@ void nsFloatManager::Shutdown()
if (floatManager)
nsMemory::Free(floatManager);
}
// Disable further caching.
sCachedFloatManagerCount = -1;
}
-nsRect
+nsFlowAreaRect
nsFloatManager::GetBand(nscoord aYOffset,
nscoord aMaxHeight,
nscoord aContentAreaWidth,
- PRBool* aHasFloats) const
+ SavedState* aState) const
{
NS_ASSERTION(aMaxHeight >= 0, "unexpected max height");
NS_ASSERTION(aContentAreaWidth >= 0, "unexpected content area width");
nscoord top = aYOffset + mY;
if (top < nscoord_MIN) {
NS_WARNING("bad value");
top = nscoord_MIN;
}
+ // Determine the last float that we should consider.
+ PRUint32 floatCount;
+ if (aState) {
+ // Use the provided state.
+ floatCount = aState->mFloatInfoCount;
+ NS_ABORT_IF_FALSE(floatCount <= mFloats.Length(), "bad state");
+ } else {
+ // Use our current state.
+ floatCount = mFloats.Length();
+ }
+
// If there are no floats at all, or we're below the last one, return
// quickly.
- PRUint32 floatCount = mFloats.Length();
if (floatCount == 0 ||
(mFloats[floatCount-1].mLeftYMost <= top &&
mFloats[floatCount-1].mRightYMost <= top)) {
- *aHasFloats = PR_FALSE;
- return nsRect(0, aYOffset, aContentAreaWidth, aMaxHeight);
+ return nsFlowAreaRect(0, aYOffset, aContentAreaWidth, aMaxHeight, PR_FALSE);
}
nscoord bottom;
if (aMaxHeight == nscoord_MAX) {
bottom = nscoord_MAX;
} else {
bottom = top + aMaxHeight;
if (bottom < top || bottom > nscoord_MAX) {
@@ -175,17 +184,17 @@ nsFloatManager::GetBand(nscoord aYOffset
if (right < left) {
NS_WARNING("bad value");
right = left;
}
// Walk backwards through the floats until we either hit the front of
// the list or we're above |top|.
PRBool haveFloats = PR_FALSE;
- for (PRUint32 i = mFloats.Length(); i > 0; --i) {
+ for (PRUint32 i = floatCount; i > 0; --i) {
const FloatInfo &fi = mFloats[i-1];
if (fi.mLeftYMost <= top && fi.mRightYMost <= top) {
// There aren't any more floats that could intersect this band.
break;
}
if (fi.mRect.IsEmpty()) {
// For compatibility, ignore floats with empty rects, even though it
// disagrees with the spec. (We might want to fix this in the
@@ -225,19 +234,18 @@ nsFloatManager::GetBand(nscoord aYOffset
right = leftEdge;
// See above.
haveFloats = PR_TRUE;
}
}
}
}
- *aHasFloats = haveFloats;
nscoord height = (bottom == nscoord_MAX) ? nscoord_MAX : (bottom - top);
- return nsRect(left - mX, top - mY, right - left, height);
+ return nsFlowAreaRect(left - mX, top - mY, right - left, height, haveFloats);
}
nsresult
nsFloatManager::AddFloat(nsIFrame* aFloatFrame, const nsRect& aMarginRect)
{
NS_ASSERTION(aMarginRect.width >= 0, "negative width!");
NS_ASSERTION(aMarginRect.height >= 0, "negative height!");
--- a/layout/generic/nsFloatManager.h
+++ b/layout/generic/nsFloatManager.h
@@ -47,28 +47,56 @@
#include "nsRect.h"
#include "nsTArray.h"
class nsIPresShell;
class nsIFrame;
struct nsHTMLReflowState;
class nsPresContext;
+/**
+ * The available space for content not occupied by floats is divided
+ * into a (vertical) sequence of rectangles. However, we need to know
+ * not only the rectangle, but also whether it was reduced (from the
+ * content rectangle) by floats that actually intruded into the content
+ * rectangle.
+ */
+struct nsFlowAreaRect {
+ nsRect mRect;
+ PRPackedBool mHasFloats;
+
+ nsFlowAreaRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
+ PRBool aHasFloats)
+ : mRect(aX, aY, aWidth, aHeight), mHasFloats(aHasFloats) {}
+};
+
#define NS_FLOAT_MANAGER_CACHE_SIZE 4
class nsFloatManager {
public:
nsFloatManager(nsIPresShell* aPresShell);
~nsFloatManager();
void* operator new(size_t aSize) CPP_THROW_NEW;
void operator delete(void* aPtr, size_t aSize);
static void Shutdown();
+ // Structure that stores the current state of a frame manager for
+ // Save/Restore purposes.
+ struct SavedState;
+ friend struct SavedState;
+ struct SavedState {
+ private:
+ PRUint32 mFloatInfoCount;
+ nscoord mX, mY;
+
+ friend class nsFloatManager;
+ };
+
/**
* Translate the current origin by the specified (dx, dy). This
* creates a new local coordinate space relative to the current
* coordinate space.
*/
void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }
/**
@@ -87,28 +115,31 @@ public:
* |aMaxHeight|. The left and right edges of the rectangle give the
* area available for line boxes in that space.
*
* @param aY [in] vertical coordinate for top of available space
* desired
* @param aMaxHeight [in] maximum height of available space desired
* @param aContentAreaWidth [in] the width of the content area (whose left
* edge must be zero in the current translation)
- * @param aHasFloats [out] whether there are floats at the sides of
- * the return value including those that do not
- * reduce the line box width at all (because they
- * are entirely in the margins)
- * @return the resulting rectangle for line boxes. It will not go
- * left of 0, nor right of aContentAreaWidth, but will be
- * narrower when floats are present.
+ * @param aState [in] If null, use the current state, otherwise, do
+ * computation based only on floats present in the given
+ * saved state.
+ * @return An nsFlowAreaRect whose:
+ * mRect is the resulting rectangle for line boxes. It will not go
+ * left of 0, nor right of aContentAreaWidth, but will be
+ * narrower when floats are present.
+ * mBandHasFloats is whether there are floats at the sides of the
+ * return value including those that do not reduce the line box
+ * width at all (because they are entirely in the margins)
*
* aY and aAvailSpace are positioned relative to the current translation
*/
- nsRect GetBand(nscoord aY, nscoord aMaxHeight, nscoord aContentAreaWidth,
- PRBool* aHasFloats) const;
+ nsFlowAreaRect GetBand(nscoord aY, nscoord aMaxHeight,
+ nscoord aContentAreaWidth, SavedState* aState) const;
/**
* Add a float that comes after all floats previously added. Its top
* must be even with or below the top of all previous floats.
*
* aMarginRect is relative to the current translation. The caller
* must ensure aMarginRect.height >= 0 and aMarginRect.width >= 0.
*/
@@ -123,28 +154,16 @@ public:
* not be removed, YOU LOSE.
*/
nsresult RemoveTrailingRegions(nsIFrame* aFrameList);
private:
struct FloatInfo;
public:
- // Structure that stores the current state of a frame manager for
- // Save/Restore purposes.
- struct SavedState;
- friend struct SavedState;
- struct SavedState {
- private:
- PRUint32 mFloatInfoCount;
- nscoord mX, mY;
-
- friend class nsFloatManager;
- };
-
PRBool HasAnyFloats() const { return !mFloats.IsEmpty(); }
/**
* Methods for dealing with the propagation of float damage during
* reflow.
*/
PRBool HasFloatDamage() const
{
@@ -167,17 +186,19 @@ public:
void PushState(SavedState* aState);
/**
* Restores the float manager to the saved state.
*
* These states must be managed using stack discipline. PopState can only
* be used after PushState has been used to save the state, and it can only
* be used once --- although it can be omitted; saved states can be ignored.
- * States must be popped in the reverse order they were pushed.
+ * States must be popped in the reverse order they were pushed. A
+ * call to PopState invalidates any saved states Pushed after the
+ * state passed to PopState was pushed.
*/
void PopState(SavedState* aState);
/**
* Get the top of the last float placed into the float manager, to
* enforce the rule that a float can't be above an earlier float.
* Returns the minimum nscoord value if there are no floats.
*
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -44,16 +44,17 @@
#include "nsGkAtoms.h"
#include "nsHTMLCanvasFrame.h"
#include "nsICanvasElement.h"
#include "nsDisplayList.h"
#include "nsTransform2D.h"
+#include "gfxContext.h"
class nsDisplayItemCanvas : public nsDisplayItem {
public:
nsDisplayItemCanvas(nsIFrame* aFrame)
: nsDisplayItem(aFrame)
{
MOZ_COUNT_CTOR(nsDisplayItemCanvas);
}
@@ -219,54 +220,45 @@ nsHTMLCanvasFrame::GetInnerArea() const
r.height = mRect.height - mBorderPadding.top - mBorderPadding.bottom;
return r;
}
void
nsHTMLCanvasFrame::PaintCanvas(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, nsPoint aPt)
{
+ nsPresContext *presContext = PresContext();
nsRect inner = GetInnerArea() + aPt;
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
if (!canvas)
return;
// anything to do?
if (inner.width == 0 || inner.height == 0)
return;
- nsIntSize canvasSize = GetCanvasSize();
- nsSize sizeAppUnits(PresContext()->DevPixelsToAppUnits(canvasSize.width),
- PresContext()->DevPixelsToAppUnits(canvasSize.height));
+ nsIntSize sizeCSSPixels = GetCanvasSize();
+ nsSize sizeAppUnits(nsPresContext::CSSPixelsToAppUnits(sizeCSSPixels.width),
+ nsPresContext::CSSPixelsToAppUnits(sizeCSSPixels.height));
- // XXXvlad clip to aDirtyRect!
+ gfxContext *ctx = aRenderingContext.ThebesContext();
- if (inner.Size() != sizeAppUnits)
- {
- float sx = inner.width / (float) sizeAppUnits.width;
- float sy = inner.height / (float) sizeAppUnits.height;
+ gfxFloat sx = inner.width / (gfxFloat) sizeAppUnits.width;
+ gfxFloat sy = inner.height / (gfxFloat) sizeAppUnits.height;
- aRenderingContext.PushState();
- aRenderingContext.Translate(inner.x, inner.y);
- aRenderingContext.Scale(sx, sy);
-
- canvas->RenderContexts(aRenderingContext.ThebesContext());
+ ctx->Save();
- aRenderingContext.PopState();
- } else {
- //nsIRenderingContext::AutoPushTranslation(&aRenderingContext, px, py);
+ ctx->Translate(gfxPoint(presContext->AppUnitsToGfxUnits(inner.x),
+ presContext->AppUnitsToGfxUnits(inner.y)));
+ ctx->Scale(sx, sy);
- aRenderingContext.PushState();
- aRenderingContext.Translate(inner.x, inner.y);
+ canvas->RenderContexts(ctx);
- canvas->RenderContexts(aRenderingContext.ThebesContext());
-
- aRenderingContext.PopState();
- }
+ ctx->Restore();
}
NS_IMETHODIMP
nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!IsVisibleForPainting(aBuilder))
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1-ltr-insets-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 20px"></div>
+<div style="margin-left: 32px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1-ltr-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 20px"></div>
+<div style="margin-left: 40px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1-rtl-insets-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 20px"></div>
+<div style="margin-right: 32px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1-rtl-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 20px"></div>
+<div style="margin-right: 40px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1a-ltr-insets.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1a-ltr.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1a-rtl-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1a-rtl.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1b-ltr-insets.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1b-ltr.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1b-rtl-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1b-rtl.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1c-ltr-insets.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1c-ltr.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1c-rtl-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1c-rtl.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1d-ltr-insets.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1d-ltr.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1d-rtl-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-1d-rtl.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2-ltr-insets-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 20px"></div>
+<div style="margin-left: 32px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2-ltr-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 20px"></div>
+<div style="margin-left: 40px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2-rtl-insets-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 20px"></div>
+<div style="margin-right: 32px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2-rtl-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 20px"></div>
+<div style="margin-right: 40px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2a-ltr-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div style="float: left; height: 20px; width: 15px"></div>
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2a-ltr.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div style="float: left; height: 20px; width: 15px"></div>
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2a-rtl-insets.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div style="float: right; height: 20px; width: 15px"></div>
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2a-rtl.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div style="float: right; height: 20px; width: 15px"></div>
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2b-ltr-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div style="float: left; height: 20px; width: 15px"></div>
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2b-ltr.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div style="float: left; height: 20px; width: 15px"></div>
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2b-rtl-insets.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div style="float: right; height: 20px; width: 15px"></div>
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2b-rtl.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div style="float: right; height: 20px; width: 15px"></div>
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2e-ltr-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div style="float: left; height: 20px; width: 15px"></div>
+ <div style="clear:left"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2e-ltr.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div style="float: left; height: 20px; width: 15px"></div>
+ <div style="clear:left"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2e-rtl-insets.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div style="float: right; height: 20px; width: 15px"></div>
+ <div style="clear:right"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2e-rtl.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div style="float: right; height: 20px; width: 15px"></div>
+ <div style="clear:right"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2f-ltr-insets.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div style="float: left; height: 20px; width: 15px"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2f-ltr.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div style="float: left; height: 20px; width: 15px"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2f-rtl-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div style="float: right; height: 20px; width: 15px"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-2f-rtl.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div style="float: right; height: 20px; width: 15px"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3-ltr-insets-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 40px"></div>
+<div style="margin-left: 32px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3-ltr-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 40px"></div>
+<div style="margin-left: 40px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3-rtl-insets-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 40px"></div>
+<div style="margin-right: 32px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3-rtl-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 40px"></div>
+<div style="margin-right: 40px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3a-ltr-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div style="float: left; height: 20px; width: 60px"></div>
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3a-ltr.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div style="float: left; height: 20px; width: 60px"></div>
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3a-rtl-insets.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div style="float: right; height: 20px; width: 60px"></div>
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3a-rtl.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div style="float: right; height: 20px; width: 60px"></div>
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3b-ltr-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div style="float: left; height: 20px; width: 60px"></div>
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3b-ltr.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div style="float: left; height: 20px; width: 60px"></div>
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3b-rtl-insets.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div style="float: right; height: 20px; width: 60px"></div>
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3b-rtl.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div style="float: right; height: 20px; width: 60px"></div>
+ <div> </div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3e-ltr-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div style="float: left; height: 20px; width: 60px"></div>
+ <div style="clear:left"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3e-ltr.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div style="float: left; height: 20px; width: 60px"></div>
+ <div style="clear:left"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3e-rtl-insets.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div style="float: right; height: 20px; width: 60px"></div>
+ <div style="clear:right"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3e-rtl.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div style="float: right; height: 20px; width: 60px"></div>
+ <div style="clear:right"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3f-ltr-insets.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: left; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
+ <div style="float: left; height: 20px; width: 60px"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3f-ltr.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: left; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-left: 40px; width: 70px; display: list-item;">
+ <div style="float: left; height: 20px; width: 60px"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3f-rtl-insets.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 6px">
+ <div style="float: right; height: 20px; width: 116px"></div>
+</div>
+<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
+ <div style="float: right; height: 20px; width: 60px"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-3f-rtl.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px">
+ <div style="float: right; height: 20px; width: 100px"></div>
+</div>
+<div style="margin-right: 40px; width: 70px; display: list-item;">
+ <div style="float: right; height: 20px; width: 60px"></div>
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-empty-ltr-insets-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 13px"></div>
+<div style="margin-left: 92px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-empty-ltr-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px"></div>
+<div style="margin-left: 100px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-empty-rtl-insets-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 13px"></div>
+<div style="margin-right: 92px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/428810-empty-rtl-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html dir="rtl">
+<title>Testcase, bug 428810</title>
+<style type="text/css">
+html, body { margin: 0; padding: 0; }
+</style>
+<div style="height: 10px"></div>
+<div style="margin-right: 100px; display: list-item;">
+
+</div>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/472020-1-ref.xul
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ outer {
+ -moz-binding: url(472020-xbl.xml#outer);
+ border: 2px solid yellow;
+ }
+ inner {
+ -moz-binding: url(472020-xbl.xml#inner);
+ }
+ box {
+ width: 50px;
+ border: 2px solid green;
+ }
+]]></style>
+
+ <outer>
+ <box/>
+ <box/>
+ </outer>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/472020-1a.xul
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="document.getElementById('o').appendChild(document.createElement('box'));">
+
+<style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ outer {
+ -moz-binding: url(472020-xbl.xml#outer);
+ border: 2px solid yellow;
+ }
+ inner {
+ -moz-binding: url(472020-xbl.xml#inner);
+ }
+ box {
+ width: 50px;
+ border: 2px solid green;
+ }
+]]></style>
+
+ <outer id="o">
+ <box/>
+ </outer>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/472020-1b.xul
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="var p = document.getElementById('o'); p.insertBefore(document.createElement('box'), p.firstChild);">
+
+<style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ outer {
+ -moz-binding: url(472020-xbl.xml#outer);
+ border: 2px solid yellow;
+ }
+ inner {
+ -moz-binding: url(472020-xbl.xml#inner);
+ }
+ box {
+ width: 50px;
+ border: 2px solid green;
+ }
+]]></style>
+
+ <outer id="o">
+ <box/>
+ </outer>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/472020-2-ref.xul
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ outer {
+ -moz-binding: url(472020-xbl.xml#outer);
+ border: 2px solid yellow;
+ }
+ inner {
+ -moz-binding: url(472020-xbl.xml#inner);
+ }
+ box {
+ width: 50px;
+ border: 2px solid green;
+ }
+]]></style>
+
+ <outer>
+ <box/>
+ </outer>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/472020-2.xul
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="document.getElementById('o').appendChild(document.createElement('box'));">
+
+<style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ outer {
+ -moz-binding: url(472020-xbl.xml#outer);
+ border: 2px solid yellow;
+ }
+ inner {
+ -moz-binding: url(472020-xbl.xml#inner);
+ }
+ box {
+ width: 50px;
+ border: 2px solid green;
+ }
+]]></style>
+
+ <outer id="o">
+ </outer>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/472020-xbl.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<bindings xmlns="http://www.mozilla.org/xbl"
+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <binding id="outer">
+ <content>
+ <xul:inner>
+ <xul:label value="Before"/>
+ <children/>
+ <xul:label value="After"/>
+ </xul:inner>
+ </content>
+ </binding>
+
+ <binding id="inner">
+ <content>
+ <children/>
+ </content>
+ </binding>
+
+</bindings>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -946,16 +946,82 @@ fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") ==
== 427370-1.html 427370-1-ref.html
== 427730-1.html 427730-1-ref.html
== 428278.html 428278-ref.html
== 428423-1a.html 428423-1-ref.html
== 428423-1b.html 428423-1-ref.html
== 428521-1a.html 428521-1-ref.html
== 428521-1b.html 428521-1-ref.html
== 428521-1c.html 428521-1-ref.html
+== 428810-1a-ltr.html 428810-1-ltr-ref.html
+== 428810-1b-ltr.html 428810-1-ltr-ref.html
+fails == 428810-1c-ltr.html 428810-empty-ltr-ref.html # bug 179596
+fails == 428810-1d-ltr.html 428810-empty-ltr-ref.html # bug 179596
+!= 428810-1-ltr-ref.html about:blank
+== 428810-2a-ltr.html 428810-2-ltr-ref.html
+== 428810-2b-ltr.html 428810-2-ltr-ref.html
+fails == 428810-2e-ltr.html 428810-empty-ltr-ref.html # bug 179596
+fails == 428810-2f-ltr.html 428810-empty-ltr-ref.html # bug 179596
+!= 428810-2-ltr-ref.html about:blank
+== 428810-3a-ltr.html 428810-3-ltr-ref.html
+== 428810-3b-ltr.html 428810-3-ltr-ref.html
+fails == 428810-3e-ltr.html 428810-empty-ltr-ref.html # bug 179596
+fails == 428810-3f-ltr.html 428810-empty-ltr-ref.html # bug 179596
+!= 428810-3-ltr-ref.html about:blank
+== 428810-1a-rtl.html 428810-1-rtl-ref.html
+== 428810-1b-rtl.html 428810-1-rtl-ref.html
+fails == 428810-1c-rtl.html 428810-empty-rtl-ref.html # bug 179596
+fails == 428810-1d-rtl.html 428810-empty-rtl-ref.html # bug 179596
+!= 428810-1-rtl-ref.html about:blank
+!= 428810-1-rtl-ref.html 428810-1-ltr-ref.html
+== 428810-2a-rtl.html 428810-2-rtl-ref.html
+== 428810-2b-rtl.html 428810-2-rtl-ref.html
+fails == 428810-2e-rtl.html 428810-empty-rtl-ref.html # bug 179596
+fails == 428810-2f-rtl.html 428810-empty-rtl-ref.html # bug 179596
+!= 428810-2-rtl-ref.html about:blank
+!= 428810-2-rtl-ref.html 428810-2-ltr-ref.html
+== 428810-3a-rtl.html 428810-3-rtl-ref.html
+== 428810-3b-rtl.html 428810-3-rtl-ref.html
+fails == 428810-3e-rtl.html 428810-empty-rtl-ref.html # bug 179596
+fails == 428810-3f-rtl.html 428810-empty-rtl-ref.html # bug 179596
+!= 428810-3-rtl-ref.html about:blank
+!= 428810-3-rtl-ref.html 428810-3-ltr-ref.html
+== 428810-1a-ltr-insets.html 428810-1-ltr-insets-ref.html
+== 428810-1b-ltr-insets.html 428810-1-ltr-insets-ref.html
+fails == 428810-1c-ltr-insets.html 428810-empty-ltr-insets-ref.html # bug 179596
+fails == 428810-1d-ltr-insets.html 428810-empty-ltr-insets-ref.html # bug 179596
+!= 428810-1-ltr-insets-ref.html about:blank
+== 428810-2a-ltr-insets.html 428810-2-ltr-insets-ref.html
+== 428810-2b-ltr-insets.html 428810-2-ltr-insets-ref.html
+fails == 428810-2e-ltr-insets.html 428810-empty-ltr-insets-ref.html # bug 179596
+fails == 428810-2f-ltr-insets.html 428810-empty-ltr-insets-ref.html # bug 179596
+!= 428810-2-ltr-insets-ref.html about:blank
+== 428810-3a-ltr-insets.html 428810-3-ltr-insets-ref.html
+== 428810-3b-ltr-insets.html 428810-3-ltr-insets-ref.html
+fails == 428810-3e-ltr-insets.html 428810-empty-ltr-insets-ref.html # bug 179596
+fails == 428810-3f-ltr-insets.html 428810-empty-ltr-insets-ref.html # bug 179596
+!= 428810-3-ltr-insets-ref.html about:blank
+== 428810-1a-rtl-insets.html 428810-1-rtl-insets-ref.html
+== 428810-1b-rtl-insets.html 428810-1-rtl-insets-ref.html
+fails == 428810-1c-rtl-insets.html 428810-empty-rtl-insets-ref.html # bug 179596
+fails == 428810-1d-rtl-insets.html 428810-empty-rtl-insets-ref.html # bug 179596
+!= 428810-1-rtl-insets-ref.html about:blank
+!= 428810-1-rtl-insets-ref.html 428810-1-ltr-insets-ref.html
+== 428810-2a-rtl-insets.html 428810-2-rtl-insets-ref.html
+== 428810-2b-rtl-insets.html 428810-2-rtl-insets-ref.html
+fails == 428810-2e-rtl-insets.html 428810-empty-rtl-insets-ref.html # bug 179596
+fails == 428810-2f-rtl-insets.html 428810-empty-rtl-insets-ref.html # bug 179596
+!= 428810-2-rtl-insets-ref.html about:blank
+!= 428810-2-rtl-insets-ref.html 428810-2-ltr-insets-ref.html
+== 428810-3a-rtl-insets.html 428810-3-rtl-insets-ref.html
+== 428810-3b-rtl-insets.html 428810-3-rtl-insets-ref.html
+fails == 428810-3e-rtl-insets.html 428810-empty-rtl-insets-ref.html # bug 179596
+fails == 428810-3f-rtl-insets.html 428810-empty-rtl-insets-ref.html # bug 179596
+!= 428810-3-rtl-insets-ref.html about:blank
+!= 428810-3-rtl-insets-ref.html 428810-3-ltr-insets-ref.html
== 430412-1.html 430412-1-ref.html
== 430813-1.html 430813-1-ref.html
== 430813-2.html 430813-2-ref.html
== 430813-3.html 430813-3-ref.html
== 431341-1.html 431341-1-ref.html
== 431341-2.html 431341-2-ref.html
== 431520-1.html 431520-1-ref.html
== 440112.html 440112-ref.html
@@ -1058,16 +1124,19 @@ fails == 461512-1.html 461512-1-ref.html
== 466395-2.html 466395-2-ref.html
== 467084-1.html 467084-1-ref.html
== 467084-2.html 467084-2-ref.html
== 467460-1.html 467460-1-ref.html
== 468546-1.xhtml 468546-1-ref.xhtml
== 468473-1.xul 468473-1-ref.xul
== 471356-1.html 471356-1-ref.html
== 471594-1.xhtml 471594-1-ref.html
+== 472020-1a.xul 472020-1-ref.xul
+fails == 472020-1b.xul 472020-1-ref.xul
+fails == 472020-2.xul 472020-2-ref.xul
== 472500-1.xul 472500-1-ref.xul
== 472769-1a.html 472769-1-ref.html
== 472769-1b.html 472769-1-ref.html
== 472769-2.html 472769-2-ref.html
== 472769-3.html 472769-3-ref.html
== 473847-1.xul 473847-1-ref.xul
== 474336-1.xul 474336-1-ref.xul
== 474417-1.html 474417-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/marker-attribute-01.svg
@@ -0,0 +1,21 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/licenses/publicdomain/
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>Test the 'marker' presentation attribute</title>
+ <!--
+ From https://bugzilla.mozilla.org/show_bug.cgi?id=
+
+ This test checks that the 'marker' presentation attribute places a
+ start, mid and end mark correctly.
+ -->
+ <marker id="marker" markerWidth="40" markerHeight="40" refX="20" refY="20">
+ <circle cx="20" cy="20" r="20" fill="lime"/>
+ </marker>
+ <rect width="100%" height="100%" fill="lime"/>
+ <circle cx="20" cy="20" r="18" fill="red"/>
+ <circle cx="60" cy="20" r="18" fill="red"/>
+ <circle cx="100" cy="20" r="18" fill="red"/>
+ <path d="M20,20 L60,20 L100,20" fill="none" stroke="none" marker="url(#marker)"/>
+</svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -69,16 +69,17 @@ include moz-only/reftest.list
== foreignObject-overflow-01.svg pass.svg
== getElementById-a-element-01.svg pass.svg
fails == inline-in-xul-basic-01.xul pass.svg
== image-scaling-01.svg pass.svg
== image-scaling-02.svg pass.svg
== invalid-text-01.svg pass.svg
== linearGradient-basic-01.svg pass.svg
== linearGradient-basic-02.svg pass.svg
+== marker-attribute-01.svg pass.svg
# Bug 456323
# == mask-transformed-01.svg mask-transformed-01-ref.svg
== nested-viewBox-01.svg pass.svg
== objectBoundingBox-and-pattern-01a.svg objectBoundingBox-and-pattern-01-ref.svg
== objectBoundingBox-and-pattern-01b.svg objectBoundingBox-and-pattern-01-ref.svg
== objectBoundingBox-and-pattern-01c.svg objectBoundingBox-and-pattern-01-ref.svg
# skip the next test on cocoa, since behaviour depends on the -minor- version of the 10.4 OS.
# See bugs 379610 and 432298.
new file mode 100644
--- /dev/null
+++ b/layout/reftests/table-anonymous-boxes/363326-1-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<div style="display: table; width: 500px">
+ <div style="display: table-cell">
+ <div style="float: right; width: 100px">one</div>
+ <div style="float:left; width: 100px">two</div>
+ </div>
+</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/table-anonymous-boxes/363326-1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<div style="display: table; width: 500px">
+ <div style="float: right; width: 100px">one<script>var foo = document.body.offsetWidth;</script></div>
+ <div style="float:left; width: 100px">two</div>
+</div>
+
+</body>
+</html>
--- a/layout/reftests/table-anonymous-boxes/reftest.list
+++ b/layout/reftests/table-anonymous-boxes/reftest.list
@@ -14,16 +14,17 @@ fails == 156888-1.html 156888-1-ref.html
== 293576-1.html 293576-1-ref.html
== 302113-1.html 302113-1-ref.html
== 315146-1.xhtml 315146-1-ref.xhtml
== 325543-1a.html 325543-1-ref.html
== 325543-1b.html 325543-1-ref.html
== 338735-1.html 338735-1-ref.html
== 339388-1a.html 339388-1-ref.html
== 339388-1b.html 339388-1-ref.html
+== 363326-1.html 363326-1-ref.html
== 368932-1.html 368932-1-ref.html
== 371054-1.html 371054-1-ref.html
== 372649-1.html 372649-1-ref.html
== 373379-1.html 373379-1-ref.html
== 394402-1a.html 394402-1-ref.html
== 394402-1b.html 394402-1-ref.html
== 407115-1.html 407115-1-ref.html
== 448111-1.html 448111-1-ref.html
--- a/layout/style/Makefile.in
+++ b/layout/style/Makefile.in
@@ -86,24 +86,24 @@ EXPORTS = \
nsCSSPseudoClassList.h \
nsCSSPseudoClasses.h \
nsCSSPseudoElementList.h \
nsCSSPseudoElements.h \
nsCSSRuleProcessor.h \
nsCSSStyleSheet.h \
nsCSSStruct.h \
nsCSSValue.h \
+ nsDOMCSSAttrDeclaration.h \
nsDOMCSSDeclaration.h \
nsICSSDeclaration.h \
nsICSSGroupRule.h \
nsICSSImportRule.h \
nsICSSLoader.h \
nsICSSLoaderObserver.h \
nsICSSNameSpaceRule.h \
- nsICSSOMFactory.h \
nsICSSParser.h \
nsICSSPseudoComparator.h \
nsICSSRule.h \
nsICSSRuleList.h \
nsICSSStyleRule.h \
nsICSSStyleRuleDOMWrapper.h \
nsICSSStyleSheet.h \
nsIComputedDOMStyle.h \
@@ -128,17 +128,16 @@ EXPORTS = \
$(NULL)
CPPSRCS = \
nsCSSAnonBoxes.cpp \
nsCSSDataBlock.cpp \
nsCSSDeclaration.cpp \
nsCSSKeywords.cpp \
nsCSSLoader.cpp \
- nsCSSOMFactory.cpp \
nsCSSParser.cpp \
nsCSSProps.cpp \
nsCSSPseudoClasses.cpp \
nsCSSPseudoElements.cpp \
nsCSSRule.cpp \
nsCSSRuleProcessor.cpp \
nsCSSRules.cpp \
nsCSSScanner.cpp \
deleted file mode 100644
--- a/layout/style/nsCSSOMFactory.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-// vim:cindent:ts=8:et:sw=4:
-/* ***** 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) 2001
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * L. David Baron <dbaron@dbaron.org> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* an XPCOM service for cross-module creation of DOM .style objects */
-
-#include "nsCSSOMFactory.h"
-#include "nsDOMCSSAttrDeclaration.h"
-
-nsCSSOMFactory::nsCSSOMFactory()
-{
-}
-
-nsCSSOMFactory::~nsCSSOMFactory()
-{
-}
-
-NS_IMPL_ISUPPORTS1(nsCSSOMFactory, nsICSSOMFactory)
-
-NS_IMETHODIMP
-nsCSSOMFactory::CreateDOMCSSAttributeDeclaration(nsIContent *aContent,
- nsDOMCSSDeclaration **aResult)
-{
- nsDOMCSSDeclaration *result = new nsDOMCSSAttributeDeclaration(aContent);
- if (!result) {
- *aResult = 0;
- return NS_ERROR_OUT_OF_MEMORY;
- }
- NS_ADDREF(result);
- *aResult = result;
- return NS_OK;
-}
deleted file mode 100644
--- a/layout/style/nsCSSOMFactory.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-// vim:cindent:ts=8:et:sw=4:
-/* ***** 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) 2001
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * L. David Baron <dbaron@dbaron.org> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* an XPCOM service for cross-module creation of DOM .style objects */
-
-#ifndef nsCSSOMFactory_h___
-#define nsCSSOMFactory_h___
-
-#include "nsICSSOMFactory.h"
-
-class nsCSSOMFactory : public nsICSSOMFactory {
-
-public:
-
- nsCSSOMFactory();
- virtual ~nsCSSOMFactory();
-
- NS_DECL_ISUPPORTS
-
- NS_IMETHOD CreateDOMCSSAttributeDeclaration(nsIContent *aContent,
- nsDOMCSSDeclaration **aResult);
-
-};
-
-#endif /* nsCSSOMFactory_h___ */
deleted file mode 100644
--- a/layout/style/nsICSSOMFactory.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-// vim:cindent:ts=8:et:sw=4:
-/* ***** 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) 2001
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * L. David Baron <dbaron@dbaron.org> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* an XPCOM service for cross-module creation of DOM .style objects */
-
-#ifndef nsICSSOMFactory_h___
-#define nsICSSOMFactory_h___
-
-#include "nsISupports.h"
-class nsDOMCSSDeclaration;
-class nsIContent;
-
-// f2fb43bf-81a1-4b0d-907a-893fe6727dbb
-#define NS_ICSSOMFACTORY_IID \
- { 0xf2fb43bf, 0x81a1, 0x4b0d, \
- { 0x90, 0x7a, 0x89, 0x3f, 0xe6, 0x72, 0x7d, 0xbb } }
-
-// 5fcaa2c1-7ca4-4f73-a357-93e79d709376
-#define NS_CSSOMFACTORY_CID \
- { 0x5fcaa2c1, 0x7ca4, 0x4f73, \
- {0xa3, 0x57, 0x93, 0xe7, 0x9d, 0x70, 0x93, 0x76 } }
-
-class nsICSSOMFactory : public nsISupports {
-public:
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICSSOMFACTORY_IID)
-
- NS_IMETHOD CreateDOMCSSAttributeDeclaration(nsIContent *aContent,
- nsDOMCSSDeclaration **aResult) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsICSSOMFactory, NS_ICSSOMFACTORY_IID)
-
-#endif /* nsICSSOMFactory_h___ */
--- a/modules/libreg/src/vr_stubs.c
+++ b/modules/libreg/src/vr_stubs.c
@@ -224,35 +224,32 @@ int FAR PASCAL _export WEP(int nParam)
#if defined(XP_MACOSX)
#ifdef STANDALONE_REGISTRY
extern XP_File vr_fileOpen(const char *name, const char * mode)
{
XP_File fh = NULL;
struct stat st;
-
-#ifdef STANDALONE_REGISTRY
+
errno = 0; /* reset errno (only if we're using stdio) */
-#endif
if ( name != NULL ) {
if ( stat( name, &st ) == 0 )
fh = fopen( name, XP_FILE_UPDATE_BIN );
else
{
/* should never get here! */
fh = fopen( name, XP_FILE_TRUNCATE_BIN );
}
}
return fh;
}
#endif /*STANDALONE_REGISTRY*/
-#if defined (XP_MACOSX)
extern void vr_findGlobalRegName()
{
OSErr err;
FSRef foundRef;
err = FSFindFolder(kLocalDomain, kDomainLibraryFolderType, kDontCreateFolder, &foundRef);
if (err == noErr)
{
@@ -282,74 +279,17 @@ extern void vr_findGlobalRegName()
UInt8 pathBuf[PATH_MAX];
err = FSRefMakePath(®Ref, pathBuf, sizeof(pathBuf));
if (err == noErr)
globalRegName = XP_STRDUP(pathBuf);
}
}
}
}
-#else
-extern void vr_findGlobalRegName()
-{
- FSSpec regSpec;
- OSErr err;
- short foundVRefNum;
- long foundDirID;
- int bCreate = 0;
-
- err = FindFolder(kOnSystemDisk,'pref', false, &foundVRefNum, &foundDirID);
- if (err == noErr)
- {
- err = FSMakeFSSpec(foundVRefNum, foundDirID, MAC_REG, ®Spec);
-
- if (err == -43) /* if file doesn't exist */
- {
- err = FSpCreate(®Spec, 'MOSS', 'REGS', smSystemScript);
- bCreate = 1;
- }
-
- if (err == noErr)
- {
- Handle thePath;
- short pathLen;
- err = FSpGetFullPath(®Spec, &pathLen, &thePath);
- if (err == noErr && thePath)
- {
- /* we have no idea if this moves memory, so better lock the handle */
- #if defined(STANDALONE_REGISTRY) || defined(USE_STDIO_MODES)
- HLock(thePath);
- globalRegName = (char *)XP_ALLOC(pathLen + 1);
- XP_STRNCPY(globalRegName, *thePath, pathLen);
- globalRegName[pathLen] = '\0';
- #else
- /* Since we're now using NSPR, this HAS to be a unix path! */
- const char* src;
- char* dst;
- HLock(thePath);
- globalRegName = (char*)XP_ALLOC(pathLen + 2);
- src = *(char**)thePath;
- dst = globalRegName;
- *dst++ = '/';
- while (pathLen--)
- {
- char c = *src++;
- *dst++ = (c == ':') ? '/' : c;
- }
- *dst = '\0';
- #endif
- }
- DisposeHandle(thePath);
- }
- }
-}
-#endif /* XP_MACOSX */
-
-#ifdef XP_MACOSX
extern char* vr_findVerRegName()
{
OSErr err;
FSRef foundRef;
err = FSFindFolder(kLocalDomain, kDomainLibraryFolderType, kDontCreateFolder, &foundRef);
if (err == noErr)
{
@@ -380,215 +320,26 @@ extern char* vr_findVerRegName()
err = FSRefMakePath(®Ref, pathBuf, sizeof(pathBuf));
if (err == noErr)
verRegName = XP_STRDUP(pathBuf);
}
}
}
return verRegName;
}
-#else
-extern char* vr_findVerRegName()
-{
- FSSpec regSpec;
- OSErr err;
- short foundVRefNum;
- long foundDirID;
- int bCreate = 0;
-
- /* quick exit if we have the info */