Merge mozilla-central to tracemonkey.
authorRobert Sayre <sayrer@gmail.com>
Thu, 09 Apr 2009 21:24:00 -0400
changeset 27167 ec6218a54521bc31fea8dab92f8d2793a861f211
parent 27166 162de46bc0f2ae012bf6d2934cfaca28de2a7ac0 (current diff)
parent 27149 9213aa676ae6de28995ed6c006be73593a2344e8 (diff)
child 27168 ad1270a07a315190f4431062ae4831863a386b72
push id6416
push userrsayre@mozilla.com
push dateFri, 10 Apr 2009 08:17:12 +0000
treeherdermozilla-central@99d61ba5f125 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.2a1pre
Merge mozilla-central to tracemonkey.
dom/interfaces/base/nsIDOMPkcs11.idl
gfx/public/nsDeviceContext.h
gfx/src/nsDeviceContext.cpp
gfx/src/nsRenderingContextImpl.h
gfx/src/shared/nsRenderingContextImpl.cpp
layout/style/nsCSSOMFactory.cpp
layout/style/nsCSSOMFactory.h
layout/style/nsICSSOMFactory.h
--- 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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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;">
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</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(&regRef, 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, &regSpec);
-
-        if (err == -43) /* if file doesn't exist */
-        {
-            err = FSpCreate(&regSpec, 'MOSS', 'REGS', smSystemScript);
-            bCreate = 1;
-        }
-
-        if (err == noErr)
-        {
-            Handle thePath;
-            short pathLen;
-            err = FSpGetFullPath(&regSpec, &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(&regRef, 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 */