mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to tracemonkey.
This commit is contained in:
commit
c05dbc60ec
@ -217,7 +217,6 @@ ACCESSIBILITY_ATOM(aria_busy, "aria-busy")
|
|||||||
ACCESSIBILITY_ATOM(aria_checked, "aria-checked")
|
ACCESSIBILITY_ATOM(aria_checked, "aria-checked")
|
||||||
ACCESSIBILITY_ATOM(aria_controls, "aria-controls")
|
ACCESSIBILITY_ATOM(aria_controls, "aria-controls")
|
||||||
ACCESSIBILITY_ATOM(aria_describedby, "aria-describedby")
|
ACCESSIBILITY_ATOM(aria_describedby, "aria-describedby")
|
||||||
ACCESSIBILITY_ATOM(aria_droppable, "aria-droppable")
|
|
||||||
ACCESSIBILITY_ATOM(aria_disabled, "aria-disabled")
|
ACCESSIBILITY_ATOM(aria_disabled, "aria-disabled")
|
||||||
ACCESSIBILITY_ATOM(aria_dropeffect, "aria-dropeffect")
|
ACCESSIBILITY_ATOM(aria_dropeffect, "aria-dropeffect")
|
||||||
ACCESSIBILITY_ATOM(aria_expanded, "aria-expanded")
|
ACCESSIBILITY_ATOM(aria_expanded, "aria-expanded")
|
||||||
|
@ -1131,8 +1131,7 @@ nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID
|
|||||||
|
|
||||||
if (aAttribute == nsAccessibilityAtoms::role ||
|
if (aAttribute == nsAccessibilityAtoms::role ||
|
||||||
aAttribute == nsAccessibilityAtoms::href ||
|
aAttribute == nsAccessibilityAtoms::href ||
|
||||||
aAttribute == nsAccessibilityAtoms::onclick ||
|
aAttribute == nsAccessibilityAtoms::onclick) {
|
||||||
aAttribute == nsAccessibilityAtoms::aria_droppable) {
|
|
||||||
// Not worth the expense to ensure which namespace these are in
|
// 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
|
// 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
|
// in the wrong namespace or an element that doesn't support it
|
||||||
|
@ -96,6 +96,12 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Bug 483950 - Hide domain name in status bar pending removal */
|
||||||
|
#security-button > label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* ::::: Fullscreen pseudo-toolbar ::::: */
|
/* ::::: Fullscreen pseudo-toolbar ::::: */
|
||||||
#fullscr-toggler {
|
#fullscr-toggler {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -901,10 +901,6 @@ var PlacesSearchBox = {
|
|||||||
//scopeBtn.label = PlacesOrganizer._places.selectedNode.title;
|
//scopeBtn.label = PlacesOrganizer._places.selectedNode.title;
|
||||||
break;
|
break;
|
||||||
case "bookmarks":
|
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);
|
content.applyFilter(filterString, this.folders);
|
||||||
break;
|
break;
|
||||||
case "history":
|
case "history":
|
||||||
@ -912,6 +908,8 @@ var PlacesSearchBox = {
|
|||||||
var query = PlacesUtils.history.getNewQuery();
|
var query = PlacesUtils.history.getNewQuery();
|
||||||
query.searchTerms = filterString;
|
query.searchTerms = filterString;
|
||||||
var options = currentOptions.clone();
|
var options = currentOptions.clone();
|
||||||
|
// Make sure we're getting uri results.
|
||||||
|
options.resultType = currentOptions.RESULT_TYPE_URI;
|
||||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
|
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
|
||||||
content.load([query], options);
|
content.load([query], options);
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,14 @@
|
|||||||
var queryNode = asQuery(this.getResultNode());
|
var queryNode = asQuery(this.getResultNode());
|
||||||
var options = queryNode.queryOptions.clone();
|
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();
|
var query = PlacesUtils.history.getNewQuery();
|
||||||
query.searchTerms = filterString;
|
query.searchTerms = filterString;
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@
|
|||||||
* 6. if folder scope was clicked, searches again and ensures folder scope
|
* 6. if folder scope was clicked, searches again and ensures folder scope
|
||||||
* remains selected.
|
* remains selected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const TEST_URL = "http://dummy.mozilla.org/";
|
||||||
|
|
||||||
// Add your tests here. Each is a function that's called by testHelper().
|
// Add your tests here. Each is a function that's called by testHelper().
|
||||||
var testCases = [
|
var testCases = [
|
||||||
@ -66,7 +68,7 @@ var testCases = [
|
|||||||
// All Bookmarks
|
// All Bookmarks
|
||||||
function () {
|
function () {
|
||||||
var defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
|
var defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
|
||||||
search(PlacesUIUtils.allBookmarksFolderId, "dummy search", defScope);
|
search(PlacesUIUtils.allBookmarksFolderId, "dummy", defScope);
|
||||||
is(selectScope("scopeBarFolder"), false,
|
is(selectScope("scopeBarFolder"), false,
|
||||||
"Folder scope should be disabled for All Bookmarks");
|
"Folder scope should be disabled for All Bookmarks");
|
||||||
resetSearch(defScope);
|
resetSearch(defScope);
|
||||||
@ -75,7 +77,7 @@ var testCases = [
|
|||||||
// History
|
// History
|
||||||
function () {
|
function () {
|
||||||
defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
|
defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
|
||||||
search(PlacesUIUtils.leftPaneQueries["History"], "dummy search", defScope);
|
search(PlacesUIUtils.leftPaneQueries["History"], "dummy", defScope);
|
||||||
is(selectScope("scopeBarFolder"), false,
|
is(selectScope("scopeBarFolder"), false,
|
||||||
"Folder scope should be disabled for History");
|
"Folder scope should be disabled for History");
|
||||||
resetSearch(defScope);
|
resetSearch(defScope);
|
||||||
@ -84,13 +86,13 @@ var testCases = [
|
|||||||
// Toolbar folder
|
// Toolbar folder
|
||||||
function () {
|
function () {
|
||||||
defScope = getDefaultScope(bmsvc.toolbarFolder);
|
defScope = getDefaultScope(bmsvc.toolbarFolder);
|
||||||
search(bmsvc.toolbarFolder, "dummy search", defScope);
|
search(bmsvc.toolbarFolder, "dummy", defScope);
|
||||||
is(selectScope("scopeBarFolder"), true,
|
is(selectScope("scopeBarFolder"), true,
|
||||||
"Folder scope should be enabled for toolbar folder");
|
"Folder scope should be enabled for toolbar folder");
|
||||||
// Ensure that folder scope is still selected after resetting and searching
|
// Ensure that folder scope is still selected after resetting and searching
|
||||||
// again.
|
// again.
|
||||||
resetSearch("scopeBarFolder");
|
resetSearch("scopeBarFolder");
|
||||||
search(bmsvc.toolbarFolder, "dummy search", "scopeBarFolder");
|
search(bmsvc.toolbarFolder, "dummy", "scopeBarFolder");
|
||||||
},
|
},
|
||||||
|
|
||||||
// A regular non-root subfolder
|
// A regular non-root subfolder
|
||||||
@ -99,13 +101,13 @@ var testCases = [
|
|||||||
"dummy folder",
|
"dummy folder",
|
||||||
bmsvc.DEFAULT_INDEX);
|
bmsvc.DEFAULT_INDEX);
|
||||||
defScope = getDefaultScope(folderId);
|
defScope = getDefaultScope(folderId);
|
||||||
search(folderId, "dummy search", defScope);
|
search(folderId, "dummy", defScope);
|
||||||
is(selectScope("scopeBarFolder"), true,
|
is(selectScope("scopeBarFolder"), true,
|
||||||
"Folder scope should be enabled for regular subfolder");
|
"Folder scope should be enabled for regular subfolder");
|
||||||
// Ensure that folder scope is still selected after resetting and searching
|
// Ensure that folder scope is still selected after resetting and searching
|
||||||
// again.
|
// again.
|
||||||
resetSearch("scopeBarFolder");
|
resetSearch("scopeBarFolder");
|
||||||
search(folderId, "dummy search", "scopeBarFolder");
|
search(folderId, "dummy", "scopeBarFolder");
|
||||||
bmsvc.removeItem(folderId);
|
bmsvc.removeItem(folderId);
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -219,6 +221,15 @@ function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
|
|||||||
"Content tree's searchTerms should be text in search box");
|
"Content tree's searchTerms should be text in search box");
|
||||||
is(doc.getElementById("searchModifiers").hidden, false,
|
is(doc.getElementById("searchModifiers").hidden, false,
|
||||||
"Scope bar should not be hidden after searching");
|
"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 {
|
else {
|
||||||
is(query.hasSearchTerms, false,
|
is(query.hasSearchTerms, false,
|
||||||
@ -260,6 +271,12 @@ function testHelper(aLibraryWin) {
|
|||||||
libraryWin = aLibraryWin;
|
libraryWin = aLibraryWin;
|
||||||
testCases.forEach(function (aTest) aTest());
|
testCases.forEach(function (aTest) aTest());
|
||||||
aLibraryWin.close();
|
aLibraryWin.close();
|
||||||
|
|
||||||
|
// Cleanup.
|
||||||
|
PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL), ["dummyTag"]);
|
||||||
|
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.unfiledBookmarksFolder);
|
||||||
|
PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,6 +285,18 @@ function testHelper(aLibraryWin) {
|
|||||||
function test() {
|
function test() {
|
||||||
waitForExplicitFinish();
|
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"].
|
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||||
getService(Ci.nsIWindowWatcher);
|
getService(Ci.nsIWindowWatcher);
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
* locale/browser/netError.dtd (%chrome/overrides/netError.dtd)
|
* locale/browser/netError.dtd (%chrome/overrides/netError.dtd)
|
||||||
* locale/browser/appstrings.properties (%chrome/overrides/appstrings.properties)
|
* locale/browser/appstrings.properties (%chrome/overrides/appstrings.properties)
|
||||||
* locale/browser/downloads/settingsChange.dtd (%chrome/overrides/settingsChange.dtd)
|
* 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://global/locale/appstrings.properties chrome://browser/locale/appstrings.properties
|
||||||
% override chrome://mozapps/locale/downloads/settingsChange.dtd chrome://browser/locale/downloads/settingsChange.dtd
|
% override chrome://mozapps/locale/downloads/settingsChange.dtd chrome://browser/locale/downloads/settingsChange.dtd
|
||||||
#ifdef MOZ_USE_GENERIC_BRANDING
|
#ifdef MOZ_USE_GENERIC_BRANDING
|
||||||
|
@ -1293,6 +1293,7 @@ tabpanels {
|
|||||||
.tabs-closebutton {
|
.tabs-closebutton {
|
||||||
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
|
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
|
||||||
border: none;
|
border: none;
|
||||||
|
margin-bottom: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs-closebutton > .toolbarbutton-icon {
|
.tabs-closebutton > .toolbarbutton-icon {
|
||||||
|
@ -247,6 +247,7 @@ user_pref("security.default_personal_cert", "Select Automatically"); // Need to
|
|||||||
user_pref("network.http.prompt-temp-redirect", false);
|
user_pref("network.http.prompt-temp-redirect", false);
|
||||||
user_pref("svg.smil.enabled", true); // Needed for SMIL mochitests until bug 482402 lands
|
user_pref("svg.smil.enabled", true); // Needed for SMIL mochitests until bug 482402 lands
|
||||||
user_pref("media.cache_size", 100);
|
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
|
user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
|
||||||
"""
|
"""
|
||||||
|
368
build/package/wince/make_wince_cab.py
Normal file
368
build/package/wince/make_wince_cab.py
Normal file
@ -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()
|
@ -72,6 +72,7 @@ LIBXUL_SDK = @LIBXUL_SDK@
|
|||||||
L10NBASEDIR = @L10NBASEDIR@
|
L10NBASEDIR = @L10NBASEDIR@
|
||||||
|
|
||||||
LIBXUL_DIST = @LIBXUL_DIST@
|
LIBXUL_DIST = @LIBXUL_DIST@
|
||||||
|
SYSTEM_LIBXUL = @SYSTEM_LIBXUL@
|
||||||
|
|
||||||
XULRUNNER_STUB_NAME = @XULRUNNER_STUB_NAME@
|
XULRUNNER_STUB_NAME = @XULRUNNER_STUB_NAME@
|
||||||
|
|
||||||
|
@ -1832,8 +1832,6 @@ case "$target" in
|
|||||||
# logging code in nsObjCExceptions.h. Currently we only use that in debug
|
# logging code in nsObjCExceptions.h. Currently we only use that in debug
|
||||||
# builds.
|
# builds.
|
||||||
MOZ_DEBUG_LDFLAGS="$MOZ_DEBUG_LDFLAGS -framework ExceptionHandling"
|
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 DTrace and -dead_strip don't interact well. See bug 403132.
|
||||||
dnl ===================================================================
|
dnl ===================================================================
|
||||||
|
@ -134,7 +134,14 @@ nsAsyncInstantiateEvent::Run()
|
|||||||
// Also make sure that we still refer to the same data.
|
// Also make sure that we still refer to the same data.
|
||||||
nsIObjectFrame* frame = mContent->
|
nsIObjectFrame* frame = mContent->
|
||||||
GetExistingFrame(nsObjectLoadingContent::eFlushContent);
|
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->mURI == mURI &&
|
||||||
mContent->mContentType.Equals(mContentType)) {
|
mContent->mContentType.Equals(mContentType)) {
|
||||||
if (LOG_ENABLED()) {
|
if (LOG_ENABLED()) {
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
#include "nsGenericElement.h"
|
#include "nsGenericElement.h"
|
||||||
#include "nsMutationEvent.h"
|
#include "nsMutationEvent.h"
|
||||||
#include "nsDOMCSSDeclaration.h"
|
#include "nsDOMCSSDeclaration.h"
|
||||||
#include "nsICSSOMFactory.h"
|
#include "nsDOMCSSAttrDeclaration.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsICSSStyleRule.h"
|
#include "nsICSSStyleRule.h"
|
||||||
@ -167,9 +167,6 @@ nsStyledElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// Others and helpers
|
// Others and helpers
|
||||||
|
|
||||||
static nsICSSOMFactory* gCSSOMFactory = nsnull;
|
|
||||||
static NS_DEFINE_CID(kCSSOMFactoryCID, NS_CSSOMFACTORY_CID);
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsStyledElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
nsStyledElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
||||||
{
|
{
|
||||||
@ -180,15 +177,8 @@ nsStyledElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
|||||||
// Just in case...
|
// Just in case...
|
||||||
ReparseStyleAttribute(PR_TRUE);
|
ReparseStyleAttribute(PR_TRUE);
|
||||||
|
|
||||||
nsresult rv;
|
slots->mStyle = new nsDOMCSSAttributeDeclaration(this);
|
||||||
if (!gCSSOMFactory) {
|
NS_ENSURE_TRUE(slots->mStyle, NS_ERROR_OUT_OF_MEMORY);
|
||||||
rv = CallGetService(kCSSOMFactoryCID, &gCSSOMFactory);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = gCSSOMFactory->CreateDOMCSSAttributeDeclaration(this,
|
|
||||||
getter_AddRefs(slots->mStyle));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
SetFlags(NODE_MAY_HAVE_STYLE);
|
SetFlags(NODE_MAY_HAVE_STYLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,10 +255,3 @@ nsStyledElement::ParseStyleAttribute(nsIContent* aContent,
|
|||||||
|
|
||||||
aResult.SetTo(aValue);
|
aResult.SetTo(aValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
nsStyledElement::Shutdown()
|
|
||||||
{
|
|
||||||
NS_IF_RELEASE(gCSSOMFactory);
|
|
||||||
}
|
|
||||||
|
@ -89,8 +89,6 @@ public:
|
|||||||
nsAttrValue& aResult,
|
nsAttrValue& aResult,
|
||||||
PRBool aForceInDataDoc);
|
PRBool aForceInDataDoc);
|
||||||
|
|
||||||
static void Shutdown();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
|
virtual PRBool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
|
||||||
|
@ -39,10 +39,10 @@
|
|||||||
#define nsICanvasElement_h___
|
#define nsICanvasElement_h___
|
||||||
|
|
||||||
#include "nsISupports.h"
|
#include "nsISupports.h"
|
||||||
#include "nsRect.h"
|
|
||||||
|
|
||||||
class gfxContext;
|
class gfxContext;
|
||||||
class nsIFrame;
|
class nsIFrame;
|
||||||
|
struct gfxRect;
|
||||||
|
|
||||||
// {C234660C-BD06-493e-8583-939A5A158B37}
|
// {C234660C-BD06-493e-8583-939A5A158B37}
|
||||||
#define NS_ICANVASELEMENT_IID \
|
#define NS_ICANVASELEMENT_IID \
|
||||||
@ -91,9 +91,9 @@ public:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Ask the canvas frame to invalidate a portion of the frame; damageRect
|
* 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
|
* Get the number of contexts in this canvas, and request a context at
|
||||||
|
@ -318,6 +318,8 @@ public:
|
|||||||
virtual ~nsCanvasRenderingContext2D();
|
virtual ~nsCanvasRenderingContext2D();
|
||||||
|
|
||||||
nsresult Redraw();
|
nsresult Redraw();
|
||||||
|
// this rect is in CSS pixels
|
||||||
|
nsresult Redraw(const gfxRect& r);
|
||||||
|
|
||||||
// nsICanvasRenderingContextInternal
|
// nsICanvasRenderingContextInternal
|
||||||
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
|
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
|
||||||
@ -889,6 +891,20 @@ nsCanvasRenderingContext2D::Redraw()
|
|||||||
return NS_OK;
|
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
|
NS_IMETHODIMP
|
||||||
nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
|
nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
|
||||||
{
|
{
|
||||||
@ -3397,7 +3413,9 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Flush layout updates
|
// Flush layout updates
|
||||||
if (!(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH))
|
PRBool skipFlush =
|
||||||
|
(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH) != 0;
|
||||||
|
if (!skipFlush)
|
||||||
FlushLayoutForTree(aWindow);
|
FlushLayoutForTree(aWindow);
|
||||||
|
|
||||||
nsCOMPtr<nsPresContext> presContext;
|
nsCOMPtr<nsPresContext> presContext;
|
||||||
@ -3427,13 +3445,23 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY
|
|||||||
if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_CARET) {
|
if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_CARET) {
|
||||||
renderDocFlags |= nsIPresShell::RENDER_CARET;
|
renderDocFlags |= nsIPresShell::RENDER_CARET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool oldDisableValue = nsLayoutUtils::sDisableGetUsedXAssertions;
|
||||||
|
nsLayoutUtils::sDisableGetUsedXAssertions = oldDisableValue || skipFlush;
|
||||||
presShell->RenderDocument(r, renderDocFlags, bgColor, mThebes);
|
presShell->RenderDocument(r, renderDocFlags, bgColor, mThebes);
|
||||||
|
nsLayoutUtils::sDisableGetUsedXAssertions = oldDisableValue;
|
||||||
|
|
||||||
// get rid of the pattern surface ref, just in case
|
// get rid of the pattern surface ref, just in case
|
||||||
mThebes->SetColor(gfxRGBA(1,1,1,1));
|
mThebes->SetColor(gfxRGBA(1,1,1,1));
|
||||||
DirtyAllStyles();
|
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;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,6 @@
|
|||||||
#include "nsIDOMEvent.h"
|
#include "nsIDOMEvent.h"
|
||||||
#include "nsIDOMNSEvent.h"
|
#include "nsIDOMNSEvent.h"
|
||||||
#include "nsDOMCSSDeclaration.h"
|
#include "nsDOMCSSDeclaration.h"
|
||||||
#include "nsICSSOMFactory.h"
|
|
||||||
#include "nsITextControlFrame.h"
|
#include "nsITextControlFrame.h"
|
||||||
#include "nsIForm.h"
|
#include "nsIForm.h"
|
||||||
#include "nsIFormControl.h"
|
#include "nsIFormControl.h"
|
||||||
|
@ -92,7 +92,7 @@ public:
|
|||||||
virtual PRBool IsWriteOnly();
|
virtual PRBool IsWriteOnly();
|
||||||
virtual void SetWriteOnly();
|
virtual void SetWriteOnly();
|
||||||
NS_IMETHOD InvalidateFrame ();
|
NS_IMETHOD InvalidateFrame ();
|
||||||
NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect);
|
NS_IMETHOD InvalidateFrameSubrect (const gfxRect& damageRect);
|
||||||
virtual PRInt32 CountContexts();
|
virtual PRInt32 CountContexts();
|
||||||
virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index);
|
virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index);
|
||||||
virtual PRBool GetIsOpaque();
|
virtual PRBool GetIsOpaque();
|
||||||
@ -555,11 +555,29 @@ nsHTMLCanvasElement::InvalidateFrame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsHTMLCanvasElement::InvalidateFrameSubrect(const nsRect& damageRect)
|
nsHTMLCanvasElement::InvalidateFrameSubrect(const gfxRect& damageRect)
|
||||||
{
|
{
|
||||||
nsIFrame *frame = GetPrimaryFrame(Flush_Frames);
|
nsIFrame *frame = GetPrimaryFrame(Flush_Frames);
|
||||||
if (frame) {
|
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;
|
return NS_OK;
|
||||||
|
@ -826,6 +826,7 @@ nsSVGElement::sViewportsMap[] = {
|
|||||||
// PresentationAttributes-Makers
|
// PresentationAttributes-Makers
|
||||||
/* static */ const nsGenericElement::MappedAttributeEntry
|
/* static */ const nsGenericElement::MappedAttributeEntry
|
||||||
nsSVGElement::sMarkersMap[] = {
|
nsSVGElement::sMarkersMap[] = {
|
||||||
|
{ &nsGkAtoms::marker },
|
||||||
{ &nsGkAtoms::marker_end },
|
{ &nsGkAtoms::marker_end },
|
||||||
{ &nsGkAtoms::marker_mid },
|
{ &nsGkAtoms::marker_mid },
|
||||||
{ &nsGkAtoms::marker_start },
|
{ &nsGkAtoms::marker_start },
|
||||||
|
@ -1422,51 +1422,105 @@ nsBindingManager::GetNestedSingleInsertionPoint(nsIContent* aParent,
|
|||||||
return insertionElement;
|
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
|
void
|
||||||
nsBindingManager::ContentAppended(nsIDocument* aDocument,
|
nsBindingManager::ContentAppended(nsIDocument* aDocument,
|
||||||
nsIContent* aContainer,
|
nsIContent* aContainer,
|
||||||
PRInt32 aNewIndexInContainer)
|
PRInt32 aNewIndexInContainer)
|
||||||
{
|
{
|
||||||
// XXX This is hacked and not quite correct. See below.
|
|
||||||
if (aNewIndexInContainer != -1 &&
|
if (aNewIndexInContainer != -1 &&
|
||||||
(mContentListTable.ops || mAnonymousNodesTable.ops)) {
|
(mContentListTable.ops || mAnonymousNodesTable.ops)) {
|
||||||
// It's not anonymous.
|
// It's not anonymous.
|
||||||
|
NS_ASSERTION(aNewIndexInContainer >= 0, "Bogus index");
|
||||||
|
|
||||||
PRBool multiple;
|
PRBool multiple;
|
||||||
nsIContent* ins = GetNestedSingleInsertionPoint(aContainer, &multiple);
|
nsIContent* ins = GetNestedSingleInsertionPoint(aContainer, &multiple);
|
||||||
|
|
||||||
if (multiple) {
|
if (multiple) {
|
||||||
// Do each kid individually
|
// Do each kid individually
|
||||||
PRInt32 childCount = aContainer->GetChildCount();
|
PRInt32 childCount = aContainer->GetChildCount();
|
||||||
NS_ASSERTION(aNewIndexInContainer >= 0, "Bogus index");
|
|
||||||
for (PRInt32 idx = aNewIndexInContainer; idx < childCount; ++idx) {
|
for (PRInt32 idx = aNewIndexInContainer; idx < childCount; ++idx) {
|
||||||
HandleChildInsertion(aContainer, aContainer->GetChildAt(idx),
|
HandleChildInsertion(aContainer, aContainer->GetChildAt(idx),
|
||||||
idx, PR_TRUE);
|
idx, PR_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ins) {
|
else if (ins) {
|
||||||
PRBool isAnonymousContentList;
|
PRInt32 insertionIndex;
|
||||||
nsCOMPtr<nsIDOMNodeList> nodeList =
|
nsXBLInsertionPoint* point =
|
||||||
GetXBLChildNodesInternal(ins, &isAnonymousContentList);
|
FindInsertionPointAndIndex(aContainer, ins, aNewIndexInContainer,
|
||||||
|
PR_TRUE, &insertionIndex);
|
||||||
if (nodeList && isAnonymousContentList) {
|
if (point) {
|
||||||
// Find the one non-pseudo-insertion point and just add ourselves.
|
PRInt32 childCount = aContainer->GetChildCount();
|
||||||
nsAnonymousContentList* contentList =
|
for (PRInt32 j = aNewIndexInContainer; j < childCount;
|
||||||
static_cast<nsAnonymousContentList*>(nodeList.get());
|
j++, insertionIndex++) {
|
||||||
|
nsIContent* child = aContainer->GetChildAt(j);
|
||||||
PRInt32 count = contentList->GetInsertionPointCount();
|
point->InsertChildAt(insertionIndex, child);
|
||||||
for (PRInt32 i = 0; i < count; i++) {
|
SetInsertionParent(child, ins);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1479,7 +1533,6 @@ nsBindingManager::ContentInserted(nsIDocument* aDocument,
|
|||||||
nsIContent* aChild,
|
nsIContent* aChild,
|
||||||
PRInt32 aIndexInContainer)
|
PRInt32 aIndexInContainer)
|
||||||
{
|
{
|
||||||
// XXX This is hacked just to make menus work again.
|
|
||||||
if (aIndexInContainer != -1 &&
|
if (aIndexInContainer != -1 &&
|
||||||
(mContentListTable.ops || mAnonymousNodesTable.ops)) {
|
(mContentListTable.ops || mAnonymousNodesTable.ops)) {
|
||||||
// It's not anonymous.
|
// It's not anonymous.
|
||||||
@ -1640,61 +1693,13 @@ nsBindingManager::HandleChildInsertion(nsIContent* aContainer,
|
|||||||
nsIContent* ins = GetNestedInsertionPoint(aContainer, aChild);
|
nsIContent* ins = GetNestedInsertionPoint(aContainer, aChild);
|
||||||
|
|
||||||
if (ins) {
|
if (ins) {
|
||||||
PRBool isAnonymousContentList;
|
PRInt32 insertionIndex;
|
||||||
nsCOMPtr<nsIDOMNodeList> nodeList =
|
nsXBLInsertionPoint* point =
|
||||||
GetXBLChildNodesInternal(ins, &isAnonymousContentList);
|
FindInsertionPointAndIndex(aContainer, ins, aIndexInContainer, aAppend,
|
||||||
|
&insertionIndex);
|
||||||
if (nodeList && isAnonymousContentList) {
|
if (point) {
|
||||||
// Find a non-pseudo-insertion point and just jam ourselves in. This is
|
point->InsertChildAt(insertionIndex, aChild);
|
||||||
// not 100% correct, since there might be multiple insertion points under
|
SetInsertionParent(aChild, ins);
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +242,19 @@ protected:
|
|||||||
void HandleChildInsertion(nsIContent* aContainer, nsIContent* aChild,
|
void HandleChildInsertion(nsIContent* aContainer, nsIContent* aChild,
|
||||||
PRUint32 aIndexInContainer, PRBool aAppend);
|
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
|
// Same as ProcessAttachedQueue, but also nulls out
|
||||||
// mProcessAttachedQueueEvent
|
// mProcessAttachedQueueEvent
|
||||||
void DoProcessAttachedQueue();
|
void DoProcessAttachedQueue();
|
||||||
|
@ -103,6 +103,7 @@
|
|||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
#include "nsICSSStyleRule.h"
|
#include "nsICSSStyleRule.h"
|
||||||
#include "nsIStyleSheet.h"
|
#include "nsIStyleSheet.h"
|
||||||
|
#include "nsDOMCSSAttrDeclaration.h"
|
||||||
#include "nsIURL.h"
|
#include "nsIURL.h"
|
||||||
#include "nsIViewManager.h"
|
#include "nsIViewManager.h"
|
||||||
#include "nsIWidget.h"
|
#include "nsIWidget.h"
|
||||||
@ -159,7 +160,6 @@
|
|||||||
// Global object maintenance
|
// Global object maintenance
|
||||||
nsICSSParser* nsXULPrototypeElement::sCSSParser = nsnull;
|
nsICSSParser* nsXULPrototypeElement::sCSSParser = nsnull;
|
||||||
nsIXBLService * nsXULElement::gXBLService = nsnull;
|
nsIXBLService * nsXULElement::gXBLService = nsnull;
|
||||||
nsICSSOMFactory* nsXULElement::gCSSOMFactory = nsnull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tearoff class for nsXULElement to implement nsIScriptEventHandlerOwner.
|
* A tearoff class for nsXULElement to implement nsIScriptEventHandlerOwner.
|
||||||
@ -191,7 +191,6 @@ private:
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
static NS_DEFINE_CID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
|
static NS_DEFINE_CID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
|
||||||
static NS_DEFINE_CID(kCSSOMFactoryCID, NS_CSSOMFACTORY_CID);
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
@ -1929,14 +1928,8 @@ nsXULElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
|||||||
NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
if (!slots->mStyle) {
|
if (!slots->mStyle) {
|
||||||
if (!gCSSOMFactory) {
|
slots->mStyle = new nsDOMCSSAttributeDeclaration(this);
|
||||||
rv = CallGetService(kCSSOMFactoryCID, &gCSSOMFactory);
|
NS_ENSURE_TRUE(slots->mStyle, NS_ERROR_OUT_OF_MEMORY);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = gCSSOMFactory->CreateDOMCSSAttributeDeclaration(this,
|
|
||||||
getter_AddRefs(slots->mStyle));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
SetFlags(NODE_MAY_HAVE_STYLE);
|
SetFlags(NODE_MAY_HAVE_STYLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,6 @@
|
|||||||
#include "nsIXULTemplateBuilder.h"
|
#include "nsIXULTemplateBuilder.h"
|
||||||
#include "nsIBoxObject.h"
|
#include "nsIBoxObject.h"
|
||||||
#include "nsIXBLService.h"
|
#include "nsIXBLService.h"
|
||||||
#include "nsICSSOMFactory.h"
|
|
||||||
#include "nsLayoutCID.h"
|
#include "nsLayoutCID.h"
|
||||||
#include "nsAttrAndChildArray.h"
|
#include "nsAttrAndChildArray.h"
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
@ -490,13 +489,11 @@ public:
|
|||||||
}
|
}
|
||||||
static void ReleaseGlobals() {
|
static void ReleaseGlobals() {
|
||||||
NS_IF_RELEASE(gXBLService);
|
NS_IF_RELEASE(gXBLService);
|
||||||
NS_IF_RELEASE(gCSSOMFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// pseudo-constants
|
// pseudo-constants
|
||||||
static nsIXBLService* gXBLService;
|
static nsIXBLService* gXBLService;
|
||||||
static nsICSSOMFactory* gCSSOMFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static nsresult
|
static nsresult
|
||||||
|
@ -752,29 +752,6 @@ nsHTMLEditor::GetBlockNodeParent(nsIDOMNode *aNode)
|
|||||||
return p;
|
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
|
// GetBlockSection: return leftmost/rightmost nodes in aChild's block
|
||||||
//
|
//
|
||||||
@ -2175,117 +2152,6 @@ nsHTMLEditor::SetParagraphFormat(const nsAString& aParagraphFormat)
|
|||||||
return InsertBasicBlock(tag);
|
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
|
NS_IMETHODIMP
|
||||||
nsHTMLEditor::GetParagraphState(PRBool *aMixed, nsAString &outFormat)
|
nsHTMLEditor::GetParagraphState(PRBool *aMixed, nsAString &outFormat)
|
||||||
{
|
{
|
||||||
@ -2332,20 +2198,6 @@ nsHTMLEditor::GetHighlightColorState(PRBool *aMixed, nsAString &aOutColor)
|
|||||||
return res;
|
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
|
nsresult
|
||||||
nsHTMLEditor::GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor, PRBool aBlockLevel)
|
nsHTMLEditor::GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor, PRBool aBlockLevel)
|
||||||
{
|
{
|
||||||
@ -4425,44 +4277,6 @@ nsHTMLEditor::IsRootTag(nsString &aTag, PRBool &aIsTag)
|
|||||||
return NS_OK;
|
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
|
// GetEnclosingTable: find ancestor who is a table, if any
|
||||||
//
|
//
|
||||||
@ -4587,50 +4401,6 @@ nsHTMLEditor::CollapseAdjacentTextNodes(nsIDOMRange *aInRange)
|
|||||||
return result;
|
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
|
NS_IMETHODIMP
|
||||||
nsHTMLEditor::SetSelectionAtDocumentStart(nsISelection *aSelection)
|
nsHTMLEditor::SetSelectionAtDocumentStart(nsISelection *aSelection)
|
||||||
{
|
{
|
||||||
|
@ -172,14 +172,9 @@ public:
|
|||||||
|
|
||||||
NS_IMETHOD LoadHTML(const nsAString &aInputString);
|
NS_IMETHOD LoadHTML(const nsAString &aInputString);
|
||||||
|
|
||||||
NS_IMETHOD GetParentBlockTags(nsTArray<nsString> *aTagList, PRBool aGetLists);
|
|
||||||
|
|
||||||
nsresult GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor,
|
nsresult GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor,
|
||||||
PRBool aBlockLevel);
|
PRBool aBlockLevel);
|
||||||
NS_IMETHOD GetHTMLBackgroundColorState(PRBool *aMixed, nsAString &outColor);
|
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 -------------- */
|
/* ------------ nsIEditorStyleSheets methods -------------- */
|
||||||
|
|
||||||
@ -231,8 +226,6 @@ public:
|
|||||||
PRBool* aIsSelected);
|
PRBool* aIsSelected);
|
||||||
NS_IMETHOD GetFirstRow(nsIDOMElement* aTableElement, nsIDOMNode** aRowNode);
|
NS_IMETHOD GetFirstRow(nsIDOMElement* aTableElement, nsIDOMNode** aRowNode);
|
||||||
NS_IMETHOD GetNextRow(nsIDOMNode* aCurrentRowNode, 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 GetLastCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode);
|
||||||
|
|
||||||
NS_IMETHOD SetSelectionAfterTableEdit(nsIDOMElement* aTable, PRInt32 aRow, PRInt32 aCol,
|
NS_IMETHOD SetSelectionAfterTableEdit(nsIDOMElement* aTable, PRInt32 aRow, PRInt32 aCol,
|
||||||
@ -265,7 +258,6 @@ public:
|
|||||||
|
|
||||||
/* ------------ Block methods moved from nsEditor -------------- */
|
/* ------------ Block methods moved from nsEditor -------------- */
|
||||||
static nsCOMPtr<nsIDOMNode> GetBlockNodeParent(nsIDOMNode *aNode);
|
static nsCOMPtr<nsIDOMNode> GetBlockNodeParent(nsIDOMNode *aNode);
|
||||||
static PRBool HasSameBlockNodeParent(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
|
|
||||||
/** Determines the bounding nodes for the block section containing aNode.
|
/** Determines the bounding nodes for the block section containing aNode.
|
||||||
* The calculation is based on some nodes intrinsically being block elements
|
* The calculation is based on some nodes intrinsically being block elements
|
||||||
* acording to HTML. Style sheets are not considered in this calculation.
|
* acording to HTML. Style sheets are not considered in this calculation.
|
||||||
@ -393,14 +385,6 @@ public:
|
|||||||
PRInt32 &aStartOffset,
|
PRInt32 &aStartOffset,
|
||||||
PRInt32 &aEndOffset);
|
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
|
// Use this to assure that selection is set after attribute nodes when
|
||||||
// trying to collapse selection at begining of a block node
|
// trying to collapse selection at begining of a block node
|
||||||
// e.g., when setting at beginning of a table cell
|
// e.g., when setting at beginning of a table cell
|
||||||
@ -426,7 +410,6 @@ public:
|
|||||||
PRBool *aSeenBR);
|
PRBool *aSeenBR);
|
||||||
|
|
||||||
// Stylesheet-related methods that aren't part of nsIEditorStyleSheets.
|
// Stylesheet-related methods that aren't part of nsIEditorStyleSheets.
|
||||||
nsresult AddCSSStyleSheet(nsICSSStyleSheet* aSheet);
|
|
||||||
nsresult GetCSSLoader(const nsAString& aURL, nsICSSLoader** aCSSLoader);
|
nsresult GetCSSLoader(const nsAString& aURL, nsICSSLoader** aCSSLoader);
|
||||||
|
|
||||||
// Returns TRUE if sheet was loaded, false if it wasn't
|
// Returns TRUE if sheet was loaded, false if it wasn't
|
||||||
@ -543,8 +526,6 @@ protected:
|
|||||||
|
|
||||||
NS_IMETHOD IsRootTag(nsString &aTag, PRBool &aIsTag);
|
NS_IMETHOD IsRootTag(nsString &aTag, PRBool &aIsTag);
|
||||||
|
|
||||||
NS_IMETHOD IsSubordinateBlock(nsString &aTag, PRBool &aIsTag);
|
|
||||||
|
|
||||||
virtual PRBool IsBlockNode(nsIDOMNode *aNode);
|
virtual PRBool IsBlockNode(nsIDOMNode *aNode);
|
||||||
|
|
||||||
static nsCOMPtr<nsIDOMNode> GetEnclosingTable(nsIDOMNode *aNode);
|
static nsCOMPtr<nsIDOMNode> GetEnclosingTable(nsIDOMNode *aNode);
|
||||||
@ -572,11 +553,6 @@ protected:
|
|||||||
nsIDOMNode **aStyleNode,
|
nsIDOMNode **aStyleNode,
|
||||||
nsAString *outValue = nsnull);
|
nsAString *outValue = nsnull);
|
||||||
|
|
||||||
void ResetTextSelectionForRange(nsIDOMNode *aParent,
|
|
||||||
PRInt32 aStartOffset,
|
|
||||||
PRInt32 aEndOffset,
|
|
||||||
nsISelection *aSelection);
|
|
||||||
|
|
||||||
// Methods for handling plaintext quotations
|
// Methods for handling plaintext quotations
|
||||||
NS_IMETHOD PasteAsPlaintextQuotation(PRInt32 aSelectionType);
|
NS_IMETHOD PasteAsPlaintextQuotation(PRInt32 aSelectionType);
|
||||||
|
|
||||||
|
@ -391,70 +391,6 @@ nsHTMLEditor::GetNextRow(nsIDOMNode* aCurrentRowNode, nsIDOMNode **aRowNode)
|
|||||||
return NS_EDITOR_ELEMENT_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
|
NS_IMETHODIMP
|
||||||
nsHTMLEditor::GetLastCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode)
|
nsHTMLEditor::GetLastCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode)
|
||||||
{
|
{
|
||||||
|
@ -76,16 +76,6 @@ public:
|
|||||||
eBlockPartial // S begins or ends in TB but extends outside of TB.
|
eBlockPartial // S begins or ends in TB but extends outside of TB.
|
||||||
} TSDBlockSelectionStatus;
|
} 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.
|
* Get the DOM document for the document in use.
|
||||||
* @return aDocument the dom document [OUT]
|
* @return aDocument the dom document [OUT]
|
||||||
@ -103,26 +93,15 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the range/extent over which the text services document
|
* Sets the range/extent over which the text services document
|
||||||
* will iterate. Note that InitWithDocument() or InitWithEditor()
|
* will iterate. Note that InitWithEditor() should have been called prior to
|
||||||
* should have been called prior to calling this method. If this
|
* calling this method. If this method is never called, the text services
|
||||||
* method is never called, the text services defaults to iterating
|
* defaults to iterating over the entire document.
|
||||||
* over the entire document.
|
|
||||||
*
|
*
|
||||||
* @param aDOMRange is the range to use. aDOMRange must point to a
|
* @param aDOMRange is the range to use. aDOMRange must point to a
|
||||||
* valid range object.
|
* valid range object.
|
||||||
*/
|
*/
|
||||||
NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange) = 0;
|
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.
|
* 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.
|
* This call does not change any internal state of the text services document.
|
||||||
@ -137,14 +116,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter) = 0;
|
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.
|
* Returns the text in the current text block.
|
||||||
* @param aStr will contain the text.
|
* @param aStr will contain the text.
|
||||||
@ -160,27 +131,6 @@ public:
|
|||||||
|
|
||||||
NS_IMETHOD FirstBlock() = 0;
|
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
|
* Tells the document to point to the last text block that
|
||||||
* contains the current selection or caret.
|
* contains the current selection or caret.
|
||||||
@ -259,21 +209,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
NS_IMETHOD InsertText(const nsString *aText) = 0;
|
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_DEFINE_STATIC_IID_ACCESSOR(nsITextServicesDocument,
|
||||||
|
@ -171,46 +171,6 @@ NS_IMPL_RELEASE(nsTextServicesDocument)
|
|||||||
|
|
||||||
NS_IMPL_QUERY_INTERFACE1(nsTextServicesDocument, nsITextServicesDocument)
|
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
|
NS_IMETHODIMP
|
||||||
nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
|
nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
|
||||||
{
|
{
|
||||||
@ -358,27 +318,6 @@ nsTextServicesDocument::SetExtent(nsIDOMRange* aDOMRange)
|
|||||||
return result;
|
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
|
NS_IMETHODIMP
|
||||||
nsTextServicesDocument::ExpandRangeToWordBoundaries(nsIDOMRange *aRange)
|
nsTextServicesDocument::ExpandRangeToWordBoundaries(nsIDOMRange *aRange)
|
||||||
{
|
{
|
||||||
@ -555,19 +494,6 @@ nsTextServicesDocument::SetFilter(nsITextServicesFilter *aFilter)
|
|||||||
return NS_OK;
|
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
|
NS_IMETHODIMP
|
||||||
nsTextServicesDocument::GetCurrentTextBlock(nsString *aStr)
|
nsTextServicesDocument::GetCurrentTextBlock(nsString *aStr)
|
||||||
{
|
{
|
||||||
@ -627,532 +553,6 @@ nsTextServicesDocument::FirstBlock()
|
|||||||
return result;
|
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
|
NS_IMETHODIMP
|
||||||
nsTextServicesDocument::LastSelectedBlock(TSDBlockSelectionStatus *aSelStatus,
|
nsTextServicesDocument::LastSelectedBlock(TSDBlockSelectionStatus *aSelStatus,
|
||||||
PRInt32 *aSelOffset,
|
PRInt32 *aSelOffset,
|
||||||
@ -2416,75 +1816,6 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||||||
return result;
|
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
|
nsresult
|
||||||
nsTextServicesDocument::InsertNode(nsIDOMNode *aNode,
|
nsTextServicesDocument::InsertNode(nsIDOMNode *aNode,
|
||||||
nsIDOMNode *aParent,
|
nsIDOMNode *aParent,
|
||||||
|
@ -138,18 +138,13 @@ public:
|
|||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
/* nsITextServicesDocument method implementations. */
|
/* nsITextServicesDocument method implementations. */
|
||||||
NS_IMETHOD InitWithDocument(nsIDOMDocument *aDOMDocument, nsIPresShell *aPresShell);
|
|
||||||
NS_IMETHOD InitWithEditor(nsIEditor *aEditor);
|
NS_IMETHOD InitWithEditor(nsIEditor *aEditor);
|
||||||
NS_IMETHOD GetDocument(nsIDOMDocument **aDoc);
|
NS_IMETHOD GetDocument(nsIDOMDocument **aDoc);
|
||||||
NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange);
|
NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange);
|
||||||
NS_IMETHOD GetExtent(nsIDOMRange** aDOMRange);
|
|
||||||
NS_IMETHOD ExpandRangeToWordBoundaries(nsIDOMRange *aRange);
|
NS_IMETHOD ExpandRangeToWordBoundaries(nsIDOMRange *aRange);
|
||||||
NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter);
|
NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter);
|
||||||
NS_IMETHOD CanEdit(PRBool *aCanEdit);
|
|
||||||
NS_IMETHOD GetCurrentTextBlock(nsString *aStr);
|
NS_IMETHOD GetCurrentTextBlock(nsString *aStr);
|
||||||
NS_IMETHOD FirstBlock();
|
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 LastSelectedBlock(TSDBlockSelectionStatus *aSelStatus, PRInt32 *aSelOffset, PRInt32 *aSelLength);
|
||||||
NS_IMETHOD PrevBlock();
|
NS_IMETHOD PrevBlock();
|
||||||
NS_IMETHOD NextBlock();
|
NS_IMETHOD NextBlock();
|
||||||
@ -158,8 +153,6 @@ public:
|
|||||||
NS_IMETHOD ScrollSelectionIntoView();
|
NS_IMETHOD ScrollSelectionIntoView();
|
||||||
NS_IMETHOD DeleteSelection();
|
NS_IMETHOD DeleteSelection();
|
||||||
NS_IMETHOD InsertText(const nsString *aText);
|
NS_IMETHOD InsertText(const nsString *aText);
|
||||||
NS_IMETHOD SetDisplayStyle(TSDDisplayStyle aStyle);
|
|
||||||
NS_IMETHOD GetDOMRangeFor(PRInt32 aOffset, PRInt32 aLength, nsIDOMRange** aRange);
|
|
||||||
|
|
||||||
/* nsIEditActionListener method implementations. */
|
/* nsIEditActionListener method implementations. */
|
||||||
nsresult InsertNode(nsIDOMNode * aNode,
|
nsresult InsertNode(nsIDOMNode * aNode,
|
||||||
|
@ -93,7 +93,8 @@ ifdef HAVE_ARM_SIMD
|
|||||||
USE_ARM_SIMD_GCC=1
|
USE_ARM_SIMD_GCC=1
|
||||||
endif
|
endif
|
||||||
ifdef HAVE_ARM_NEON
|
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
|
endif
|
||||||
|
|
||||||
|
@ -2217,8 +2217,8 @@ pixman_bool_t pixman_have_vmx (void) {
|
|||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
|
||||||
|
#if defined(USE_ARM_SIMD)
|
||||||
extern int pixman_msvc_try_arm_simd_op();
|
extern int pixman_msvc_try_arm_simd_op();
|
||||||
extern int pixman_msvc_try_arm_neon_op();
|
|
||||||
|
|
||||||
pixman_bool_t
|
pixman_bool_t
|
||||||
pixman_have_arm_simd (void)
|
pixman_have_arm_simd (void)
|
||||||
@ -2238,6 +2238,10 @@ pixman_have_arm_simd (void)
|
|||||||
|
|
||||||
return have_arm_simd;
|
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_bool_t
|
||||||
pixman_have_arm_neon (void)
|
pixman_have_arm_neon (void)
|
||||||
@ -2257,6 +2261,7 @@ pixman_have_arm_neon (void)
|
|||||||
|
|
||||||
return have_arm_neon;
|
return have_arm_neon;
|
||||||
}
|
}
|
||||||
|
#endif /* USE_ARM_NEON */
|
||||||
|
|
||||||
#else /* linux ELF */
|
#else /* linux ELF */
|
||||||
|
|
||||||
@ -2317,6 +2322,7 @@ pixman_arm_read_auxv() {
|
|||||||
arm_tests_initialized = TRUE;
|
arm_tests_initialized = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(USE_ARM_SIMD)
|
||||||
pixman_bool_t
|
pixman_bool_t
|
||||||
pixman_have_arm_simd (void)
|
pixman_have_arm_simd (void)
|
||||||
{
|
{
|
||||||
@ -2325,7 +2331,9 @@ pixman_have_arm_simd (void)
|
|||||||
|
|
||||||
return arm_has_v6;
|
return arm_has_v6;
|
||||||
}
|
}
|
||||||
|
#endif /* USE_ARM_SIMD */
|
||||||
|
|
||||||
|
#if defined(USE_ARM_NEON)
|
||||||
pixman_bool_t
|
pixman_bool_t
|
||||||
pixman_have_arm_neon (void)
|
pixman_have_arm_neon (void)
|
||||||
{
|
{
|
||||||
@ -2334,6 +2342,7 @@ pixman_have_arm_neon (void)
|
|||||||
|
|
||||||
return arm_has_neon;
|
return arm_has_neon;
|
||||||
}
|
}
|
||||||
|
#endif /* USE_ARM_NEON */
|
||||||
|
|
||||||
#endif /* linux */
|
#endif /* linux */
|
||||||
|
|
||||||
|
@ -63,7 +63,6 @@ EXPORTS = \
|
|||||||
nsIImage.h \
|
nsIImage.h \
|
||||||
nsGfxCIID.h \
|
nsGfxCIID.h \
|
||||||
nsIRegion.h \
|
nsIRegion.h \
|
||||||
nsDeviceContext.h \
|
|
||||||
nsITheme.h \
|
nsITheme.h \
|
||||||
nsThemeConstants.h \
|
nsThemeConstants.h \
|
||||||
$(NULL)
|
$(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___ */
|
|
@ -67,7 +67,6 @@ endif
|
|||||||
|
|
||||||
CPPSRCS = \
|
CPPSRCS = \
|
||||||
nsColor.cpp \
|
nsColor.cpp \
|
||||||
nsDeviceContext.cpp \
|
|
||||||
nsFont.cpp \
|
nsFont.cpp \
|
||||||
nsRect.cpp \
|
nsRect.cpp \
|
||||||
nsRegion.cpp \
|
nsRegion.cpp \
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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 */
|
|
@ -57,7 +57,6 @@ REQUIRES= \
|
|||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
CPPSRCS = \
|
CPPSRCS = \
|
||||||
nsRenderingContextImpl.cpp \
|
|
||||||
gfxImageFrame.cpp \
|
gfxImageFrame.cpp \
|
||||||
$(NULL)
|
$(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;
|
|
||||||
}
|
|
@ -57,6 +57,7 @@ REQUIRES = xpcom \
|
|||||||
string \
|
string \
|
||||||
thebes \
|
thebes \
|
||||||
widget \
|
widget \
|
||||||
|
locale \
|
||||||
view \
|
view \
|
||||||
pref \
|
pref \
|
||||||
unicharutil \
|
unicharutil \
|
||||||
@ -65,6 +66,10 @@ REQUIRES = xpcom \
|
|||||||
qcms \
|
qcms \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
ifeq (,$(filter windows,$(MOZ_WIDGET_TOOLKIT)))
|
||||||
|
REQUIRES += uconv
|
||||||
|
endif
|
||||||
|
|
||||||
CPPSRCS = \
|
CPPSRCS = \
|
||||||
nsThebesDeviceContext.cpp \
|
nsThebesDeviceContext.cpp \
|
||||||
nsThebesImage.cpp \
|
nsThebesImage.cpp \
|
||||||
|
@ -37,12 +37,20 @@
|
|||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** 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 "nsIServiceManager.h"
|
||||||
#include "nsIPrefService.h"
|
#include "nsIPrefService.h"
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
|
|
||||||
#include "nsThebesDeviceContext.h"
|
#include "nsThebesDeviceContext.h"
|
||||||
#include "nsThebesRenderingContext.h"
|
#include "nsThebesRenderingContext.h"
|
||||||
|
#include "gfxUserFontSet.h"
|
||||||
|
|
||||||
#include "nsIWidget.h"
|
#include "nsIWidget.h"
|
||||||
#include "nsIView.h"
|
#include "nsIView.h"
|
||||||
@ -114,7 +122,176 @@ static int x11_error_handler (Display *dpy, XErrorEvent *err) {
|
|||||||
PRLogModuleInfo* gThebesGFXLog = nsnull;
|
PRLogModuleInfo* gThebesGFXLog = nsnull;
|
||||||
#endif
|
#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()
|
nsThebesDeviceContext::nsThebesDeviceContext()
|
||||||
{
|
{
|
||||||
@ -125,21 +302,305 @@ nsThebesDeviceContext::nsThebesDeviceContext()
|
|||||||
|
|
||||||
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("#### Creating DeviceContext %p\n", this));
|
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;
|
mDepth = 0;
|
||||||
mWidth = 0;
|
mWidth = 0;
|
||||||
mHeight = 0;
|
mHeight = 0;
|
||||||
mPrintingScale = 1.0f;
|
mPrintingScale = 1.0f;
|
||||||
|
|
||||||
mWidgetSurfaceCache.Init();
|
|
||||||
|
|
||||||
#if defined(XP_WIN) && !defined(WINCE)
|
#if defined(XP_WIN) && !defined(WINCE)
|
||||||
SCRIPT_DIGITSUBSTITUTE sds;
|
SCRIPT_DIGITSUBSTITUTE sds;
|
||||||
ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &sds);
|
ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &sds);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PRBool DeleteValue(nsHashKey* aKey, void* aValue, void* closure)
|
||||||
|
{
|
||||||
|
delete ((nsString*)aValue);
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
nsThebesDeviceContext::~nsThebesDeviceContext()
|
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
|
/* static */ void
|
||||||
@ -288,6 +749,16 @@ nsThebesDeviceContext::Init(nsNativeWidget aWidget)
|
|||||||
|
|
||||||
SetDPI();
|
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 defined(MOZ_ENABLE_GTK2) && defined(MOZ_X11)
|
||||||
if (getenv ("MOZ_X_SYNC")) {
|
if (getenv ("MOZ_X_SYNC")) {
|
||||||
@ -467,7 +938,6 @@ nsThebesDeviceContext::GetPaletteInfo(nsPaletteInfo& aPaletteInfo)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsThebesDeviceContext::ConvertPixel(nscolor aColor, PRUint32 & aPixel)
|
nsThebesDeviceContext::ConvertPixel(nscolor aColor, PRUint32 & aPixel)
|
||||||
{
|
{
|
||||||
@ -554,7 +1024,7 @@ nsThebesDeviceContext::InitForPrinting(nsIDeviceContextSpec *aDevice)
|
|||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsThebesDeviceContext::PrepareDocument(PRUnichar * aTitle,
|
nsThebesDeviceContext::PrepareDocument(PRUnichar * aTitle,
|
||||||
PRUnichar* aPrintToFileName)
|
PRUnichar* aPrintToFileName)
|
||||||
{
|
{
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -562,9 +1032,9 @@ nsThebesDeviceContext::PrepareDocument(PRUnichar * aTitle,
|
|||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsThebesDeviceContext::BeginDocument(PRUnichar* aTitle,
|
nsThebesDeviceContext::BeginDocument(PRUnichar* aTitle,
|
||||||
PRUnichar* aPrintToFileName,
|
PRUnichar* aPrintToFileName,
|
||||||
PRInt32 aStartPage,
|
PRInt32 aStartPage,
|
||||||
PRInt32 aEndPage)
|
PRInt32 aEndPage)
|
||||||
{
|
{
|
||||||
static const PRUnichar kEmpty[] = { '\0' };
|
static const PRUnichar kEmpty[] = { '\0' };
|
||||||
@ -661,7 +1131,7 @@ nsThebesDeviceContext::ComputeClientRectUsingScreen(nsRect* outRect)
|
|||||||
if (screen) {
|
if (screen) {
|
||||||
PRInt32 x, y, width, height;
|
PRInt32 x, y, width, height;
|
||||||
screen->GetAvailRect(&x, &y, &width, &height);
|
screen->GetAvailRect(&x, &y, &width, &height);
|
||||||
|
|
||||||
// convert to device units
|
// convert to device units
|
||||||
outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
|
outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
|
||||||
outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
|
outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
|
||||||
@ -682,20 +1152,18 @@ nsThebesDeviceContext::ComputeFullAreaUsingScreen(nsRect* outRect)
|
|||||||
if ( screen ) {
|
if ( screen ) {
|
||||||
PRInt32 x, y, width, height;
|
PRInt32 x, y, width, height;
|
||||||
screen->GetRect ( &x, &y, &width, &height );
|
screen->GetRect ( &x, &y, &width, &height );
|
||||||
|
|
||||||
// convert to device units
|
// convert to device units
|
||||||
outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
|
outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
|
||||||
outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
|
outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
|
||||||
outRect->width = NSIntPixelsToAppUnits(width, AppUnitsPerDevPixel());
|
outRect->width = NSIntPixelsToAppUnits(width, AppUnitsPerDevPixel());
|
||||||
outRect->height = NSIntPixelsToAppUnits(height, AppUnitsPerDevPixel());
|
outRect->height = NSIntPixelsToAppUnits(height, AppUnitsPerDevPixel());
|
||||||
|
|
||||||
mWidth = outRect->width;
|
mWidth = outRect->width;
|
||||||
mHeight = outRect->height;
|
mHeight = outRect->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// FindScreen
|
// FindScreen
|
||||||
//
|
//
|
||||||
|
@ -41,16 +41,20 @@
|
|||||||
#define _NS_THEBESDEVICECONTEXT_H_
|
#define _NS_THEBESDEVICECONTEXT_H_
|
||||||
|
|
||||||
#include "nsIScreenManager.h"
|
#include "nsIScreenManager.h"
|
||||||
|
#include "nsIDeviceContext.h"
|
||||||
#include "nsDeviceContext.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 "nsRefPtrHashtable.h"
|
||||||
#include "nsHashKeys.h"
|
#include "nsHashKeys.h"
|
||||||
|
|
||||||
#include "prlog.h"
|
#include "prlog.h"
|
||||||
|
|
||||||
#include "gfxContext.h"
|
|
||||||
|
|
||||||
#ifdef PR_LOGGING
|
#ifdef PR_LOGGING
|
||||||
extern PRLogModuleInfo* gThebesGFXLog;
|
extern PRLogModuleInfo* gThebesGFXLog;
|
||||||
#endif
|
#endif
|
||||||
@ -61,7 +65,12 @@ extern PRLogModuleInfo* gThebesGFXLog;
|
|||||||
#include "gfxOS2Surface.h"
|
#include "gfxOS2Surface.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class nsThebesDeviceContext : public DeviceContextImpl
|
class nsHashtable;
|
||||||
|
class nsFontCache;
|
||||||
|
|
||||||
|
class nsThebesDeviceContext : public nsIDeviceContext,
|
||||||
|
public nsIObserver,
|
||||||
|
public nsSupportsWeakReference
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsThebesDeviceContext();
|
nsThebesDeviceContext();
|
||||||
@ -69,16 +78,32 @@ public:
|
|||||||
|
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
NS_IMETHOD Init(nsNativeWidget aWidget);
|
NS_IMETHOD Init(nsNativeWidget aWidget);
|
||||||
NS_IMETHOD InitForPrinting(nsIDeviceContextSpec *aDevSpec);
|
NS_IMETHOD InitForPrinting(nsIDeviceContextSpec *aDevSpec);
|
||||||
NS_IMETHOD CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext);
|
NS_IMETHOD CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext);
|
||||||
|
|
||||||
NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext);
|
NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext);
|
||||||
NS_IMETHOD CreateRenderingContext(nsIRenderingContext *&aContext);
|
NS_IMETHOD CreateRenderingContext(nsIRenderingContext *&aContext);
|
||||||
NS_IMETHOD CreateRenderingContextInstance(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 SupportsNativeWidgets(PRBool& aSupportsWidgets);
|
||||||
NS_IMETHOD PrepareNativeWidget(nsIWidget *aWidget, void **aOut);
|
NS_IMETHOD PrepareNativeWidget(nsIWidget *aWidget, void **aOut);
|
||||||
|
|
||||||
@ -93,7 +118,7 @@ public:
|
|||||||
|
|
||||||
NS_IMETHOD ConvertPixel(nscolor aColor, PRUint32& aPixel);
|
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 GetRect(nsRect& aRect);
|
||||||
NS_IMETHOD GetClientRect(nsRect& aRect);
|
NS_IMETHOD GetClientRect(nsRect& aRect);
|
||||||
|
|
||||||
@ -126,6 +151,11 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual nsresult CreateFontAliasTable();
|
||||||
|
nsresult AliasFont(const nsString& aFont,
|
||||||
|
const nsString& aAlias, const nsString& aAltAlias,
|
||||||
|
PRBool aForceAlias);
|
||||||
|
void GetLocaleLangGroup(void);
|
||||||
nsresult SetDPI();
|
nsresult SetDPI();
|
||||||
void ComputeClientRectUsingScreen(nsRect *outRect);
|
void ComputeClientRectUsingScreen(nsRect *outRect);
|
||||||
void ComputeFullAreaUsingScreen(nsRect *outRect);
|
void ComputeFullAreaUsingScreen(nsRect *outRect);
|
||||||
@ -133,7 +163,14 @@ protected:
|
|||||||
void CalcPrintingSize();
|
void CalcPrintingSize();
|
||||||
void UpdateScaledAppUnits();
|
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:
|
private:
|
||||||
nsCOMPtr<nsIScreenManager> mScreenManager;
|
nsCOMPtr<nsIScreenManager> mScreenManager;
|
||||||
@ -141,8 +178,6 @@ private:
|
|||||||
nscoord mWidth;
|
nscoord mWidth;
|
||||||
nscoord mHeight;
|
nscoord mHeight;
|
||||||
|
|
||||||
nsRefPtrHashtable<nsISupportsHashKey, gfxASurface> mWidgetSurfaceCache;
|
|
||||||
|
|
||||||
nsRefPtr<gfxASurface> mPrintingSurface;
|
nsRefPtr<gfxASurface> mPrintingSurface;
|
||||||
float mPrintingScale;
|
float mPrintingScale;
|
||||||
nsCOMPtr<nsIDeviceContextSpec> mDeviceContextSpec;
|
nsCOMPtr<nsIDeviceContextSpec> mDeviceContextSpec;
|
||||||
|
@ -40,10 +40,8 @@
|
|||||||
#include "nsThebesRenderingContext.h"
|
#include "nsThebesRenderingContext.h"
|
||||||
#include "nsThebesDeviceContext.h"
|
#include "nsThebesDeviceContext.h"
|
||||||
|
|
||||||
#include "nsRect.h"
|
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsTransform2D.h"
|
#include "nsTransform2D.h"
|
||||||
#include "nsIRegion.h"
|
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
#include "nsIInterfaceRequestorUtils.h"
|
#include "nsIInterfaceRequestorUtils.h"
|
||||||
#include "nsGfxCIID.h"
|
#include "nsGfxCIID.h"
|
||||||
@ -52,10 +50,10 @@
|
|||||||
#include "gfxIImageFrame.h"
|
#include "gfxIImageFrame.h"
|
||||||
#include "nsIImage.h"
|
#include "nsIImage.h"
|
||||||
|
|
||||||
#include "nsIThebesFontMetrics.h"
|
|
||||||
#include "nsThebesRegion.h"
|
#include "nsThebesRegion.h"
|
||||||
#include "nsThebesImage.h"
|
#include "nsThebesImage.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -81,6 +79,47 @@ static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
|
|||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(nsThebesRenderingContext, nsIRenderingContext)
|
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()
|
nsThebesRenderingContext::nsThebesRenderingContext()
|
||||||
: mLineStyle(nsLineStyle_kNone)
|
: mLineStyle(nsLineStyle_kNone)
|
||||||
, mColor(NS_RGB(0,0,0))
|
, mColor(NS_RGB(0,0,0))
|
||||||
@ -159,7 +198,7 @@ nsThebesRenderingContext::GetDeviceContext(nsIDeviceContext *& aDeviceContext)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsThebesRenderingContext::PushTranslation(PushedTranslation* aState)
|
nsThebesRenderingContext::PushTranslation(PushedTranslation* aState)
|
||||||
{
|
{
|
||||||
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::PushTranslation\n", this));
|
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::PushTranslation\n", this));
|
||||||
@ -298,6 +337,7 @@ nsThebesRenderingContext::SetClipRegion(const nsIRegion& pxRegion,
|
|||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// other junk
|
// other junk
|
||||||
//
|
//
|
||||||
@ -336,7 +376,7 @@ nsThebesRenderingContext::SetColor(nscolor aColor)
|
|||||||
* CSS colors are defined to be in by the spec.
|
* CSS colors are defined to be in by the spec.
|
||||||
*/
|
*/
|
||||||
mThebes->SetColor(gfxRGBA(aColor));
|
mThebes->SetColor(gfxRGBA(aColor));
|
||||||
|
|
||||||
mColor = aColor;
|
mColor = aColor;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -780,7 +820,7 @@ nsThebesRenderingContext::GetRightToLeftText(PRBool* aIsRTL)
|
|||||||
void
|
void
|
||||||
nsThebesRenderingContext::SetTextRunRTL(PRBool aIsRTL)
|
nsThebesRenderingContext::SetTextRunRTL(PRBool aIsRTL)
|
||||||
{
|
{
|
||||||
mFontMetrics->SetTextRunRTL(aIsRTL);
|
mFontMetrics->SetTextRunRTL(aIsRTL);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -816,9 +856,9 @@ nsThebesRenderingContext::GetFontMetrics(nsIFontMetrics *&aFontMetrics)
|
|||||||
PRInt32
|
PRInt32
|
||||||
nsThebesRenderingContext::GetMaxStringLength()
|
nsThebesRenderingContext::GetMaxStringLength()
|
||||||
{
|
{
|
||||||
if (!mFontMetrics)
|
if (!mFontMetrics)
|
||||||
return 1;
|
return 1;
|
||||||
return mFontMetrics->GetMaxStringLength();
|
return mFontMetrics->GetMaxStringLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -837,6 +877,407 @@ nsThebesRenderingContext::GetWidth(PRUnichar aC, nscoord &aWidth, PRInt32 *aFont
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
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)
|
nsThebesRenderingContext::GetWidthInternal(const char* aString, PRUint32 aLength, nscoord& aWidth)
|
||||||
{
|
{
|
||||||
#ifdef DISABLE_TEXT
|
#ifdef DISABLE_TEXT
|
||||||
@ -852,7 +1293,7 @@ nsThebesRenderingContext::GetWidthInternal(const char* aString, PRUint32 aLength
|
|||||||
return mFontMetrics->GetWidth(aString, aLength, aWidth, this);
|
return mFontMetrics->GetWidth(aString, aLength, aWidth, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult
|
||||||
nsThebesRenderingContext::GetWidthInternal(const PRUnichar *aString, PRUint32 aLength,
|
nsThebesRenderingContext::GetWidthInternal(const PRUnichar *aString, PRUint32 aLength,
|
||||||
nscoord &aWidth, PRInt32 *aFontID)
|
nscoord &aWidth, PRInt32 *aFontID)
|
||||||
{
|
{
|
||||||
@ -869,28 +1310,28 @@ nsThebesRenderingContext::GetWidthInternal(const PRUnichar *aString, PRUint32 aL
|
|||||||
return mFontMetrics->GetWidth(aString, aLength, aWidth, aFontID, this);
|
return mFontMetrics->GetWidth(aString, aLength, aWidth, aFontID, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult
|
||||||
nsThebesRenderingContext::GetTextDimensionsInternal(const char* aString, PRUint32 aLength,
|
nsThebesRenderingContext::GetTextDimensionsInternal(const char* aString, PRUint32 aLength,
|
||||||
nsTextDimensions& aDimensions)
|
nsTextDimensions& aDimensions)
|
||||||
{
|
{
|
||||||
mFontMetrics->GetMaxAscent(aDimensions.ascent);
|
mFontMetrics->GetMaxAscent(aDimensions.ascent);
|
||||||
mFontMetrics->GetMaxDescent(aDimensions.descent);
|
mFontMetrics->GetMaxDescent(aDimensions.descent);
|
||||||
return GetWidth(aString, aLength, aDimensions.width);
|
return GetWidth(aString, aLength, aDimensions.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult
|
||||||
nsThebesRenderingContext::GetTextDimensionsInternal(const PRUnichar* aString,
|
nsThebesRenderingContext::GetTextDimensionsInternal(const PRUnichar* aString,
|
||||||
PRUint32 aLength,
|
PRUint32 aLength,
|
||||||
nsTextDimensions& aDimensions,
|
nsTextDimensions& aDimensions,
|
||||||
PRInt32* aFontID)
|
PRInt32* aFontID)
|
||||||
{
|
{
|
||||||
mFontMetrics->GetMaxAscent(aDimensions.ascent);
|
mFontMetrics->GetMaxAscent(aDimensions.ascent);
|
||||||
mFontMetrics->GetMaxDescent(aDimensions.descent);
|
mFontMetrics->GetMaxDescent(aDimensions.descent);
|
||||||
return GetWidth(aString, aLength, aDimensions.width, aFontID);
|
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)
|
#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,
|
nsThebesRenderingContext::GetTextDimensionsInternal(const char* aString,
|
||||||
PRInt32 aLength,
|
PRInt32 aLength,
|
||||||
PRInt32 aAvailWidth,
|
PRInt32 aAvailWidth,
|
||||||
@ -904,7 +1345,7 @@ nsThebesRenderingContext::GetTextDimensionsInternal(const char* aString,
|
|||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult
|
||||||
nsThebesRenderingContext::GetTextDimensionsInternal(const PRUnichar* aString,
|
nsThebesRenderingContext::GetTextDimensionsInternal(const PRUnichar* aString,
|
||||||
PRInt32 aLength,
|
PRInt32 aLength,
|
||||||
PRInt32 aAvailWidth,
|
PRInt32 aAvailWidth,
|
||||||
@ -920,7 +1361,7 @@ nsThebesRenderingContext::GetTextDimensionsInternal(const PRUnichar* aString,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_MATHML
|
#ifdef MOZ_MATHML
|
||||||
NS_IMETHODIMP
|
nsresult
|
||||||
nsThebesRenderingContext::GetBoundingMetricsInternal(const char* aString,
|
nsThebesRenderingContext::GetBoundingMetricsInternal(const char* aString,
|
||||||
PRUint32 aLength,
|
PRUint32 aLength,
|
||||||
nsBoundingMetrics& aBoundingMetrics)
|
nsBoundingMetrics& aBoundingMetrics)
|
||||||
@ -928,7 +1369,7 @@ nsThebesRenderingContext::GetBoundingMetricsInternal(const char* aString,
|
|||||||
return mFontMetrics->GetBoundingMetrics(aString, aLength, this, aBoundingMetrics);
|
return mFontMetrics->GetBoundingMetrics(aString, aLength, this, aBoundingMetrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult
|
||||||
nsThebesRenderingContext::GetBoundingMetricsInternal(const PRUnichar* aString,
|
nsThebesRenderingContext::GetBoundingMetricsInternal(const PRUnichar* aString,
|
||||||
PRUint32 aLength,
|
PRUint32 aLength,
|
||||||
nsBoundingMetrics& aBoundingMetrics,
|
nsBoundingMetrics& aBoundingMetrics,
|
||||||
@ -938,7 +1379,7 @@ nsThebesRenderingContext::GetBoundingMetricsInternal(const PRUnichar* aString,
|
|||||||
}
|
}
|
||||||
#endif // MOZ_MATHML
|
#endif // MOZ_MATHML
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult
|
||||||
nsThebesRenderingContext::DrawStringInternal(const char *aString, PRUint32 aLength,
|
nsThebesRenderingContext::DrawStringInternal(const char *aString, PRUint32 aLength,
|
||||||
nscoord aX, nscoord aY,
|
nscoord aX, nscoord aY,
|
||||||
const nscoord* aSpacing)
|
const nscoord* aSpacing)
|
||||||
@ -951,7 +1392,7 @@ nsThebesRenderingContext::DrawStringInternal(const char *aString, PRUint32 aLeng
|
|||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult
|
||||||
nsThebesRenderingContext::DrawStringInternal(const PRUnichar *aString, PRUint32 aLength,
|
nsThebesRenderingContext::DrawStringInternal(const PRUnichar *aString, PRUint32 aLength,
|
||||||
nscoord aX, nscoord aY,
|
nscoord aX, nscoord aY,
|
||||||
PRInt32 aFontID,
|
PRInt32 aFontID,
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsIRenderingContext.h"
|
#include "nsIRenderingContext.h"
|
||||||
#include "nsRenderingContextImpl.h"
|
|
||||||
#include "nsIDeviceContext.h"
|
#include "nsIDeviceContext.h"
|
||||||
#include "nsIFontMetrics.h"
|
#include "nsIFontMetrics.h"
|
||||||
#include "nsIWidget.h"
|
#include "nsIWidget.h"
|
||||||
@ -57,7 +56,7 @@
|
|||||||
|
|
||||||
class nsIImage;
|
class nsIImage;
|
||||||
|
|
||||||
class nsThebesRenderingContext : public nsRenderingContextImpl
|
class nsThebesRenderingContext : public nsIRenderingContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsThebesRenderingContext();
|
nsThebesRenderingContext();
|
||||||
@ -65,6 +64,74 @@ public:
|
|||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
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, gfxASurface* aThebesSurface);
|
||||||
NS_IMETHOD Init(nsIDeviceContext* aContext, gfxContext* aThebesContext);
|
NS_IMETHOD Init(nsIDeviceContext* aContext, gfxContext* aThebesContext);
|
||||||
|
|
||||||
@ -99,81 +166,6 @@ public:
|
|||||||
NS_IMETHOD FillEllipse(const nsRect& aRect);
|
NS_IMETHOD FillEllipse(const nsRect& aRect);
|
||||||
NS_IMETHOD FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
|
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 PushFilter(const nsRect& aRect, PRBool aAreaIsOpaque, float aOpacity);
|
||||||
NS_IMETHOD PopFilter();
|
NS_IMETHOD PopFilter();
|
||||||
|
|
||||||
@ -183,6 +175,10 @@ public:
|
|||||||
NS_IMETHOD PopTranslation(PushedTranslation* aState);
|
NS_IMETHOD PopTranslation(PushedTranslation* aState);
|
||||||
NS_IMETHOD SetTranslation(nscoord aX, nscoord aY);
|
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 SetRightToLeftText(PRBool aIsRTL);
|
||||||
NS_IMETHOD GetRightToLeftText(PRBool* aIsRTL);
|
NS_IMETHOD GetRightToLeftText(PRBool* aIsRTL);
|
||||||
virtual void SetTextRunRTL(PRBool aIsRTL);
|
virtual void SetTextRunRTL(PRBool aIsRTL);
|
||||||
@ -212,8 +208,64 @@ public:
|
|||||||
void TransformCoord (nscoord *aX, nscoord *aY);
|
void TransformCoord (nscoord *aX, nscoord *aY);
|
||||||
|
|
||||||
protected:
|
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;
|
nsCOMPtr<nsIDeviceContext> mDeviceContext;
|
||||||
// cached pixels2twips, twips2pixels values
|
// cached app units per device pixel value
|
||||||
double mP2A;
|
double mP2A;
|
||||||
|
|
||||||
nsCOMPtr<nsIWidget> mWidget;
|
nsCOMPtr<nsIWidget> mWidget;
|
||||||
|
@ -649,23 +649,26 @@ $(addsuffix .$(OBJ_SUFFIX),jsdtracef jsinterp jsobj): $(CURDIR)/javascript-trace
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef GNU_CC
|
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
|
imacro_asm.js: imacro_asm.js.in jsopcode.tbl
|
||||||
$(CC) -c -x c -E -P -I$(srcdir) $< > $@
|
$(CC) -c -x c -E -P -I$(srcdir) $< > $@
|
||||||
|
|
||||||
GARBAGE += imacros.c.out imacro_asm.js
|
GARBAGE += imacros.c.tmp imacro_asm.js
|
||||||
|
|
||||||
ifndef CROSS_COMPILE
|
ifneq (,$(wildcard $(RUN_TEST_PROGRAM))$(if $(NSPR_LIBS),,1))
|
||||||
# Obsolete comment: if you replace update-imacros with libs, this would apply
|
libs:: imacro_asm.js $(srcdir)/imacros.jsasm
|
||||||
# but then parallel gmake would sometimes try to run $(DIST)/bin/js before it
|
$(wildcard $(RUN_TEST_PROGRAM)) $(DIST)/bin/js$(BIN_SUFFIX) $< $(srcdir)/imacros.jsasm > imacros.c.tmp
|
||||||
# had been built and installed. Want a fix for this, de-automating for now.
|
@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"
|
||||||
|
|
||||||
# Build imacros.c.out after descending into DIRS and building the js shell.
|
update-imacros: imacros.c.tmp
|
||||||
# This may result in an updated imacros.c.out file that requires a re-build
|
cp $< $(srcdir)/imacros.c.out
|
||||||
# to stabilize.
|
|
||||||
update-imacros:: imacros.c.out
|
|
||||||
@cmp -s imacros.c.out $(srcdir)/$< || cp imacros.c.out $(srcdir)
|
|
||||||
|
|
||||||
%.c.out: %.jsasm imacro_asm.js
|
.PHONY: update-imacros
|
||||||
$(DIST)/bin/js imacro_asm.js $< > $@
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -2505,6 +2505,17 @@ nsLayoutUtils::GetStringWidth(const nsIFrame* aFrame,
|
|||||||
|
|
||||||
/* static */ PRBool
|
/* static */ PRBool
|
||||||
nsLayoutUtils::GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult)
|
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));
|
const nsBlockFrame* block = nsLayoutUtils::GetAsBlock(const_cast<nsIFrame*>(aFrame));
|
||||||
if (!block) {
|
if (!block) {
|
||||||
@ -2512,7 +2523,11 @@ nsLayoutUtils::GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult)
|
|||||||
// so, use the baseline of its first row.
|
// so, use the baseline of its first row.
|
||||||
nsIAtom* fType = aFrame->GetType();
|
nsIAtom* fType = aFrame->GetType();
|
||||||
if (fType == nsGkAtoms::tableOuterFrame) {
|
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;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2522,12 +2537,12 @@ nsLayoutUtils::GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult)
|
|||||||
if (!sFrame) {
|
if (!sFrame) {
|
||||||
NS_NOTREACHED("not scroll frame");
|
NS_NOTREACHED("not scroll frame");
|
||||||
}
|
}
|
||||||
nscoord kidBaseline;
|
LinePosition kidPosition;
|
||||||
if (GetFirstLineBaseline(sFrame->GetScrolledFrame(), &kidBaseline)) {
|
if (GetFirstLinePosition(sFrame->GetScrolledFrame(), &kidPosition)) {
|
||||||
// Consider only the border and padding that contributes to the
|
// Consider only the border and padding that contributes to the
|
||||||
// kid's position, not the scrolling, so we get the initial
|
// kid's position, not the scrolling, so we get the initial
|
||||||
// position.
|
// position.
|
||||||
*aResult = kidBaseline + aFrame->GetUsedBorderAndPadding().top;
|
*aResult = kidPosition + aFrame->GetUsedBorderAndPadding().top;
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
@ -2542,16 +2557,19 @@ nsLayoutUtils::GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult)
|
|||||||
line != line_end; ++line) {
|
line != line_end; ++line) {
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
nsIFrame *kid = line->mFirstChild;
|
nsIFrame *kid = line->mFirstChild;
|
||||||
nscoord kidBaseline;
|
LinePosition kidPosition;
|
||||||
if (GetFirstLineBaseline(kid, &kidBaseline)) {
|
if (GetFirstLinePosition(kid, &kidPosition)) {
|
||||||
*aResult = kidBaseline + kid->GetPosition().y;
|
*aResult = kidPosition + kid->GetPosition().y;
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// XXX Is this the right test? We have some bogus empty lines
|
// XXX Is this the right test? We have some bogus empty lines
|
||||||
// floating around, but IsEmpty is perhaps too weak.
|
// floating around, but IsEmpty is perhaps too weak.
|
||||||
if (line->GetHeight() != 0 || !line->IsEmpty()) {
|
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_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -775,6 +775,28 @@ public:
|
|||||||
*/
|
*/
|
||||||
static PRBool GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult);
|
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)
|
* Derive a baseline of |aFrame| (measured from its top border edge)
|
||||||
* from its last in-flow line box (not descending into anything with
|
* from its last in-flow line box (not descending into anything with
|
||||||
|
@ -5103,8 +5103,6 @@ PresShell::RenderDocument(const nsRect& aRect, PRUint32 aFlags,
|
|||||||
|
|
||||||
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
|
||||||
if (rootFrame) {
|
if (rootFrame) {
|
||||||
nsAutoDisableGetUsedXAssertions disableAssert;
|
|
||||||
|
|
||||||
nsDisplayListBuilder builder(rootFrame, PR_FALSE,
|
nsDisplayListBuilder builder(rootFrame, PR_FALSE,
|
||||||
(aFlags & RENDER_CARET) != 0);
|
(aFlags & RENDER_CARET) != 0);
|
||||||
nsDisplayList list;
|
nsDisplayList list;
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
#include "nsDataDocumentContentPolicy.h"
|
#include "nsDataDocumentContentPolicy.h"
|
||||||
#include "nsNoDataProtocolContentPolicy.h"
|
#include "nsNoDataProtocolContentPolicy.h"
|
||||||
#include "nsDOMCID.h"
|
#include "nsDOMCID.h"
|
||||||
#include "nsCSSOMFactory.h"
|
|
||||||
#include "nsInspectorCSSUtils.h"
|
#include "nsInspectorCSSUtils.h"
|
||||||
#include "nsHTMLContentSerializer.h"
|
#include "nsHTMLContentSerializer.h"
|
||||||
#include "nsHTMLParts.h"
|
#include "nsHTMLParts.h"
|
||||||
@ -522,7 +521,6 @@ MAKE_CTOR(CreateXTFService, nsIXTFService, NS_NewXTF
|
|||||||
MAKE_CTOR(CreateXMLContentBuilder, nsIXMLContentBuilder, NS_NewXMLContentBuilder)
|
MAKE_CTOR(CreateXMLContentBuilder, nsIXMLContentBuilder, NS_NewXMLContentBuilder)
|
||||||
#endif
|
#endif
|
||||||
MAKE_CTOR(CreateContentDLF, nsIDocumentLoaderFactory, NS_NewContentDocumentLoaderFactory)
|
MAKE_CTOR(CreateContentDLF, nsIDocumentLoaderFactory, NS_NewContentDocumentLoaderFactory)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCSSOMFactory)
|
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsInspectorCSSUtils)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsInspectorCSSUtils)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWyciwygProtocolHandler)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWyciwygProtocolHandler)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsContentAreaDragDrop)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsContentAreaDragDrop)
|
||||||
@ -995,11 +993,6 @@ static const nsModuleComponentInfo gComponents[] = {
|
|||||||
"@mozilla.org/content/subtree-content-iterator;1",
|
"@mozilla.org/content/subtree-content-iterator;1",
|
||||||
CreateSubtreeIterator },
|
CreateSubtreeIterator },
|
||||||
|
|
||||||
{ "CSS Object Model Factory",
|
|
||||||
NS_CSSOMFACTORY_CID,
|
|
||||||
nsnull,
|
|
||||||
nsCSSOMFactoryConstructor },
|
|
||||||
|
|
||||||
{ "Inspector CSS Utils",
|
{ "Inspector CSS Utils",
|
||||||
NS_INSPECTORCSSUTILS_CID,
|
NS_INSPECTORCSSUTILS_CID,
|
||||||
nsnull,
|
nsnull,
|
||||||
|
@ -59,7 +59,6 @@
|
|||||||
#include "nsEventListenerManager.h"
|
#include "nsEventListenerManager.h"
|
||||||
#include "nsFrame.h"
|
#include "nsFrame.h"
|
||||||
#include "nsGenericElement.h" // for nsDOMEventRTTearoff
|
#include "nsGenericElement.h" // for nsDOMEventRTTearoff
|
||||||
#include "nsStyledElement.h"
|
|
||||||
#include "nsGlobalWindow.h"
|
#include "nsGlobalWindow.h"
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
#include "nsImageFrame.h"
|
#include "nsImageFrame.h"
|
||||||
@ -321,7 +320,6 @@ nsLayoutStatics::Shutdown()
|
|||||||
nsCSSScanner::ReleaseGlobals();
|
nsCSSScanner::ReleaseGlobals();
|
||||||
|
|
||||||
NS_IF_RELEASE(nsRuleNode::gLangService);
|
NS_IF_RELEASE(nsRuleNode::gLangService);
|
||||||
nsStyledElement::Shutdown();
|
|
||||||
|
|
||||||
nsTextFragment::Shutdown();
|
nsTextFragment::Shutdown();
|
||||||
|
|
||||||
|
@ -1075,14 +1075,14 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
mLines.begin().next()->IsBlock()))) {
|
mLines.begin().next()->IsBlock()))) {
|
||||||
// Reflow the bullet
|
// Reflow the bullet
|
||||||
nsHTMLReflowMetrics metrics;
|
nsHTMLReflowMetrics metrics;
|
||||||
// FIXME: aReflowState.mComputedBorderPadding.top isn't even the
|
// XXX Use the entire line when we fix bug 25888.
|
||||||
// right place -- we really want the top of the line whose baseline
|
nsLayoutUtils::LinePosition position;
|
||||||
// we're using (or, actually, the entire line, once we fix bug
|
PRBool havePosition = nsLayoutUtils::GetFirstLinePosition(this, &position);
|
||||||
// 25888)
|
nscoord lineTop = havePosition ? position.mTop
|
||||||
ReflowBullet(state, metrics, aReflowState.mComputedBorderPadding.top);
|
: aReflowState.mComputedBorderPadding.top;
|
||||||
|
ReflowBullet(state, metrics, lineTop);
|
||||||
|
|
||||||
nscoord baseline;
|
if (havePosition) {
|
||||||
if (nsLayoutUtils::GetFirstLineBaseline(this, &baseline)) {
|
|
||||||
// We have some lines to align the bullet with.
|
// We have some lines to align the bullet with.
|
||||||
|
|
||||||
// Doing the alignment using the baseline will also cater for
|
// Doing the alignment using the baseline will also cater for
|
||||||
@ -1090,7 +1090,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
// Tall bullets won't look particularly nice here...
|
// Tall bullets won't look particularly nice here...
|
||||||
nsRect bbox = mBullet->GetRect();
|
nsRect bbox = mBullet->GetRect();
|
||||||
bbox.y = baseline - metrics.ascent;
|
bbox.y = position.mBaseline - metrics.ascent;
|
||||||
mBullet->SetRect(bbox);
|
mBullet->SetRect(bbox);
|
||||||
}
|
}
|
||||||
// Otherwise just leave the bullet where it is, up against our top padding.
|
// Otherwise just leave the bullet where it is, up against our top padding.
|
||||||
@ -1657,19 +1657,19 @@ nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState,
|
|||||||
} else {
|
} else {
|
||||||
// Note that this check will become incorrect once bug 25888 is fixed
|
// Note that this check will become incorrect once bug 25888 is fixed
|
||||||
// because we are only checking the top of the line
|
// because we are only checking the top of the line
|
||||||
aState.GetAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE);
|
|
||||||
PRBool wasImpactedByFloat = aLine->IsImpactedByFloat();
|
PRBool wasImpactedByFloat = aLine->IsImpactedByFloat();
|
||||||
PRBool isImpactedByFloat = aState.IsImpactedByFloat();
|
nsFlowAreaRect floatAvailableSpace =
|
||||||
|
aState.GetFloatAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE);
|
||||||
|
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
printf("nsBlockFrame::PropagateFloatDamage %p was = %d, is=%d\n",
|
printf("nsBlockFrame::PropagateFloatDamage %p was = %d, is=%d\n",
|
||||||
this, wasImpactedByFloat, isImpactedByFloat);
|
this, wasImpactedByFloat, floatAvailableSpace.mHasFloats);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Mark the line dirty if it was or is affected by a float
|
// 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
|
// We actually only really need to reflow if the amount of impact
|
||||||
// changes, but that's not straightforward to check
|
// changes, but that's not straightforward to check
|
||||||
if (wasImpactedByFloat || isImpactedByFloat) {
|
if (wasImpactedByFloat || floatAvailableSpace.mHasFloats) {
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2951,15 +2951,15 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||||||
|
|
||||||
// Here aState.mY is the top border-edge of the block.
|
// Here aState.mY is the top border-edge of the block.
|
||||||
// Compute the available space for the block
|
// Compute the available space for the block
|
||||||
aState.GetAvailableSpace();
|
nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace();
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
#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
|
#endif
|
||||||
PRBool isImpacted = aState.IsImpactedByFloat() ? PR_TRUE : PR_FALSE;
|
aLine->SetLineIsImpactedByFloat(floatAvailableSpace.mHasFloats);
|
||||||
aLine->SetLineIsImpactedByFloat(isImpacted);
|
|
||||||
nsRect availSpace;
|
nsRect availSpace;
|
||||||
aState.ComputeBlockAvailSpace(frame, display, replacedBlock != nsnull,
|
aState.ComputeBlockAvailSpace(frame, display, floatAvailableSpace,
|
||||||
availSpace);
|
replacedBlock != nsnull, availSpace);
|
||||||
|
|
||||||
// Now put the Y coordinate back to the top of the top-margin +
|
// Now put the Y coordinate back to the top of the top-margin +
|
||||||
// clearance, and flow the block.
|
// clearance, and flow the block.
|
||||||
@ -3039,7 +3039,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||||||
// then pushing it to the next page would give it more room. Note that
|
// 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.
|
// isImpacted doesn't include impact from the block's own floats.
|
||||||
PRBool forceFit = aState.IsAdjacentWithTop() && clearance <= 0 &&
|
PRBool forceFit = aState.IsAdjacentWithTop() && clearance <= 0 &&
|
||||||
!isImpacted;
|
!floatAvailableSpace.mHasFloats;
|
||||||
nsCollapsingMargin collapsedBottomMargin;
|
nsCollapsingMargin collapsedBottomMargin;
|
||||||
nsRect combinedArea(0,0,0,0);
|
nsRect combinedArea(0,0,0,0);
|
||||||
*aKeepReflowGoing = brc.PlaceBlock(blockHtmlRS, forceFit, aLine.get(),
|
*aKeepReflowGoing = brc.PlaceBlock(blockHtmlRS, forceFit, aLine.get(),
|
||||||
@ -3347,24 +3347,23 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
if (ShouldApplyTopMargin(aState, aLine)) {
|
if (ShouldApplyTopMargin(aState, aLine)) {
|
||||||
aState.mY += aState.mPrevBottomMargin.get();
|
aState.mY += aState.mPrevBottomMargin.get();
|
||||||
}
|
}
|
||||||
aState.GetAvailableSpace();
|
nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace();
|
||||||
PRBool impactedByFloats = aState.IsImpactedByFloat() ? PR_TRUE : PR_FALSE;
|
aLine->SetLineIsImpactedByFloat(floatAvailableSpace.mHasFloats);
|
||||||
aLine->SetLineIsImpactedByFloat(impactedByFloats);
|
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
|
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
|
||||||
this, impactedByFloats);
|
this, floatAvailableSpace.mHasFloats);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const nsMargin& borderPadding = aState.BorderPadding();
|
const nsMargin& borderPadding = aState.BorderPadding();
|
||||||
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
nscoord x = floatAvailableSpace.mRect.x + borderPadding.left;
|
||||||
nscoord availWidth = aState.mAvailSpaceRect.width;
|
nscoord availWidth = floatAvailableSpace.mRect.width;
|
||||||
nscoord availHeight;
|
nscoord availHeight;
|
||||||
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
|
||||||
availHeight = NS_UNCONSTRAINEDSIZE;
|
availHeight = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* XXX get the height right! */
|
/* XXX get the height right! */
|
||||||
availHeight = aState.mAvailSpaceRect.height;
|
availHeight = floatAvailableSpace.mRect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure to enable resize optimization before we call BeginLineReflow
|
// Make sure to enable resize optimization before we call BeginLineReflow
|
||||||
@ -3373,7 +3372,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
|
|
||||||
aLineLayout.BeginLineReflow(x, aState.mY,
|
aLineLayout.BeginLineReflow(x, aState.mY,
|
||||||
availWidth, availHeight,
|
availWidth, availHeight,
|
||||||
impactedByFloats,
|
floatAvailableSpace.mHasFloats,
|
||||||
PR_FALSE /*XXX isTopOfPage*/);
|
PR_FALSE /*XXX isTopOfPage*/);
|
||||||
|
|
||||||
aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, PR_FALSE);
|
aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, PR_FALSE);
|
||||||
@ -3396,7 +3395,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
// continuations
|
// continuations
|
||||||
PRBool isContinuingPlaceholders = PR_FALSE;
|
PRBool isContinuingPlaceholders = PR_FALSE;
|
||||||
|
|
||||||
if (impactedByFloats) {
|
if (floatAvailableSpace.mHasFloats) {
|
||||||
// There is a soft break opportunity at the start of the line, because
|
// There is a soft break opportunity at the start of the line, because
|
||||||
// we can always move this line down below float(s).
|
// we can always move this line down below float(s).
|
||||||
if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0, PR_TRUE, eNormalBreak)) {
|
if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0, PR_TRUE, eNormalBreak)) {
|
||||||
@ -3501,14 +3500,14 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
//
|
//
|
||||||
// What we do is to advance past the first float we find and
|
// What we do is to advance past the first float we find and
|
||||||
// then reflow the line all over again.
|
// 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");
|
"unconstrained height on totally empty line");
|
||||||
|
|
||||||
// See the analogous code for blocks in nsBlockReflowState::ClearFloats.
|
// See the analogous code for blocks in nsBlockReflowState::ClearFloats.
|
||||||
if (aState.mAvailSpaceRect.height > 0) {
|
if (floatAvailableSpace.mRect.height > 0) {
|
||||||
NS_ASSERTION(aState.IsImpactedByFloat(),
|
NS_ASSERTION(floatAvailableSpace.mHasFloats,
|
||||||
"redo line on totally empty line with non-empty band...");
|
"redo line on totally empty line with non-empty band...");
|
||||||
aState.mY += aState.mAvailSpaceRect.height;
|
aState.mY += floatAvailableSpace.mRect.height;
|
||||||
} else {
|
} else {
|
||||||
NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight,
|
NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight,
|
||||||
"We shouldn't be running out of height here");
|
"We shouldn't be running out of height here");
|
||||||
@ -5646,8 +5645,9 @@ nsBlockFrame::DeleteNextInFlowChild(nsPresContext* aPresContext,
|
|||||||
// Float support
|
// Float support
|
||||||
|
|
||||||
nsRect
|
nsRect
|
||||||
nsBlockFrame::ComputeFloatAvailableSpace(nsBlockReflowState& aState,
|
nsBlockFrame::AdjustFloatAvailableSpace(nsBlockReflowState& aState,
|
||||||
nsIFrame* aFloatFrame)
|
const nsRect& aFloatAvailableSpace,
|
||||||
|
nsIFrame* aFloatFrame)
|
||||||
{
|
{
|
||||||
// Compute the available width. By default, assume the width of the
|
// Compute the available width. By default, assume the width of the
|
||||||
// containing block.
|
// containing block.
|
||||||
@ -5663,7 +5663,7 @@ nsBlockFrame::ComputeFloatAvailableSpace(nsBlockReflowState& aState,
|
|||||||
// give tables only the available space
|
// give tables only the available space
|
||||||
// if they can shrink we may not be constrained to place
|
// if they can shrink we may not be constrained to place
|
||||||
// them in the next line
|
// them in the next line
|
||||||
availWidth = aState.mAvailSpaceRect.width;
|
availWidth = aFloatAvailableSpace.width;
|
||||||
// round down to twips per pixel so that we fit
|
// round down to twips per pixel so that we fit
|
||||||
// needed when prev. float has procentage width
|
// needed when prev. float has procentage width
|
||||||
// (maybe is a table flaw that makes table chose to round up
|
// (maybe is a table flaw that makes table chose to round up
|
||||||
@ -5696,12 +5696,14 @@ nsBlockFrame::ComputeFloatAvailableSpace(nsBlockReflowState& aState,
|
|||||||
|
|
||||||
nscoord
|
nscoord
|
||||||
nsBlockFrame::ComputeFloatWidth(nsBlockReflowState& aState,
|
nsBlockFrame::ComputeFloatWidth(nsBlockReflowState& aState,
|
||||||
|
const nsRect& aFloatAvailableSpace,
|
||||||
nsPlaceholderFrame* aPlaceholder)
|
nsPlaceholderFrame* aPlaceholder)
|
||||||
{
|
{
|
||||||
// Reflow the float.
|
// Reflow the float.
|
||||||
nsIFrame* floatFrame = aPlaceholder->GetOutOfFlowFrame();
|
nsIFrame* floatFrame = aPlaceholder->GetOutOfFlowFrame();
|
||||||
|
|
||||||
nsRect availSpace = ComputeFloatAvailableSpace(aState, floatFrame);
|
nsRect availSpace = AdjustFloatAvailableSpace(aState, aFloatAvailableSpace,
|
||||||
|
floatFrame);
|
||||||
|
|
||||||
nsHTMLReflowState floatRS(aState.mPresContext, aState.mReflowState,
|
nsHTMLReflowState floatRS(aState.mPresContext, aState.mReflowState,
|
||||||
floatFrame,
|
floatFrame,
|
||||||
@ -5712,6 +5714,7 @@ nsBlockFrame::ComputeFloatWidth(nsBlockReflowState& aState,
|
|||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||||
|
const nsRect& aFloatAvailableSpace,
|
||||||
nsPlaceholderFrame* aPlaceholder,
|
nsPlaceholderFrame* aPlaceholder,
|
||||||
nsMargin& aFloatMargin,
|
nsMargin& aFloatMargin,
|
||||||
nsReflowStatus& aReflowStatus)
|
nsReflowStatus& aReflowStatus)
|
||||||
@ -5723,12 +5726,13 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
|||||||
#ifdef NOISY_FLOAT
|
#ifdef NOISY_FLOAT
|
||||||
printf("Reflow Float %p in parent %p, availSpace(%d,%d,%d,%d)\n",
|
printf("Reflow Float %p in parent %p, availSpace(%d,%d,%d,%d)\n",
|
||||||
aPlaceholder->GetOutOfFlowFrame(), this,
|
aPlaceholder->GetOutOfFlowFrame(), this,
|
||||||
aState.mAvailSpaceRect.x, aState.mAvailSpaceRect.y,
|
aFloatAvailableSpace.x, aFloatAvailableSpace.y,
|
||||||
aState.mAvailSpaceRect.width, aState.mAvailSpaceRect.height
|
aFloatAvailableSpace.width, aFloatAvailableSpace.height
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsRect availSpace = ComputeFloatAvailableSpace(aState, floatFrame);
|
nsRect availSpace = AdjustFloatAvailableSpace(aState, aFloatAvailableSpace,
|
||||||
|
floatFrame);
|
||||||
|
|
||||||
nsHTMLReflowState floatRS(aState.mPresContext, aState.mReflowState,
|
nsHTMLReflowState floatRS(aState.mPresContext, aState.mReflowState,
|
||||||
floatFrame,
|
floatFrame,
|
||||||
@ -6650,22 +6654,43 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState,
|
|||||||
mBullet->WillReflow(aState.mPresContext);
|
mBullet->WillReflow(aState.mPresContext);
|
||||||
mBullet->Reflow(aState.mPresContext, aMetrics, reflowState, status);
|
mBullet->Reflow(aState.mPresContext, aMetrics, reflowState, status);
|
||||||
|
|
||||||
// Place the bullet now, separate it from mOutsideBulletX by its margin.
|
// Get the float available space using our saved state from before we
|
||||||
// If the mAvailSpaceRect position is outside the mOutsideBulletX
|
// started reflowing the block, so that we ignore any floats inside
|
||||||
// position it means the line didn't care about the float edge and we
|
// the block.
|
||||||
// use that position instead (there cannot be any floats at the start
|
// FIXME: aLineTop isn't actually set correctly by some callers, since
|
||||||
// of the line this case since that would violate CSS 2.1 float rules).
|
// they reposition the line.
|
||||||
// XXX we need to take floats inside the principal block that clears
|
nsRect floatAvailSpace =
|
||||||
// outside floats into account also (bug 428810).
|
aState.GetFloatAvailableSpaceWithState(aLineTop, PR_FALSE,
|
||||||
nscoord x = rs.mStyleVisibility->mDirection == NS_STYLE_DIRECTION_LTR ?
|
&aState.mFloatManagerStateBefore)
|
||||||
PR_MIN(aState.mOutsideBulletX, aState.mAvailSpaceRect.x)
|
.mRect;
|
||||||
- reflowState.mComputedMargin.right - aMetrics.width :
|
// FIXME (bug 25888): need to check the entire region that the first
|
||||||
PR_MAX(aState.mOutsideBulletX, aState.mAvailSpaceRect.XMost())
|
// line overlaps, not just the top pixel.
|
||||||
+ reflowState.mComputedMargin.left;
|
|
||||||
|
|
||||||
// FIXME: come up with rules for when mAvailSpaceRect is valid so we
|
// Place the bullet now. We want to place the bullet relative to the
|
||||||
// don't need to do this.
|
// border-box of the associated block (using the right/left margin of
|
||||||
aState.GetAvailableSpace();
|
// 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
|
// Approximate the bullets position; vertical alignment will provide
|
||||||
// the final vertical location.
|
// the final vertical location.
|
||||||
@ -6824,6 +6849,7 @@ nsBlockFrame::BlockCanIntersectFloats(nsIFrame* aFrame)
|
|||||||
/* static */
|
/* static */
|
||||||
nsBlockFrame::ReplacedElementWidthToClear
|
nsBlockFrame::ReplacedElementWidthToClear
|
||||||
nsBlockFrame::WidthToClearPastFloats(nsBlockReflowState& aState,
|
nsBlockFrame::WidthToClearPastFloats(nsBlockReflowState& aState,
|
||||||
|
const nsRect& aFloatAvailableSpace,
|
||||||
nsIFrame* aFrame)
|
nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
nscoord leftOffset, rightOffset;
|
nscoord leftOffset, rightOffset;
|
||||||
@ -6877,7 +6903,8 @@ nsBlockFrame::WidthToClearPastFloats(nsBlockReflowState& aState,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aState.ComputeReplacedBlockOffsetsForFloats(aFrame, leftOffset, rightOffset,
|
aState.ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace,
|
||||||
|
leftOffset, rightOffset,
|
||||||
&result);
|
&result);
|
||||||
|
|
||||||
// result.marginLeft has already been subtracted from leftOffset (etc.)
|
// result.marginLeft has already been subtracted from leftOffset (etc.)
|
||||||
@ -6901,7 +6928,8 @@ nsBlockFrame::WidthToClearPastFloats(nsBlockReflowState& aState,
|
|||||||
offsetState.mComputedBorderPadding.LeftRight() -
|
offsetState.mComputedBorderPadding.LeftRight() -
|
||||||
(result.marginLeft + result.marginRight);
|
(result.marginLeft + result.marginRight);
|
||||||
} else {
|
} else {
|
||||||
aState.ComputeReplacedBlockOffsetsForFloats(aFrame, leftOffset, rightOffset);
|
aState.ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace,
|
||||||
|
leftOffset, rightOffset);
|
||||||
nscoord availWidth = aState.mContentArea.width - leftOffset - rightOffset;
|
nscoord availWidth = aState.mContentArea.width - leftOffset - rightOffset;
|
||||||
|
|
||||||
// We actually don't want the min width here; see bug 427782; we only
|
// We actually don't want the min width here; see bug 427782; we only
|
||||||
|
@ -304,7 +304,9 @@ public:
|
|||||||
{ return marginLeft + borderBoxWidth + marginRight; }
|
{ return marginLeft + borderBoxWidth + marginRight; }
|
||||||
};
|
};
|
||||||
static ReplacedElementWidthToClear
|
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
|
* Walks up the frame tree, starting with aCandidate, and returns the first
|
||||||
@ -529,14 +531,17 @@ protected:
|
|||||||
LineReflowStatus* aLineReflowStatus);
|
LineReflowStatus* aLineReflowStatus);
|
||||||
|
|
||||||
// Compute the available width for a float.
|
// Compute the available width for a float.
|
||||||
nsRect ComputeFloatAvailableSpace(nsBlockReflowState& aState,
|
nsRect AdjustFloatAvailableSpace(nsBlockReflowState& aState,
|
||||||
nsIFrame* aFloatFrame);
|
const nsRect& aFloatAvailableSpace,
|
||||||
|
nsIFrame* aFloatFrame);
|
||||||
// Computes the border-box width of the float
|
// Computes the border-box width of the float
|
||||||
nscoord ComputeFloatWidth(nsBlockReflowState& aState,
|
nscoord ComputeFloatWidth(nsBlockReflowState& aState,
|
||||||
|
const nsRect& aFloatAvailableSpace,
|
||||||
nsPlaceholderFrame* aPlaceholder);
|
nsPlaceholderFrame* aPlaceholder);
|
||||||
// An incomplete aReflowStatus indicates the float should be split
|
// An incomplete aReflowStatus indicates the float should be split
|
||||||
// but only if the available height is constrained.
|
// but only if the available height is constrained.
|
||||||
nsresult ReflowFloat(nsBlockReflowState& aState,
|
nsresult ReflowFloat(nsBlockReflowState& aState,
|
||||||
|
const nsRect& aFloatAvailableSpace,
|
||||||
nsPlaceholderFrame* aPlaceholder,
|
nsPlaceholderFrame* aPlaceholder,
|
||||||
nsMargin& aFloatMargin,
|
nsMargin& aFloatMargin,
|
||||||
nsReflowStatus& aReflowStatus);
|
nsReflowStatus& aReflowStatus);
|
||||||
|
@ -102,6 +102,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
|||||||
// coordinate system origin for later.
|
// coordinate system origin for later.
|
||||||
mFloatManager->Translate(borderPadding.left, borderPadding.top);
|
mFloatManager->Translate(borderPadding.left, borderPadding.top);
|
||||||
mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY);
|
mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY);
|
||||||
|
mFloatManager->PushState(&mFloatManagerStateBefore); // never popped
|
||||||
}
|
}
|
||||||
|
|
||||||
mReflowStatus = NS_FRAME_COMPLETE;
|
mReflowStatus = NS_FRAME_COMPLETE;
|
||||||
@ -139,16 +140,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
|||||||
mCurrentLine = aFrame->end_lines();
|
mCurrentLine = aFrame->end_lines();
|
||||||
|
|
||||||
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(aReflowState.frame);
|
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
|
void
|
||||||
@ -198,6 +189,7 @@ nsBlockReflowState::FreeLineBox(nsLineBox* aLine)
|
|||||||
|
|
||||||
void
|
void
|
||||||
nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
||||||
|
const nsRect& aFloatAvailableSpace,
|
||||||
nscoord& aLeftResult,
|
nscoord& aLeftResult,
|
||||||
nscoord& aRightResult,
|
nscoord& aRightResult,
|
||||||
nsBlockFrame::
|
nsBlockFrame::
|
||||||
@ -208,13 +200,13 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
|||||||
// only give it free space. An example is a table frame - the
|
// only give it free space. An example is a table frame - the
|
||||||
// tables do not flow around floats.
|
// tables do not flow around floats.
|
||||||
// However, we can let its margins intersect floats.
|
// However, we can let its margins intersect floats.
|
||||||
NS_ASSERTION(mAvailSpaceRect.x >= 0, "bad avail space rect x");
|
NS_ASSERTION(aFloatAvailableSpace.x >= 0, "bad avail space rect x");
|
||||||
NS_ASSERTION(mAvailSpaceRect.width == 0 ||
|
NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
|
||||||
mAvailSpaceRect.XMost() <= mContentArea.width,
|
aFloatAvailableSpace.XMost() <= mContentArea.width,
|
||||||
"bad avail space rect width");
|
"bad avail space rect width");
|
||||||
|
|
||||||
nscoord leftOffset, rightOffset;
|
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.
|
// We don't need to compute margins when there are no floats around.
|
||||||
leftOffset = 0;
|
leftOffset = 0;
|
||||||
rightOffset = 0;
|
rightOffset = 0;
|
||||||
@ -231,12 +223,13 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
|||||||
aReplacedWidth->marginRight == os.mComputedMargin.right),
|
aReplacedWidth->marginRight == os.mComputedMargin.right),
|
||||||
"unexpected aReplacedWidth");
|
"unexpected aReplacedWidth");
|
||||||
|
|
||||||
nscoord leftFloatXOffset = mAvailSpaceRect.x;
|
nscoord leftFloatXOffset = aFloatAvailableSpace.x;
|
||||||
leftOffset = PR_MAX(leftFloatXOffset, os.mComputedMargin.left) -
|
leftOffset = PR_MAX(leftFloatXOffset, os.mComputedMargin.left) -
|
||||||
(aReplacedWidth ? aReplacedWidth->marginLeft
|
(aReplacedWidth ? aReplacedWidth->marginLeft
|
||||||
: os.mComputedMargin.left);
|
: os.mComputedMargin.left);
|
||||||
leftOffset = PR_MAX(leftOffset, 0); // in case of negative margin
|
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) -
|
rightOffset = PR_MAX(rightFloatXOffset, os.mComputedMargin.right) -
|
||||||
(aReplacedWidth ? aReplacedWidth->marginRight
|
(aReplacedWidth ? aReplacedWidth->marginRight
|
||||||
: os.mComputedMargin.right);
|
: os.mComputedMargin.right);
|
||||||
@ -252,11 +245,13 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
|||||||
void
|
void
|
||||||
nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
const nsStyleDisplay* aDisplay,
|
const nsStyleDisplay* aDisplay,
|
||||||
|
const nsFlowAreaRect& aFloatAvailableSpace,
|
||||||
PRBool aBlockAvoidsFloats,
|
PRBool aBlockAvoidsFloats,
|
||||||
nsRect& aResult)
|
nsRect& aResult)
|
||||||
{
|
{
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
#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
|
#endif
|
||||||
aResult.y = mY;
|
aResult.y = mY;
|
||||||
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
||||||
@ -284,7 +279,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
|||||||
!aBlockAvoidsFloats,
|
!aBlockAvoidsFloats,
|
||||||
"unexpected replaced width");
|
"unexpected replaced width");
|
||||||
if (!aBlockAvoidsFloats) {
|
if (!aBlockAvoidsFloats) {
|
||||||
if (mBandHasFloats) {
|
if (aFloatAvailableSpace.mHasFloats) {
|
||||||
// Use the float-edge property to determine how the child block
|
// Use the float-edge property to determine how the child block
|
||||||
// will interact with the float.
|
// will interact with the float.
|
||||||
const nsStyleBorder* borderStyle = aFrame->GetStyleBorder();
|
const nsStyleBorder* borderStyle = aFrame->GetStyleBorder();
|
||||||
@ -300,8 +295,8 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
|||||||
{
|
{
|
||||||
// The child block's margins should be placed adjacent to,
|
// The child block's margins should be placed adjacent to,
|
||||||
// but not overlap the float.
|
// but not overlap the float.
|
||||||
aResult.x = mAvailSpaceRect.x + borderPadding.left;
|
aResult.x = aFloatAvailableSpace.mRect.x + borderPadding.left;
|
||||||
aResult.width = mAvailSpaceRect.width;
|
aResult.width = aFloatAvailableSpace.mRect.width;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -319,11 +314,14 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
|||||||
nsBlockFrame::ReplacedElementWidthToClear *replacedWidth = nsnull;
|
nsBlockFrame::ReplacedElementWidthToClear *replacedWidth = nsnull;
|
||||||
if (aFrame->GetType() == nsGkAtoms::tableOuterFrame) {
|
if (aFrame->GetType() == nsGkAtoms::tableOuterFrame) {
|
||||||
replacedWidth = &replacedWidthStruct;
|
replacedWidth = &replacedWidthStruct;
|
||||||
replacedWidthStruct = nsBlockFrame::WidthToClearPastFloats(*this, aFrame);
|
replacedWidthStruct =
|
||||||
|
nsBlockFrame::WidthToClearPastFloats(*this, aFloatAvailableSpace.mRect,
|
||||||
|
aFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
nscoord leftOffset, rightOffset;
|
nscoord leftOffset, rightOffset;
|
||||||
ComputeReplacedBlockOffsetsForFloats(aFrame, leftOffset, rightOffset,
|
ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect,
|
||||||
|
leftOffset, rightOffset,
|
||||||
replacedWidth);
|
replacedWidth);
|
||||||
aResult.x = borderPadding.left + leftOffset;
|
aResult.x = borderPadding.left + leftOffset;
|
||||||
aResult.width = mContentArea.width - leftOffset - rightOffset;
|
aResult.width = mContentArea.width - leftOffset - rightOffset;
|
||||||
@ -334,8 +332,10 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
nsFlowAreaRect
|
||||||
nsBlockReflowState::GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint)
|
nsBlockReflowState::GetFloatAvailableSpaceWithState(
|
||||||
|
nscoord aY, PRBool aRelaxHeightConstraint,
|
||||||
|
nsFloatManager::SavedState *aState) const
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Verify that the caller setup the coordinate system properly
|
// Verify that the caller setup the coordinate system properly
|
||||||
@ -345,27 +345,24 @@ nsBlockReflowState::GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint)
|
|||||||
"bad coord system");
|
"bad coord system");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRBool hasFloats;
|
nsFlowAreaRect result =
|
||||||
mAvailSpaceRect =
|
|
||||||
mFloatManager->GetBand(aY - BorderPadding().top,
|
mFloatManager->GetBand(aY - BorderPadding().top,
|
||||||
aRelaxHeightConstraint ? nscoord_MAX
|
aRelaxHeightConstraint ? nscoord_MAX
|
||||||
: mContentArea.height,
|
: mContentArea.height,
|
||||||
mContentArea.width,
|
mContentArea.width, aState);
|
||||||
&hasFloats);
|
|
||||||
mBandHasFloats = hasFloats;
|
|
||||||
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
||||||
if (mAvailSpaceRect.width < 0)
|
if (result.mRect.width < 0)
|
||||||
mAvailSpaceRect.width = 0;
|
result.mRect.width = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (nsBlockFrame::gNoisyReflow) {
|
if (nsBlockFrame::gNoisyReflow) {
|
||||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||||
printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n",
|
printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n",
|
||||||
mAvailSpaceRect.x, mAvailSpaceRect.y,
|
result.mRect.x, result.mRect.y, result.mRect.width,
|
||||||
mAvailSpaceRect.width, mAvailSpaceRect.height,
|
result.mRect.height, result.mHasFloats);
|
||||||
mBandHasFloats);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -524,17 +521,6 @@ nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsBlockReflowState::IsImpactedByFloat() const
|
|
||||||
{
|
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
|
||||||
printf("nsBlockReflowState::IsImpactedByFloat %p returned %d\n",
|
|
||||||
this, mBandHasFloats);
|
|
||||||
#endif
|
|
||||||
return mBandHasFloats;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsBlockReflowState::InitFloat(nsLineLayout& aLineLayout,
|
nsBlockReflowState::InitFloat(nsLineLayout& aLineLayout,
|
||||||
nsPlaceholderFrame* aPlaceholder,
|
nsPlaceholderFrame* aPlaceholder,
|
||||||
@ -575,6 +561,17 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
|||||||
nsFloatCache* fc = mFloatCacheFreeList.Alloc();
|
nsFloatCache* fc = mFloatCacheFreeList.Alloc();
|
||||||
fc->mPlaceholder = aPlaceholder;
|
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;
|
PRBool placed;
|
||||||
|
|
||||||
// Now place the float immediately if possible. Otherwise stash it
|
// Now place the float immediately if possible. Otherwise stash it
|
||||||
@ -582,20 +579,11 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
|||||||
// If one or more floats has already been pushed to the next line,
|
// 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
|
// don't let this one go on the current line, since that would violate
|
||||||
// float ordering.
|
// float ordering.
|
||||||
|
nsRect floatAvailableSpace = GetFloatAvailableSpace().mRect;
|
||||||
if (mBelowCurrentLineFloats.IsEmpty() &&
|
if (mBelowCurrentLineFloats.IsEmpty() &&
|
||||||
(aLineLayout.LineIsEmpty() ||
|
(aLineLayout.LineIsEmpty() ||
|
||||||
mBlock->ComputeFloatWidth(*this, aPlaceholder) <= aAvailableWidth)) {
|
mBlock->ComputeFloatWidth(*this, floatAvailableSpace, aPlaceholder) <=
|
||||||
// Because we are in the middle of reflowing a placeholder frame
|
aAvailableWidth)) {
|
||||||
// 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);
|
|
||||||
|
|
||||||
// And then place it
|
// And then place it
|
||||||
PRBool isLeftFloat;
|
PRBool isLeftFloat;
|
||||||
// force it to fit if we're at the top of the block and we can't
|
// force it to fit if we're at the top of the block and we can't
|
||||||
@ -606,9 +594,11 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
|||||||
"If we asked for force-fit, it should have been placed");
|
"If we asked for force-fit, it should have been placed");
|
||||||
if (forceFit || (placed && !NS_FRAME_IS_TRUNCATED(aReflowStatus))) {
|
if (forceFit || (placed && !NS_FRAME_IS_TRUNCATED(aReflowStatus))) {
|
||||||
// Pass on updated available space to the current inline reflow engine
|
// Pass on updated available space to the current inline reflow engine
|
||||||
GetAvailableSpace(mY, forceFit);
|
nsFlowAreaRect floatAvailSpace =
|
||||||
nsRect availSpace(nsPoint(mAvailSpaceRect.x + BorderPadding().left, mY),
|
GetFloatAvailableSpace(mY, forceFit);
|
||||||
mAvailSpaceRect.Size());
|
nsRect availSpace(nsPoint(floatAvailSpace.mRect.x + BorderPadding().left,
|
||||||
|
mY),
|
||||||
|
floatAvailSpace.mRect.Size());
|
||||||
aLineLayout.UpdateBand(availSpace, isLeftFloat,
|
aLineLayout.UpdateBand(availSpace, isLeftFloat,
|
||||||
aPlaceholder->GetOutOfFlowFrame());
|
aPlaceholder->GetOutOfFlowFrame());
|
||||||
|
|
||||||
@ -632,9 +622,6 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
|||||||
}
|
}
|
||||||
delete fc;
|
delete fc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore coordinate system
|
|
||||||
mFloatManager->Translate(dx, dy);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Always claim to be placed; we don't know whether we fit yet, so we
|
// Always claim to be placed; we don't know whether we fit yet, so we
|
||||||
@ -656,19 +643,24 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore coordinate system
|
||||||
|
mFloatManager->Translate(dx, dy);
|
||||||
|
|
||||||
return placed;
|
return placed;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats,
|
||||||
PRUint8 aFloats, PRBool aForceFit)
|
const nsFlowAreaRect& aFloatAvailableSpace,
|
||||||
|
PRBool aForceFit)
|
||||||
{
|
{
|
||||||
// If the current Y coordinate is not impacted by any floats
|
// If the current Y coordinate is not impacted by any floats
|
||||||
// then by definition the float fits.
|
// then by definition the float fits.
|
||||||
PRBool result = PR_TRUE;
|
PRBool result = PR_TRUE;
|
||||||
if (mBandHasFloats) {
|
if (aFloatAvailableSpace.mHasFloats) {
|
||||||
// XXX We should allow overflow by up to half a pixel here (bug 21193).
|
// 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
|
// The available width is too narrow (and its been impacted by a
|
||||||
// prior float)
|
// prior float)
|
||||||
result = PR_FALSE;
|
result = PR_FALSE;
|
||||||
@ -681,7 +673,8 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
|||||||
// At this point we know that there is enough horizontal space for
|
// At this point we know that there is enough horizontal space for
|
||||||
// the float (somewhere). Lets see if there is enough vertical
|
// the float (somewhere). Lets see if there is enough vertical
|
||||||
// space.
|
// space.
|
||||||
if (NSCoordGreaterThan(aFloatSize.height, mAvailSpaceRect.height)) {
|
if (NSCoordGreaterThan(aFloatSize.height,
|
||||||
|
aFloatAvailableSpace.mRect.height)) {
|
||||||
// The available height is too short. However, its possible that
|
// The available height is too short. However, its possible that
|
||||||
// there is enough open space below which is not impacted by a
|
// there is enough open space below which is not impacted by a
|
||||||
// float.
|
// float.
|
||||||
@ -692,16 +685,16 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
|||||||
// here.
|
// here.
|
||||||
nscoord xa;
|
nscoord xa;
|
||||||
if (NS_STYLE_FLOAT_LEFT == aFloats) {
|
if (NS_STYLE_FLOAT_LEFT == aFloats) {
|
||||||
xa = mAvailSpaceRect.x;
|
xa = aFloatAvailableSpace.mRect.x;
|
||||||
}
|
}
|
||||||
else {
|
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
|
// 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
|
// XXXldb This seems wrong, but we might want to fix bug 6976
|
||||||
// first.
|
// first.
|
||||||
if (xa < mAvailSpaceRect.x) {
|
if (xa < aFloatAvailableSpace.mRect.x) {
|
||||||
xa = mAvailSpaceRect.x;
|
xa = aFloatAvailableSpace.mRect.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nscoord xb = xa + aFloatSize.width;
|
nscoord xb = xa + aFloatSize.width;
|
||||||
@ -721,19 +714,21 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
|||||||
nscoord yb = ya + aFloatSize.height;
|
nscoord yb = ya + aFloatSize.height;
|
||||||
|
|
||||||
nscoord saveY = mY;
|
nscoord saveY = mY;
|
||||||
|
nsFlowAreaRect floatAvailableSpace(aFloatAvailableSpace);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Get the available space at the new Y coordinate
|
// 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.
|
// there is no more available space. We lose.
|
||||||
result = PR_FALSE;
|
result = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mY += mAvailSpaceRect.height;
|
mY += floatAvailableSpace.mRect.height;
|
||||||
GetAvailableSpace(mY, aForceFit);
|
floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
|
||||||
|
|
||||||
if (mBandHasFloats) {
|
if (floatAvailableSpace.mHasFloats) {
|
||||||
if ((xa < mAvailSpaceRect.x) || (xb > mAvailSpaceRect.XMost())) {
|
if (xa < floatAvailableSpace.mRect.x ||
|
||||||
|
xb > floatAvailableSpace.mRect.XMost()) {
|
||||||
// The float can't go here.
|
// The float can't go here.
|
||||||
result = PR_FALSE;
|
result = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
@ -741,17 +736,15 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See if there is now enough height for the float.
|
// 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
|
// Winner. The bottom Y coordinate of the float is in
|
||||||
// this band.
|
// this band.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore Y coordinate and available space information
|
// Restore Y coordinate
|
||||||
// regardless of the outcome.
|
|
||||||
mY = saveY;
|
mY = saveY;
|
||||||
GetAvailableSpace(mY, aForceFit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -792,14 +785,15 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
|||||||
mY = ClearFloats(mY, floatDisplay->mBreakType);
|
mY = ClearFloats(mY, floatDisplay->mBreakType);
|
||||||
}
|
}
|
||||||
// Get the band of available space
|
// Get the band of available space
|
||||||
GetAvailableSpace(mY, aForceFit);
|
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
|
||||||
|
|
||||||
NS_ASSERTION(floatFrame->GetParent() == mBlock,
|
NS_ASSERTION(floatFrame->GetParent() == mBlock,
|
||||||
"Float frame has wrong parent");
|
"Float frame has wrong parent");
|
||||||
|
|
||||||
// Reflow the float
|
// Reflow the float
|
||||||
nsMargin floatMargin;
|
nsMargin floatMargin;
|
||||||
mBlock->ReflowFloat(*this, placeholder, floatMargin, aReflowStatus);
|
mBlock->ReflowFloat(*this, floatAvailableSpace.mRect, placeholder,
|
||||||
|
floatMargin, aReflowStatus);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (nsBlockFrame::gNoisyReflow) {
|
if (nsBlockFrame::gNoisyReflow) {
|
||||||
@ -825,8 +819,9 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
|||||||
// Can the float fit here?
|
// Can the float fit here?
|
||||||
PRBool keepFloatOnSameLine = PR_FALSE;
|
PRBool keepFloatOnSameLine = PR_FALSE;
|
||||||
|
|
||||||
while (!CanPlaceFloat(floatSize, floatDisplay->mFloats, aForceFit)) {
|
while (!CanPlaceFloat(floatSize, floatDisplay->mFloats, floatAvailableSpace,
|
||||||
if (mAvailSpaceRect.height <= 0) {
|
aForceFit)) {
|
||||||
|
if (floatAvailableSpace.mRect.height <= 0) {
|
||||||
// No space, nowhere to put anything.
|
// No space, nowhere to put anything.
|
||||||
mY = saveY;
|
mY = saveY;
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
@ -836,8 +831,8 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
|||||||
if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
|
if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
|
||||||
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
|
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
|
||||||
|
|
||||||
mY += mAvailSpaceRect.height;
|
mY += floatAvailableSpace.mRect.height;
|
||||||
GetAvailableSpace(mY, aForceFit);
|
floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
|
||||||
} else {
|
} else {
|
||||||
// This quirk matches the one in nsBlockFrame::ReflowFloat
|
// This quirk matches the one in nsBlockFrame::ReflowFloat
|
||||||
// IE handles float tables in a very special way
|
// IE handles float tables in a very special way
|
||||||
@ -875,13 +870,14 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the table does not fit anymore in this line so advance to next band
|
// the table does not fit anymore in this line so advance to next band
|
||||||
mY += mAvailSpaceRect.height;
|
mY += floatAvailableSpace.mRect.height;
|
||||||
GetAvailableSpace(mY, aForceFit);
|
floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
|
||||||
// reflow the float again now since we have more space
|
// reflow the float again now since we have more space
|
||||||
// XXXldb We really don't need to Reflow in a loop, we just need
|
// XXXldb We really don't need to Reflow in a loop, we just need
|
||||||
// to ComputeSize in a loop (once ComputeSize depends on
|
// to ComputeSize in a loop (once ComputeSize depends on
|
||||||
// availableWidth, which should make this work again).
|
// 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
|
// Get the floats bounding box and margin information
|
||||||
floatSize = floatFrame->GetSize() +
|
floatSize = floatFrame->GetSize() +
|
||||||
nsSize(floatMargin.LeftRight(), floatMargin.TopBottom());
|
nsSize(floatMargin.LeftRight(), floatMargin.TopBottom());
|
||||||
@ -900,18 +896,18 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
|||||||
nscoord floatX, floatY;
|
nscoord floatX, floatY;
|
||||||
if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
|
if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
|
||||||
isLeftFloat = PR_TRUE;
|
isLeftFloat = PR_TRUE;
|
||||||
floatX = mAvailSpaceRect.x;
|
floatX = floatAvailableSpace.mRect.x;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isLeftFloat = PR_FALSE;
|
isLeftFloat = PR_FALSE;
|
||||||
if (!keepFloatOnSameLine) {
|
if (!keepFloatOnSameLine) {
|
||||||
floatX = mAvailSpaceRect.XMost() - floatSize.width;
|
floatX = floatAvailableSpace.mRect.XMost() - floatSize.width;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// this is the IE quirk (see few lines above)
|
// this is the IE quirk (see few lines above)
|
||||||
// the table is kept in the same line: don't let it overlap the
|
// the table is kept in the same line: don't let it overlap the
|
||||||
// previous float
|
// previous float
|
||||||
floatX = mAvailSpaceRect.x;
|
floatX = floatAvailableSpace.mRect.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*aIsLeftFloat = isLeftFloat;
|
*aIsLeftFloat = isLeftFloat;
|
||||||
@ -1105,22 +1101,25 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
|
|||||||
|
|
||||||
if (aReplacedBlock) {
|
if (aReplacedBlock) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
GetAvailableSpace(newY, PR_FALSE);
|
nsFlowAreaRect floatAvailableSpace =
|
||||||
|
GetFloatAvailableSpace(newY, PR_FALSE);
|
||||||
nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
|
nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
|
||||||
nsBlockFrame::WidthToClearPastFloats(*this, aReplacedBlock);
|
nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
|
||||||
if (!mBandHasFloats ||
|
aReplacedBlock);
|
||||||
PR_MAX(mAvailSpaceRect.x, replacedWidth.marginLeft) +
|
if (!floatAvailableSpace.mHasFloats ||
|
||||||
|
PR_MAX(floatAvailableSpace.mRect.x, replacedWidth.marginLeft) +
|
||||||
replacedWidth.borderBoxWidth +
|
replacedWidth.borderBoxWidth +
|
||||||
PR_MAX(mContentArea.width -
|
PR_MAX(mContentArea.width -
|
||||||
PR_MIN(mContentArea.width, mAvailSpaceRect.XMost()),
|
PR_MIN(mContentArea.width,
|
||||||
|
floatAvailableSpace.mRect.XMost()),
|
||||||
replacedWidth.marginRight) <=
|
replacedWidth.marginRight) <=
|
||||||
mContentArea.width) {
|
mContentArea.width) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames
|
// 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.
|
// See if there's room in the next band.
|
||||||
newY += mAvailSpaceRect.height;
|
newY += floatAvailableSpace.mRect.height;
|
||||||
} else {
|
} else {
|
||||||
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
|
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
|
||||||
// Stop trying to clear here; we'll just get pushed to the
|
// Stop trying to clear here; we'll just get pushed to the
|
||||||
@ -1131,11 +1130,6 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
|
|||||||
newY += 1;
|
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
|
#ifdef DEBUG
|
||||||
|
@ -83,12 +83,23 @@ public:
|
|||||||
void SetupOverflowPlaceholdersProperty();
|
void SetupOverflowPlaceholdersProperty();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the available reflow space for the current y coordinate. The
|
* Get the available reflow space (the area not occupied by floats)
|
||||||
* available space is relative to our coordinate system (0,0) is our
|
* for the current y coordinate. The available space is relative to
|
||||||
* upper left corner.
|
* 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); }
|
nsFlowAreaRect GetFloatAvailableSpace() const
|
||||||
void GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint);
|
{ 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
|
* The following functions all return PR_TRUE if they were able to
|
||||||
@ -104,7 +115,9 @@ public:
|
|||||||
PRBool aInitialReflow,
|
PRBool aInitialReflow,
|
||||||
nscoord aAvailableWidth,
|
nscoord aAvailableWidth,
|
||||||
nsReflowStatus& aReflowStatus);
|
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 FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||||
PRBool* aIsLeftFloat,
|
PRBool* aIsLeftFloat,
|
||||||
nsReflowStatus& aReflowStatus,
|
nsReflowStatus& aReflowStatus,
|
||||||
@ -149,6 +162,7 @@ public:
|
|||||||
// (which need not be the current mY). Callers need only pass
|
// (which need not be the current mY). Callers need only pass
|
||||||
// aReplacedWidth for outer table frames.
|
// aReplacedWidth for outer table frames.
|
||||||
void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
||||||
|
const nsRect& aFloatAvailableSpace,
|
||||||
nscoord& aLeftResult,
|
nscoord& aLeftResult,
|
||||||
nscoord& aRightResult,
|
nscoord& aRightResult,
|
||||||
nsBlockFrame::ReplacedElementWidthToClear
|
nsBlockFrame::ReplacedElementWidthToClear
|
||||||
@ -157,6 +171,7 @@ public:
|
|||||||
// Caller must have called GetAvailableSpace for the current mY
|
// Caller must have called GetAvailableSpace for the current mY
|
||||||
void ComputeBlockAvailSpace(nsIFrame* aFrame,
|
void ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
const nsStyleDisplay* aDisplay,
|
const nsStyleDisplay* aDisplay,
|
||||||
|
const nsFlowAreaRect& aFloatAvailableSpace,
|
||||||
PRBool aBlockAvoidsFloats,
|
PRBool aBlockAvoidsFloats,
|
||||||
nsRect& aResult);
|
nsRect& aResult);
|
||||||
|
|
||||||
@ -174,8 +189,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool IsImpactedByFloat() const;
|
|
||||||
|
|
||||||
nsLineBox* NewLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock);
|
nsLineBox* NewLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock);
|
||||||
|
|
||||||
void FreeLineBox(nsLineBox* aLine);
|
void FreeLineBox(nsLineBox* aLine);
|
||||||
@ -204,12 +217,11 @@ public:
|
|||||||
// XXX get rid of this
|
// XXX get rid of this
|
||||||
nsReflowStatus mReflowStatus;
|
nsReflowStatus mReflowStatus;
|
||||||
|
|
||||||
// The x-position we should place an outside bullet relative to.
|
// The float manager state as it was before the contents of this
|
||||||
// This is the border-box edge of the principal box. However, if a line box
|
// block. This is needed for positioning bullets, since we only want
|
||||||
// would be displaced by floats, we want to displace it by the same amount.
|
// to move the bullet to flow around floats that were before this
|
||||||
// That is, we act as though the edge of the floats is the content-edge of
|
// block, not floats inside of it.
|
||||||
// the block, displaced by the block's padding and border.
|
nsFloatManager::SavedState mFloatManagerStateBefore;
|
||||||
nscoord mOutsideBulletX;
|
|
||||||
|
|
||||||
nscoord mBottomEdge;
|
nscoord mBottomEdge;
|
||||||
|
|
||||||
@ -250,10 +262,6 @@ public:
|
|||||||
// The current Y coordinate in the block
|
// The current Y coordinate in the block
|
||||||
nscoord mY;
|
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
|
// The combined area of all floats placed so far
|
||||||
nsRect mFloatCombinedArea;
|
nsRect mFloatCombinedArea;
|
||||||
|
|
||||||
@ -296,11 +304,6 @@ public:
|
|||||||
|
|
||||||
PRUint8 mFloatBreakType;
|
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)
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
@ -135,11 +135,11 @@ void nsFloatManager::Shutdown()
|
|||||||
sCachedFloatManagerCount = -1;
|
sCachedFloatManagerCount = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRect
|
nsFlowAreaRect
|
||||||
nsFloatManager::GetBand(nscoord aYOffset,
|
nsFloatManager::GetBand(nscoord aYOffset,
|
||||||
nscoord aMaxHeight,
|
nscoord aMaxHeight,
|
||||||
nscoord aContentAreaWidth,
|
nscoord aContentAreaWidth,
|
||||||
PRBool* aHasFloats) const
|
SavedState* aState) const
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aMaxHeight >= 0, "unexpected max height");
|
NS_ASSERTION(aMaxHeight >= 0, "unexpected max height");
|
||||||
NS_ASSERTION(aContentAreaWidth >= 0, "unexpected content area width");
|
NS_ASSERTION(aContentAreaWidth >= 0, "unexpected content area width");
|
||||||
@ -150,14 +150,23 @@ nsFloatManager::GetBand(nscoord aYOffset,
|
|||||||
top = nscoord_MIN;
|
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
|
// If there are no floats at all, or we're below the last one, return
|
||||||
// quickly.
|
// quickly.
|
||||||
PRUint32 floatCount = mFloats.Length();
|
|
||||||
if (floatCount == 0 ||
|
if (floatCount == 0 ||
|
||||||
(mFloats[floatCount-1].mLeftYMost <= top &&
|
(mFloats[floatCount-1].mLeftYMost <= top &&
|
||||||
mFloats[floatCount-1].mRightYMost <= top)) {
|
mFloats[floatCount-1].mRightYMost <= top)) {
|
||||||
*aHasFloats = PR_FALSE;
|
return nsFlowAreaRect(0, aYOffset, aContentAreaWidth, aMaxHeight, PR_FALSE);
|
||||||
return nsRect(0, aYOffset, aContentAreaWidth, aMaxHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nscoord bottom;
|
nscoord bottom;
|
||||||
@ -180,7 +189,7 @@ nsFloatManager::GetBand(nscoord aYOffset,
|
|||||||
// Walk backwards through the floats until we either hit the front of
|
// Walk backwards through the floats until we either hit the front of
|
||||||
// the list or we're above |top|.
|
// the list or we're above |top|.
|
||||||
PRBool haveFloats = PR_FALSE;
|
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];
|
const FloatInfo &fi = mFloats[i-1];
|
||||||
if (fi.mLeftYMost <= top && fi.mRightYMost <= top) {
|
if (fi.mLeftYMost <= top && fi.mRightYMost <= top) {
|
||||||
// There aren't any more floats that could intersect this band.
|
// There aren't any more floats that could intersect this band.
|
||||||
@ -230,9 +239,8 @@ nsFloatManager::GetBand(nscoord aYOffset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*aHasFloats = haveFloats;
|
|
||||||
nscoord height = (bottom == nscoord_MAX) ? nscoord_MAX : (bottom - top);
|
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
|
nsresult
|
||||||
|
@ -52,6 +52,22 @@ class nsIFrame;
|
|||||||
struct nsHTMLReflowState;
|
struct nsHTMLReflowState;
|
||||||
class nsPresContext;
|
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
|
#define NS_FLOAT_MANAGER_CACHE_SIZE 4
|
||||||
|
|
||||||
class nsFloatManager {
|
class nsFloatManager {
|
||||||
@ -64,6 +80,18 @@ public:
|
|||||||
|
|
||||||
static void Shutdown();
|
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
|
* Translate the current origin by the specified (dx, dy). This
|
||||||
* creates a new local coordinate space relative to the current
|
* creates a new local coordinate space relative to the current
|
||||||
@ -92,18 +120,21 @@ public:
|
|||||||
* @param aMaxHeight [in] maximum height of available space desired
|
* @param aMaxHeight [in] maximum height of available space desired
|
||||||
* @param aContentAreaWidth [in] the width of the content area (whose left
|
* @param aContentAreaWidth [in] the width of the content area (whose left
|
||||||
* edge must be zero in the current translation)
|
* edge must be zero in the current translation)
|
||||||
* @param aHasFloats [out] whether there are floats at the sides of
|
* @param aState [in] If null, use the current state, otherwise, do
|
||||||
* the return value including those that do not
|
* computation based only on floats present in the given
|
||||||
* reduce the line box width at all (because they
|
* saved state.
|
||||||
* are entirely in the margins)
|
* @return An nsFlowAreaRect whose:
|
||||||
* @return the resulting rectangle for line boxes. It will not go
|
* mRect is the resulting rectangle for line boxes. It will not go
|
||||||
* left of 0, nor right of aContentAreaWidth, but will be
|
* left of 0, nor right of aContentAreaWidth, but will be
|
||||||
* narrower when floats are present.
|
* 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
|
* aY and aAvailSpace are positioned relative to the current translation
|
||||||
*/
|
*/
|
||||||
nsRect GetBand(nscoord aY, nscoord aMaxHeight, nscoord aContentAreaWidth,
|
nsFlowAreaRect GetBand(nscoord aY, nscoord aMaxHeight,
|
||||||
PRBool* aHasFloats) const;
|
nscoord aContentAreaWidth, SavedState* aState) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a float that comes after all floats previously added. Its top
|
* Add a float that comes after all floats previously added. Its top
|
||||||
@ -128,18 +159,6 @@ private:
|
|||||||
struct FloatInfo;
|
struct FloatInfo;
|
||||||
public:
|
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(); }
|
PRBool HasAnyFloats() const { return !mFloats.IsEmpty(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,7 +191,9 @@ public:
|
|||||||
* These states must be managed using stack discipline. PopState can only
|
* 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 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.
|
* 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);
|
void PopState(SavedState* aState);
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
|
|
||||||
#include "nsTransform2D.h"
|
#include "nsTransform2D.h"
|
||||||
|
|
||||||
|
#include "gfxContext.h"
|
||||||
|
|
||||||
class nsDisplayItemCanvas : public nsDisplayItem {
|
class nsDisplayItemCanvas : public nsDisplayItem {
|
||||||
public:
|
public:
|
||||||
@ -224,6 +225,7 @@ void
|
|||||||
nsHTMLCanvasFrame::PaintCanvas(nsIRenderingContext& aRenderingContext,
|
nsHTMLCanvasFrame::PaintCanvas(nsIRenderingContext& aRenderingContext,
|
||||||
const nsRect& aDirtyRect, nsPoint aPt)
|
const nsRect& aDirtyRect, nsPoint aPt)
|
||||||
{
|
{
|
||||||
|
nsPresContext *presContext = PresContext();
|
||||||
nsRect inner = GetInnerArea() + aPt;
|
nsRect inner = GetInnerArea() + aPt;
|
||||||
|
|
||||||
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
|
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
|
||||||
@ -234,34 +236,24 @@ nsHTMLCanvasFrame::PaintCanvas(nsIRenderingContext& aRenderingContext,
|
|||||||
if (inner.width == 0 || inner.height == 0)
|
if (inner.width == 0 || inner.height == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nsIntSize canvasSize = GetCanvasSize();
|
nsIntSize sizeCSSPixels = GetCanvasSize();
|
||||||
nsSize sizeAppUnits(PresContext()->DevPixelsToAppUnits(canvasSize.width),
|
nsSize sizeAppUnits(nsPresContext::CSSPixelsToAppUnits(sizeCSSPixels.width),
|
||||||
PresContext()->DevPixelsToAppUnits(canvasSize.height));
|
nsPresContext::CSSPixelsToAppUnits(sizeCSSPixels.height));
|
||||||
|
|
||||||
// XXXvlad clip to aDirtyRect!
|
gfxContext *ctx = aRenderingContext.ThebesContext();
|
||||||
|
|
||||||
if (inner.Size() != sizeAppUnits)
|
gfxFloat sx = inner.width / (gfxFloat) sizeAppUnits.width;
|
||||||
{
|
gfxFloat sy = inner.height / (gfxFloat) sizeAppUnits.height;
|
||||||
float sx = inner.width / (float) sizeAppUnits.width;
|
|
||||||
float sy = inner.height / (float) sizeAppUnits.height;
|
|
||||||
|
|
||||||
aRenderingContext.PushState();
|
ctx->Save();
|
||||||
aRenderingContext.Translate(inner.x, inner.y);
|
|
||||||
aRenderingContext.Scale(sx, sy);
|
|
||||||
|
|
||||||
canvas->RenderContexts(aRenderingContext.ThebesContext());
|
ctx->Translate(gfxPoint(presContext->AppUnitsToGfxUnits(inner.x),
|
||||||
|
presContext->AppUnitsToGfxUnits(inner.y)));
|
||||||
|
ctx->Scale(sx, sy);
|
||||||
|
|
||||||
aRenderingContext.PopState();
|
canvas->RenderContexts(ctx);
|
||||||
} else {
|
|
||||||
//nsIRenderingContext::AutoPushTranslation(&aRenderingContext, px, py);
|
|
||||||
|
|
||||||
aRenderingContext.PushState();
|
ctx->Restore();
|
||||||
aRenderingContext.Translate(inner.x, inner.y);
|
|
||||||
|
|
||||||
canvas->RenderContexts(aRenderingContext.ThebesContext());
|
|
||||||
|
|
||||||
aRenderingContext.PopState();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
10
layout/reftests/bugs/428810-1-ltr-insets-ref.html
Normal file
10
layout/reftests/bugs/428810-1-ltr-insets-ref.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 20px"></div>
|
||||||
|
<div style="margin-left: 32px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
10
layout/reftests/bugs/428810-1-ltr-ref.html
Normal file
10
layout/reftests/bugs/428810-1-ltr-ref.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 20px"></div>
|
||||||
|
<div style="margin-left: 40px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
11
layout/reftests/bugs/428810-1-rtl-insets-ref.html
Normal file
11
layout/reftests/bugs/428810-1-rtl-insets-ref.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html dir="rtl">
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 20px"></div>
|
||||||
|
<div style="margin-right: 32px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
11
layout/reftests/bugs/428810-1-rtl-ref.html
Normal file
11
layout/reftests/bugs/428810-1-rtl-ref.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html dir="rtl">
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 20px"></div>
|
||||||
|
<div style="margin-right: 40px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
12
layout/reftests/bugs/428810-1a-ltr-insets.html
Normal file
12
layout/reftests/bugs/428810-1a-ltr-insets.html
Normal file
@ -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>
|
||||||
|
|
12
layout/reftests/bugs/428810-1a-ltr.html
Normal file
12
layout/reftests/bugs/428810-1a-ltr.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-1a-rtl-insets.html
Normal file
13
layout/reftests/bugs/428810-1a-rtl-insets.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-1a-rtl.html
Normal file
13
layout/reftests/bugs/428810-1a-rtl.html
Normal file
@ -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>
|
||||||
|
|
12
layout/reftests/bugs/428810-1b-ltr-insets.html
Normal file
12
layout/reftests/bugs/428810-1b-ltr-insets.html
Normal file
@ -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>
|
||||||
|
|
12
layout/reftests/bugs/428810-1b-ltr.html
Normal file
12
layout/reftests/bugs/428810-1b-ltr.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-1b-rtl-insets.html
Normal file
13
layout/reftests/bugs/428810-1b-rtl-insets.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-1b-rtl.html
Normal file
13
layout/reftests/bugs/428810-1b-rtl.html
Normal file
@ -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>
|
||||||
|
|
12
layout/reftests/bugs/428810-1c-ltr-insets.html
Normal file
12
layout/reftests/bugs/428810-1c-ltr-insets.html
Normal file
@ -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>
|
||||||
|
|
12
layout/reftests/bugs/428810-1c-ltr.html
Normal file
12
layout/reftests/bugs/428810-1c-ltr.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-1c-rtl-insets.html
Normal file
13
layout/reftests/bugs/428810-1c-rtl-insets.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-1c-rtl.html
Normal file
13
layout/reftests/bugs/428810-1c-rtl.html
Normal file
@ -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>
|
||||||
|
|
12
layout/reftests/bugs/428810-1d-ltr-insets.html
Normal file
12
layout/reftests/bugs/428810-1d-ltr-insets.html
Normal file
@ -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>
|
||||||
|
|
12
layout/reftests/bugs/428810-1d-ltr.html
Normal file
12
layout/reftests/bugs/428810-1d-ltr.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-1d-rtl-insets.html
Normal file
13
layout/reftests/bugs/428810-1d-rtl-insets.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-1d-rtl.html
Normal file
13
layout/reftests/bugs/428810-1d-rtl.html
Normal file
@ -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>
|
||||||
|
|
10
layout/reftests/bugs/428810-2-ltr-insets-ref.html
Normal file
10
layout/reftests/bugs/428810-2-ltr-insets-ref.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 20px"></div>
|
||||||
|
<div style="margin-left: 32px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
10
layout/reftests/bugs/428810-2-ltr-ref.html
Normal file
10
layout/reftests/bugs/428810-2-ltr-ref.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 20px"></div>
|
||||||
|
<div style="margin-left: 40px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
11
layout/reftests/bugs/428810-2-rtl-insets-ref.html
Normal file
11
layout/reftests/bugs/428810-2-rtl-insets-ref.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html dir="rtl">
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 20px"></div>
|
||||||
|
<div style="margin-right: 32px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
11
layout/reftests/bugs/428810-2-rtl-ref.html
Normal file
11
layout/reftests/bugs/428810-2-rtl-ref.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html dir="rtl">
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 20px"></div>
|
||||||
|
<div style="margin-right: 40px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
13
layout/reftests/bugs/428810-2a-ltr-insets.html
Normal file
13
layout/reftests/bugs/428810-2a-ltr-insets.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-2a-ltr.html
Normal file
13
layout/reftests/bugs/428810-2a-ltr.html
Normal file
@ -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>
|
||||||
|
|
14
layout/reftests/bugs/428810-2a-rtl-insets.html
Normal file
14
layout/reftests/bugs/428810-2a-rtl-insets.html
Normal file
@ -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>
|
||||||
|
|
14
layout/reftests/bugs/428810-2a-rtl.html
Normal file
14
layout/reftests/bugs/428810-2a-rtl.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-2b-ltr-insets.html
Normal file
13
layout/reftests/bugs/428810-2b-ltr-insets.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 6px">
|
||||||
|
<div style="float: left; height: 20px; width: 116px"></div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 70px; display: list-item; margin: 1px 1px 32px 32px; border: medium solid transparent; border-width: 2px 2px 16px 16px; padding: 4px 4px 8px 8px">
|
||||||
|
<div style="float: left; height: 20px; width: 15px"></div>
|
||||||
|
<div> </div>
|
||||||
|
</div>
|
||||||
|
|
13
layout/reftests/bugs/428810-2b-ltr.html
Normal file
13
layout/reftests/bugs/428810-2b-ltr.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 10px">
|
||||||
|
<div style="float: left; height: 20px; width: 100px"></div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-left: 40px; width: 70px; display: list-item;">
|
||||||
|
<div style="float: left; height: 20px; width: 15px"></div>
|
||||||
|
<div> </div>
|
||||||
|
</div>
|
||||||
|
|
14
layout/reftests/bugs/428810-2b-rtl-insets.html
Normal file
14
layout/reftests/bugs/428810-2b-rtl-insets.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html dir="rtl">
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 6px">
|
||||||
|
<div style="float: right; height: 20px; width: 116px"></div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 70px; display: list-item; margin: 1px 32px 32px 1px; border: medium solid transparent; border-width: 2px 16px 16px 2px; padding: 4px 8px 8px 4px">
|
||||||
|
<div style="float: right; height: 20px; width: 15px"></div>
|
||||||
|
<div> </div>
|
||||||
|
</div>
|
||||||
|
|
14
layout/reftests/bugs/428810-2b-rtl.html
Normal file
14
layout/reftests/bugs/428810-2b-rtl.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html dir="rtl">
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 10px">
|
||||||
|
<div style="float: right; height: 20px; width: 100px"></div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-right: 40px; width: 70px; display: list-item;">
|
||||||
|
<div style="float: right; height: 20px; width: 15px"></div>
|
||||||
|
<div> </div>
|
||||||
|
</div>
|
||||||
|
|
13
layout/reftests/bugs/428810-2e-ltr-insets.html
Normal file
13
layout/reftests/bugs/428810-2e-ltr-insets.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-2e-ltr.html
Normal file
13
layout/reftests/bugs/428810-2e-ltr.html
Normal file
@ -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>
|
||||||
|
|
14
layout/reftests/bugs/428810-2e-rtl-insets.html
Normal file
14
layout/reftests/bugs/428810-2e-rtl-insets.html
Normal file
@ -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>
|
||||||
|
|
14
layout/reftests/bugs/428810-2e-rtl.html
Normal file
14
layout/reftests/bugs/428810-2e-rtl.html
Normal file
@ -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>
|
||||||
|
|
12
layout/reftests/bugs/428810-2f-ltr-insets.html
Normal file
12
layout/reftests/bugs/428810-2f-ltr-insets.html
Normal file
@ -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>
|
||||||
|
|
12
layout/reftests/bugs/428810-2f-ltr.html
Normal file
12
layout/reftests/bugs/428810-2f-ltr.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-2f-rtl-insets.html
Normal file
13
layout/reftests/bugs/428810-2f-rtl-insets.html
Normal file
@ -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>
|
||||||
|
|
13
layout/reftests/bugs/428810-2f-rtl.html
Normal file
13
layout/reftests/bugs/428810-2f-rtl.html
Normal file
@ -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>
|
||||||
|
|
10
layout/reftests/bugs/428810-3-ltr-insets-ref.html
Normal file
10
layout/reftests/bugs/428810-3-ltr-insets-ref.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 40px"></div>
|
||||||
|
<div style="margin-left: 32px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
10
layout/reftests/bugs/428810-3-ltr-ref.html
Normal file
10
layout/reftests/bugs/428810-3-ltr-ref.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 40px"></div>
|
||||||
|
<div style="margin-left: 40px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
11
layout/reftests/bugs/428810-3-rtl-insets-ref.html
Normal file
11
layout/reftests/bugs/428810-3-rtl-insets-ref.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html dir="rtl">
|
||||||
|
<title>Testcase, bug 428810</title>
|
||||||
|
<style type="text/css">
|
||||||
|
html, body { margin: 0; padding: 0; }
|
||||||
|
</style>
|
||||||
|
<div style="height: 40px"></div>
|
||||||
|
<div style="margin-right: 32px; display: list-item;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user