merge commit for bug 399397

This commit is contained in:
Bob Clary 2008-07-24 00:52:24 -04:00
commit 5e4e630789
264 changed files with 24798 additions and 7300 deletions

View File

@ -2,3 +2,5 @@ df7a3c8ffeeaba229067efee5a20e21dae0dd877 MOZILLA_1_9_a4_BASE
4209e16b58411750ac73f761023e46b76b793e2c MOZILLA_1_9_a6_BASE
66a5c7bce7ee86a820d3c0d54fa07cb719be751c MOZILLA_1_9_a7_BASE
caeba7562e495a9f604984df0b48b6f99bec3e2e FENNEC_M4
9d9941eacb14827fdab4716710042fdde84eb60d FIREFOX_3_1a1_RELEASE
9d9941eacb14827fdab4716710042fdde84eb60d FIREFOX_3_1a1_BUILD1

View File

@ -92,35 +92,27 @@ cpp_quote("")
import "objidl.idl";
import "oaidl.idl";
const long DISPID_DOC_URL = -5904;
const long DISPID_DOC_TITLE = -5905;
const long DISPID_DOC_MIMETYPE = -5906;
const long DISPID_DOC_DOCTYPE = -5907;
const long DISPID_DOC_NAMESPACE = -5908;
const long DISPID_DOC_MEDIATYPES = -5909;
[object, uuid(0D68D6D0-D93D-4d08-A30D-F00DD1F45B24)]
interface ISimpleDOMDocument : IUnknown
{
[propget, id(DISPID_DOC_URL)] HRESULT URL(
[propget] HRESULT URL(
[out, retval] BSTR * url
);
[propget, id(DISPID_DOC_TITLE)] HRESULT title(
[propget] HRESULT title(
[out, retval] BSTR * title
);
[propget, id(DISPID_DOC_MIMETYPE)] HRESULT mimeType(
[propget] HRESULT mimeType(
[out, retval] BSTR * mimeType
);
[propget, id(DISPID_DOC_DOCTYPE)] HRESULT docType(
[propget] HRESULT docType(
[out, retval] BSTR * docType
);
[propget, id(DISPID_DOC_NAMESPACE)] HRESULT nameSpaceURIForID(
[propget] HRESULT nameSpaceURIForID(
[in] short nameSpaceID,
[out, retval] BSTR * nameSpaceURI
);
[propput, id(DISPID_DOC_MEDIATYPES)] HRESULT alternateViewMediaTypes(
[propput] HRESULT alternateViewMediaTypes(
[in] BSTR * commaSeparatedMediaTypes
);
}

View File

@ -133,13 +133,9 @@ cpp_quote("")
import "objidl.idl";
import "oaidl.idl";
const long DISPID_NODE_NODEINFO = -5900;
const long DISPID_NODE_ATTRIBUTES = -5901;
const long DISPID_NODE_ATTRIBUTESFORNAMES = -5902;
const long DISPID_NODE_COMPSTYLE = -5903;
const long DISPID_NODE_COMPSTYLEFORPROPS = -5904;
const long DISPID_NODE_LANGUAGE = -5905;
import "ISimpleDOMText.idl";
import "ISimpleDOMDocument.idl";
[object, uuid(1814ceeb-49e2-407f-af99-fa755a7d2607)]
interface ISimpleDOMNode : IUnknown
@ -157,7 +153,7 @@ interface ISimpleDOMNode : IUnknown
const unsigned short NODETYPE_DOCUMENT_FRAGMENT = 11;
const unsigned short NODETYPE_NOTATION = 12;
[propget, id(DISPID_NODE_NODEINFO)] HRESULT nodeInfo(
[propget] HRESULT nodeInfo(
[out] BSTR *nodeName, // for performance returns NULL for text nodes (true nodeName would be "#text")
[out] short *nameSpaceID,
[out] BSTR *nodeValue,
@ -166,7 +162,7 @@ interface ISimpleDOMNode : IUnknown
[out, retval] unsigned short *nodeType
);
[propget, id(DISPID_NODE_ATTRIBUTES)] HRESULT attributes(
[propget] HRESULT attributes(
[in] unsigned short maxAttribs,
[out, size_is(maxAttribs), length_is(*numAttribs)] BSTR *attribNames,
[out, size_is(maxAttribs), length_is(*numAttribs)] short *nameSpaceID,
@ -174,14 +170,14 @@ interface ISimpleDOMNode : IUnknown
[out, retval] unsigned short *numAttribs
);
[propget, id(DISPID_NODE_ATTRIBUTESFORNAMES)] HRESULT attributesForNames(
[propget] HRESULT attributesForNames(
[in] unsigned short numAttribs,
[in, size_is(numAttribs), length_is(numAttribs)] BSTR *attribNames,
[in, size_is(numAttribs), length_is(numAttribs)] short *nameSpaceID,
[out, retval, size_is(numAttribs), length_is(numAttribs)] BSTR *attribValues
);
[propget, id(DISPID_NODE_COMPSTYLE)] HRESULT computedStyle(
[propget] HRESULT computedStyle(
[in] unsigned short maxStyleProperties,
[in] boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes
[out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleProperties,
@ -189,7 +185,7 @@ interface ISimpleDOMNode : IUnknown
[out, retval] unsigned short *numStyleProperties
);
[propget, id(DISPID_NODE_COMPSTYLEFORPROPS)] HRESULT computedStyleForProperties(
[propget] HRESULT computedStyleForProperties(
[in] unsigned short numStyleProperties,
[in] boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes
[in, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleProperties,
@ -210,7 +206,18 @@ interface ISimpleDOMNode : IUnknown
[propget, local] HRESULT localInterface([out][retval] void **localInterface);
[propget, id(DISPID_NODE_LANGUAGE)] HRESULT language([out, retval] BSTR *language);
[propget] HRESULT language([out, retval] BSTR *language);
}
[
uuid(a6245497-9c0b-4449-85a5-bd6ad07df8ea),
helpstring("ISimpleDOM Type Library")
]
library ISimpleDOM
{
interface ISimpleDOMNode;
interface ISimpleDOMText;
interface ISimpleDOMDocument;
};

View File

@ -98,7 +98,7 @@ done_gen: ISimpleDOMNode.idl \
ISimpleDOMDocument.idl \
ISimpleDOMText.idl
$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMNode.idl
$(MIDL) $(MIDL_FLAGS) -I $(srcdir) -Oicf $(srcdir)/ISimpleDOMNode.idl
$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMDocument.idl
$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMText.idl
touch $@

View File

@ -191,8 +191,7 @@ NS_IMETHODIMP nsAccessNode::Init()
// so that nsDocAccessible::RefreshNodes() can find the anonymous subtree to release when
// the root node goes away
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
if (content && (content->IsNativeAnonymous() ||
content->GetBindingParent())) {
if (content && content->IsInAnonymousSubtree()) {
// Specific examples of where this is used: <input type="file"> and <xul:findbar>
nsCOMPtr<nsIAccessible> parentAccessible;
docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE, getter_AddRefs(parentAccessible));

View File

@ -792,11 +792,9 @@ nsAccUtils::FindNeighbourPointingToNode(nsIContent *aForNode,
nsIAtom *aTagName,
PRUint32 aAncestorLevelsToSearch)
{
nsCOMPtr<nsIContent> binding;
nsAutoString controlID;
if (!nsAccUtils::GetID(aForNode, controlID)) {
binding = aForNode->GetBindingParent();
if (binding == aForNode)
if (!aForNode->IsInAnonymousSubtree())
return nsnull;
aForNode->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::anonid, controlID);
@ -805,6 +803,7 @@ nsAccUtils::FindNeighbourPointingToNode(nsIContent *aForNode,
}
// Look for label in subtrees of nearby ancestors
nsCOMPtr<nsIContent> binding(aForNode->GetBindingParent());
PRUint32 count = 0;
nsIContent *labelContent = nsnull;
nsIContent *prevSearched = nsnull;

View File

@ -1760,9 +1760,8 @@ void nsDocAccessible::RefreshNodes(nsIDOMNode *aStartNode)
getter_AddRefs(childAccessNode));
childAccessNode->GetDOMNode(getter_AddRefs(possibleAnonNode));
nsCOMPtr<nsIContent> iterContent = do_QueryInterface(possibleAnonNode);
if (iterContent && (iterContent->IsNativeAnonymous() ||
iterContent->GetBindingParent())) {
// GetBindingParent() check is a perf win -- make sure we don't
if (iterContent && iterContent->IsInAnonymousSubtree()) {
// IsInAnonymousSubtree() check is a perf win -- make sure we don't
// shut down the same subtree twice since we'll reach non-anon content via
// DOM traversal later in this method
RefreshNodes(possibleAnonNode);

View File

@ -89,7 +89,8 @@ static nsCSSTextAttrMapItem gCSSTextAttrsMap[] = {
{ "text-decoration", "line-through", "text-line-through-style", "solid" },
{ "text-decoration", "underline", "text-underline-style", "solid" },
{ "text-align", kAnyValue, kCopyName, kCopyValue },
{ "text-indent", kAnyValue, kCopyName, kCopyValue }
{ "text-indent", kAnyValue, kCopyName, kCopyValue },
{ "vertical-align", kAnyValue, "text-position", kCopyValue }
};
nsCSSTextAttr::nsCSSTextAttr(PRBool aIncludeDefAttrValue, nsIDOMElement *aElm,

View File

@ -640,7 +640,9 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
if (findContent->IsNodeOfType(nsINode::eHTML) &&
findContent->NodeInfo()->Equals(nsAccessibilityAtoms::br)) {
nsIContent *parent = findContent->GetParent();
if (parent && parent->IsNativeAnonymous() && parent->GetChildCount() == 1) {
if (parent &&
parent->IsRootOfNativeAnonymousSubtree() &&
parent->GetChildCount() == 1) {
// This <br> is the only node in a text control, therefore it is the hacky
// "bogus node" used when there is no text in a control
*aHyperTextOffset = 0;

View File

@ -67,12 +67,13 @@
return;
}
var errorMsg = " for " + aID + "at offset " + aOffset;
is(startOffset.value, aStartOffset,
"Wrong start offset for " + aID);
"Wrong start offset" + errorMsg);
is(endOffset.value, aEndOffset,
"Wrong end offset for " + aID);
"Wrong end offset" + errorMsg);
compareTextAttrs(aID, attrs, aAttrs);
compareTextAttrs(errorMsg, attrs, aAttrs);
var defAttrs = null;
try{
@ -85,10 +86,10 @@
return;
}
compareTextAttrs(aID, defAttrs, aDefAttrs);
compareTextAttrs(errorMsg, defAttrs, aDefAttrs);
}
function compareTextAttrs(aID, aAttrs, aExpectedAttrs)
function compareTextAttrs(aErrorMsg, aAttrs, aExpectedAttrs)
{
var enumerate = aAttrs.enumerate();
while (enumerate.hasMoreElements()) {
@ -96,10 +97,11 @@
QueryInterface(Components.interfaces.nsIPropertyElement);
if (!(prop.key in aExpectedAttrs))
ok(false, "Unexpected attribute '" + prop.key + "' for " + aID);
ok(false,
"Unexpected attribute '" + prop.key + "'" + aErrorMsg);
else
is(prop.value, aExpectedAttrs[prop.key],
"Attribute '" + prop.key + "' has wrong value for " + aID);
"Attribute '" + prop.key + "' has wrong value" + aErrorMsg);
}
for (var name in aExpectedAttrs) {
@ -110,7 +112,8 @@
}
if (!value)
ok(false, "There is no expected attribute '" + name + "' for " + aID);
ok(false,
"There is no expected attribute '" + name + "'" + aErrorMsg);
}
}
@ -142,7 +145,7 @@
gObserverService.addObserver(gA11yEventObserver, "accessible-event",
false);
ID = "area7";
ID = "area8";
var node = document.getElementById(ID);
node.focus();
@ -161,7 +164,8 @@
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "Lucida Grande"
"font-family": "Lucida Grande",
"text-position": "baseline"
};
var attrs = { "background-color": "transparent" };
@ -201,7 +205,8 @@
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif"
"font-family": "serif",
"text-position": "baseline"
};
var attrs = {};
@ -224,7 +229,8 @@
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif"
"font-family": "serif",
"text-position": "baseline"
};
attrs = {};
@ -253,7 +259,8 @@
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif"
"font-family": "serif",
"text-position": "baseline"
};
attrs = {"color": "rgb(0, 128, 0)"};
@ -276,7 +283,8 @@
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif"
"font-family": "serif",
"text-position": "baseline"
};
attrs = {"color": "rgb(0, 128, 0)"};
@ -299,7 +307,8 @@
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif"
"font-family": "serif",
"text-position": "baseline"
};
attrs = {"color": "rgb(0, 128, 0)"};
@ -315,7 +324,7 @@
testTextAttrs(ID, 11, attrs, 11, 18, defAttrs);
//////////////////////////////////////////////////////////////////////////
// area6
// area6 (CSS vertical-align property, bug 445938)
ID = "area6";
defAttrs = {
"font-style": "normal",
@ -325,7 +334,47 @@
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif"
"font-family": "serif",
"text-position": "baseline"
};
attrs = {};
testTextAttrs(ID, 0, attrs, 0, 5, defAttrs);
attrs = {"text-position": "super", "font-size": "13px" };
testTextAttrs(ID, 5, attrs, 5, 13, defAttrs);
attrs = {};
testTextAttrs(ID, 13, attrs, 13, 27, defAttrs);
attrs = {"text-position": "super" };
testTextAttrs(ID, 27, attrs, 27, 35, defAttrs);
attrs = {};
testTextAttrs(ID, 35, attrs, 35, 39, defAttrs);
attrs = {"text-position": "sub", "font-size": "13px" };
testTextAttrs(ID, 39, attrs, 39, 50, defAttrs);
attrs = {};
testTextAttrs(ID, 50, attrs, 50, 55, defAttrs);
attrs = {"text-position": "sub" };
testTextAttrs(ID, 55, attrs, 55, 64, defAttrs);
//////////////////////////////////////////////////////////////////////////
// area7
ID = "area7";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "transparent",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
attrs = {"language": "ru"};
@ -403,7 +452,14 @@
<img src="moz.png" alt="image"/>
<span style="color: red">Red</span>Normal
</p>
<p lang="en" id="area6">
<p id="area6">
This <sup>sentence</sup> has the word
<span style="vertical-align:super;">sentence</span> in
<sub>superscript</sub> and
<span style="vertical-align:sub;">subscript</span>
</p>
<p lang="en" id="area7">
<span lang="ru">Привет</span>
<span style="background-color: blue">Blue BG color</span>
<span lang="de">Ich bin/Du bist</span>
@ -413,7 +469,7 @@
</span>
</p>
<input id="area7" value="valid text inalid tixt"/>
<input id="area8" value="valid text inalid tixt"/>
<p id="output"/>
</body>

View File

@ -1,7 +1,7 @@
WIN32_MODULE_COMPANYNAME=Mozilla Corporation
WIN32_MODULE_COPYRIGHT=©Firefox and Mozilla Developers, according to the MPL 1.1/GPL 2.0/LGPL 2.1 licenses, as applicable.
WIN32_MODULE_PRODUCTVERSION=3,1,0,0
WIN32_MODULE_PRODUCTVERSION_STRING=3.1a1pre
WIN32_MODULE_PRODUCTVERSION_STRING=3.1a2pre
WIN32_MODULE_TRADEMARKS=Firefox is a Trademark of The Mozilla Foundation.
WIN32_MODULE_DESCRIPTION=Firefox
WIN32_MODULE_PRODUCTNAME=Firefox

View File

@ -37,17 +37,17 @@
# NSIS branding defines for unofficial builds.
# The official release build branding.nsi is located in other-license/branding/firefox/
# The nightly build branding.nsi is located in browser/installer/windows/nsis/
!define BrandShortName "Gran Paradiso"
!define BrandShortName "Shiretoko"
# BrandFullNameInternal is used for some registry and file system values
# instead of BrandFullName and typically should not be modified.
!define BrandFullNameInternal "Gran Paradiso"
!define BrandFullNameInternal "Shiretoko"
!define CompanyName "mozilla.org"
!define URLInfoAbout "http://www.mozilla.org"
!define URLUpdateInfo "http://www.mozilla.org/projects/firefox"
!define SurveyURL "https://survey.mozilla.com/1/Mozilla%20Firefox/${AppVersion}/${AB_CD}/exit.html"
# Everything below this line may be modified for Alpha / Beta releases.
!define BrandFullName "Gran Paradiso"
!define BrandFullName "Shiretoko"
# Add !define NO_INSTDIR_FROM_REG to prevent finding a non-default installation
# directory in the registry and using that as the default. This prevents

View File

@ -1 +1 @@
MOZ_APP_DISPLAYNAME="GranParadiso"
MOZ_APP_DISPLAYNAME="Shiretoko"

View File

@ -28,7 +28,7 @@ resource 'STR#' (5000, "English") {
"Save AsÉ",
// Descriptive text, curly quotes are 0xD2 and 0xD3
"You are about to install\n"
"Gran Paradiso.\n"
"Shiretoko.\n"
"\n"
"Please read the license agreement. If you agree to its terms and accept, click ÒAcceptÓ to access the software. Otherwise, click ÒDeclineÓ to cancel."
};
@ -41,7 +41,7 @@ resource 'STR#' (5000, "English") {
// 0xD2 and 0xD3 are curly double-quotes ("), 0xD4 and 0xD5 are curly
// single quotes ('), 0xD5 is also the apostrophe.
data 'TEXT' (5000, "English") {
"GRAN PARADISO END-USER SOFTWARE LICENSE AGREEMENT\n"
"SHIRETOKO END-USER SOFTWARE LICENSE AGREEMENT\n"
"Version 3.0, May 2008\n"
"\n"
"A SOURCE CODE VERSION OF CERTAIN FIREFOX BROWSER FUNCTIONALITY THAT YOU MAY USE, MODIFY AND DISTRIBUTE IS AVAILABLE TO YOU FREE-OF-CHARGE FROM WWW.MOZILLA.ORG UNDER THE MOZILLA PUBLIC LICENSE and other open source software licenses.\n"

View File

@ -1,3 +1,3 @@
# Do NOT localize or otherwise change these values
browser.startup.homepage=http://www.mozilla.org/projects/granparadiso/
browser.startup.homepage=http://www.mozilla.org/projects/shiretoko/

View File

@ -1,6 +1,6 @@
<!ENTITY brandShortName "Gran Paradiso">
<!ENTITY brandFullName "Gran Paradiso">
<!ENTITY brandShortName "Shiretoko">
<!ENTITY brandFullName "Shiretoko">
<!ENTITY vendorShortName "mozilla.org">
<!-- LOCALIZATION NOTE (releaseBaseURL): The about: page appends __MOZ_APP_VERSION__.html, e.g. 2.0.html -->
<!ENTITY releaseBaseURL "http://www.mozilla.org/projects/granparadiso/releases/">
<!ENTITY releaseBaseURL "http://www.mozilla.org/projects/shiretoko/releases/">

View File

@ -1,3 +1,3 @@
brandShortName=Gran Paradiso
brandFullName=Gran Paradiso
brandShortName=Shiretoko
brandFullName=Shiretoko
vendorShortName=mozilla.org

View File

@ -2,6 +2,6 @@
@AB_CD@.jar:
% locale branding @AB_CD@ %locale/branding/
# Gran Paradiso branding only exists in en-US
# Unofficial branding only exists in en-US
locale/branding/brand.dtd (en-US/brand.dtd)
* locale/branding/brand.properties (en-US/brand.properties)

View File

@ -1 +1 @@
3.1a1pre
3.1a2pre

View File

@ -70,6 +70,8 @@ sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_VERSION)
DIST = $(DEPTH)/dist
LIBXUL_SDK = @LIBXUL_SDK@
L10NBASEDIR = @L10NBASEDIR@
ifdef LIBXUL_SDK
LIBXUL_DIST = $(LIBXUL_SDK)
else

View File

@ -868,7 +868,11 @@ endif
# overridden by the command line. (Besides, AB_CD is prettier).
AB_CD = $(MOZ_UI_LOCALE)
EXPAND_LOCALE_SRCDIR = $(if $(filter en-US,$(AB_CD)),$(topsrcdir)/$(1)/en-US,$(topsrcdir)/../l10n/$(AB_CD)/$(subst /locales,,$(1)))
ifndef L10NBASEDIR
L10NBASEDIR = $(error L10NBASEDIR not defined by configure)
endif
EXPAND_LOCALE_SRCDIR = $(if $(filter en-US,$(AB_CD)),$(topsrcdir)/$(1)/en-US,$(L10NBASEDIR)/$(AB_CD)/$(subst /locales,,$(1)))
ifdef relativesrcdir
LOCALE_SRCDIR = $(call EXPAND_LOCALE_SRCDIR,$(relativesrcdir))

File diff suppressed because it is too large Load Diff

View File

@ -10,4 +10,4 @@
# hardcoded milestones in the tree from these two files.
#--------------------------------------------------------
1.9.1a1pre
1.9.1a2pre

View File

@ -196,6 +196,7 @@ FixMath.h
float.h
Folders.h
fontconfig/fontconfig.h
fontconfig/fcfreetype.h
Font.h
Fonts.h
fp.h

View File

@ -207,6 +207,20 @@ MOZ_ARG_ENABLE_BOOL(compile-environment,
COMPILE_ENVIRONMENT=1,
COMPILE_ENVIRONMENT= )
MOZ_ARG_WITH_STRING(l10n-base,
[ --with-l10nbase=DIR path to l10n repositories],
L10NBASEDIR=$withval)
if test ! -z "$L10NBASEDIR"; then
if test "$L10NBASEDIR" = "yes" -o "$L10NBASEDIR" = "no"; then
AC_MSG_ERROR([--with-l10n-base must specify a path])
elif test -d "$L10NBASEDIR"; then
L10NBASEDIR=`cd "$L10NBASEDIR" && pwd`
else
AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist])
fi
fi
AC_SUBST(L10NBASEDIR)
dnl ========================================================
dnl Checks for compilers.
dnl ========================================================

View File

@ -146,7 +146,7 @@ public:
* @see nsIAnonymousContentCreator
* @return whether this content is anonymous
*/
PRBool IsNativeAnonymous() const
PRBool IsRootOfNativeAnonymousSubtree() const
{
return HasFlag(NODE_IS_ANONYMOUS);
}
@ -177,7 +177,7 @@ public:
}
nsIContent* content = GetBindingParent();
while (content) {
if (content->IsNativeAnonymous()) {
if (content->IsRootOfNativeAnonymousSubtree()) {
NS_ERROR("Element not marked to be in native anonymous subtree!");
break;
}
@ -189,6 +189,31 @@ public:
#endif
}
/**
* Returns true if and only if this node has a parent, but is not in
* its parent's child list.
*/
PRBool IsRootOfAnonymousSubtree() const
{
NS_ASSERTION(!IsRootOfNativeAnonymousSubtree() ||
(GetParent() && GetBindingParent() == GetParent()),
"root of native anonymous subtree must have parent equal "
"to binding parent");
nsIContent *bindingParent = GetBindingParent();
return bindingParent && bindingParent == GetParent();
}
/**
* Returns true if and only if there is NOT a path through child lists
* from the top of this node's parent chain back to this node.
*/
PRBool IsInAnonymousSubtree() const
{
NS_ASSERTION(!IsInNativeAnonymousSubtree() || GetBindingParent(),
"must have binding parent when in native anonymous subtree");
return GetBindingParent() != nsnull;
}
/**
* Get the namespace that this element's tag is defined in
* @return the namespace
@ -563,9 +588,12 @@ public:
}
/**
* Gets content node with the binding responsible for our construction (and
* existence). Used by anonymous content (XBL-generated). null for all
* explicit content.
* Gets content node with the binding (or native code, possibly on the
* frame) responsible for our construction (and existence). Used by
* anonymous content (both XBL-generated and native-anonymous).
*
* null for all explicit content (i.e., content reachable from the top
* of its GetParent() chain via child lists).
*
* @return the binding parent
*/

View File

@ -146,6 +146,7 @@ CPPSRCS = \
nsNoDataProtocolContentPolicy.cpp \
nsNodeInfo.cpp \
nsNodeInfoManager.cpp \
nsNodeIterator.cpp \
nsNodeUtils.cpp \
nsObjectLoadingContent.cpp \
nsParserUtils.cpp \
@ -164,6 +165,7 @@ CPPSRCS = \
nsSyncLoadService.cpp \
nsTextFragment.cpp \
nsTextNode.cpp \
nsTraversal.cpp \
nsTreeWalker.cpp \
nsXMLContentSerializer.cpp \
nsXMLHttpRequest.cpp \

View File

@ -1890,7 +1890,7 @@ nsContentUtils::GenerateStateKey(nsIContent* aContent,
NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
// Don't capture state for anonymous content
if (aContent->IsNativeAnonymous() || aContent->GetBindingParent()) {
if (aContent->IsInAnonymousSubtree()) {
return NS_OK;
}

View File

@ -85,6 +85,7 @@
#include "nsIDOMText.h"
#include "nsIDOMComment.h"
#include "nsDOMDocumentType.h"
#include "nsNodeIterator.h"
#include "nsTreeWalker.h"
#include "nsIServiceManager.h"
@ -1141,6 +1142,7 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNodeSelector)
// nsNodeSH::PreCreate() depends on the identity pointer being the
// same as nsINode (which nsIDocument inherits), so if you change
// the below line, make sure nsNodeSH::PreCreate() still does the
@ -2143,8 +2145,8 @@ nsDocument::ElementFromPoint(PRInt32 aX, PRInt32 aY, nsIDOMElement** aReturn)
// replace it with the first non-anonymous parent node of type element.
while (ptContent &&
!ptContent->IsNodeOfType(nsINode::eELEMENT) ||
ptContent->GetBindingParent() ||
ptContent->IsNativeAnonymous()) {
ptContent->IsInAnonymousSubtree()) {
// XXXldb: Faster to jump to GetBindingParent if non-null?
ptContent = ptContent->GetParent();
}
@ -4201,7 +4203,28 @@ nsDocument::CreateNodeIterator(nsIDOMNode *aRoot,
PRBool aEntityReferenceExpansion,
nsIDOMNodeIterator **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
*_retval = nsnull;
if (!aRoot)
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
nsresult rv = nsContentUtils::CheckSameOrigin(this, aRoot);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_ARG_POINTER(_retval);
nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
NS_ENSURE_TRUE(root, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
nsNodeIterator *iterator = new nsNodeIterator(root,
aWhatToShow,
aFilter,
aEntityReferenceExpansion);
NS_ENSURE_TRUE(iterator, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*_retval = iterator);
return NS_OK;
}
NS_IMETHODIMP
@ -4213,17 +4236,26 @@ nsDocument::CreateTreeWalker(nsIDOMNode *aRoot,
{
*_retval = nsnull;
if (!aRoot) {
if (!aRoot)
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
nsresult rv = nsContentUtils::CheckSameOrigin(this, aRoot);
if (NS_FAILED(rv)) {
return rv;
}
NS_ENSURE_SUCCESS(rv, rv);
return NS_NewTreeWalker(aRoot, aWhatToShow, aFilter,
aEntityReferenceExpansion, _retval);
NS_ENSURE_ARG_POINTER(_retval);
nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
NS_ENSURE_TRUE(root, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
nsTreeWalker* walker = new nsTreeWalker(root,
aWhatToShow,
aFilter,
aEntityReferenceExpansion);
NS_ENSURE_TRUE(walker, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*_retval = walker);
return NS_OK;
}
@ -6598,3 +6630,17 @@ nsDocument::SetScriptTypeID(PRUint32 aScriptType)
NS_ERROR("Can't change default script type for a document");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::QuerySelector(const nsAString& aSelector,
nsIDOMElement **aReturn)
{
return nsGenericElement::doQuerySelector(this, aSelector, aReturn);
}
NS_IMETHODIMP
nsDocument::QuerySelectorAll(const nsAString& aSelector,
nsIDOMNodeList **aReturn)
{
return nsGenericElement::doQuerySelectorAll(this, aSelector, aReturn);
}

View File

@ -67,6 +67,7 @@
#include "nsIContent.h"
#include "nsIEventListenerManager.h"
#include "nsIDOM3Node.h"
#include "nsIDOMNodeSelector.h"
#include "nsIPrincipal.h"
#include "nsIParser.h"
#include "nsBindingManager.h"
@ -404,6 +405,7 @@ class nsDocument : public nsIDocument,
public nsIDOMNSEventTarget,
public nsIScriptObjectPrincipal,
public nsIRadioGroupContainer,
public nsIDOMNodeSelector,
public nsStubMutationObserver
{
public:
@ -734,6 +736,9 @@ public:
// nsIDOMNSEventTarget
NS_DECL_NSIDOMNSEVENTTARGET
// nsIDOMNodeSelector
NS_DECL_NSIDOMNODESELECTOR
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED

View File

@ -592,8 +592,11 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
(!aBindingParent && aParent &&
aParent->GetBindingParent() == GetBindingParent()),
"Already have a binding parent. Unbind first!");
NS_PRECONDITION(aBindingParent != this || IsNativeAnonymous(),
"Only native anonymous content should have itself as its "
NS_PRECONDITION(aBindingParent != this,
"Content must not be its own binding parent");
NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
aBindingParent == aParent,
"Native anonymous content must have its parent as its "
"own binding parent");
if (!aBindingParent && aParent) {
@ -605,13 +608,14 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsDataSlots *slots = GetDataSlots();
NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
NS_ASSERTION(IsNativeAnonymous() || !HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
NS_ASSERTION(IsRootOfNativeAnonymousSubtree() ||
!HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
aBindingParent->IsInNativeAnonymousSubtree(),
"Trying to re-bind content from native anonymous subtree to"
"non-native anonymous parent!");
slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
if (IsNativeAnonymous() ||
aBindingParent->IsInNativeAnonymousSubtree()) {
if (IsRootOfNativeAnonymousSubtree() ||
aParent->IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
}
}

View File

@ -126,6 +126,9 @@
#include "nsIFocusController.h"
#include "nsIControllers.h"
#include "nsXBLInsertionPoint.h"
#include "nsICSSStyleRule.h" /* For nsCSSSelectorList */
#include "nsCSSRuleProcessor.h"
#ifdef MOZ_XUL
#include "nsIXULDocument.h"
#endif /* MOZ_XUL */
@ -432,18 +435,15 @@ nsIContent*
nsIContent::FindFirstNonNativeAnonymous() const
{
// This handles also nested native anonymous content.
nsIContent* content = GetBindingParent();
nsIContent* possibleResult =
!IsNativeAnonymous() ? const_cast<nsIContent*>(this) : nsnull;
while (content) {
if (content->IsNativeAnonymous()) {
content = possibleResult = content->GetParent();
} else {
content = content->GetBindingParent();
for (const nsIContent *content = this; content;
content = content->GetBindingParent()) {
if (!content->IsInNativeAnonymousSubtree()) {
// Oops, this function signature allows casting const to
// non-const. (Then again, so does GetChildAt(0)->GetParent().)
return const_cast<nsIContent*>(content);
}
}
return possibleResult;
return nsnull;
}
//----------------------------------------------------------------------
@ -1157,6 +1157,68 @@ nsDOMEventRTTearoff::AddEventListener(const nsAString& aType,
//----------------------------------------------------------------------
NS_IMPL_CYCLE_COLLECTION_1(nsNodeSelectorTearoff, mContent)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNodeSelectorTearoff)
NS_INTERFACE_MAP_ENTRY(nsIDOMNodeSelector)
NS_INTERFACE_MAP_END_AGGREGATED(mContent)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeSelectorTearoff)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNodeSelectorTearoff)
NS_IMETHODIMP
nsNodeSelectorTearoff::QuerySelector(const nsAString& aSelector,
nsIDOMElement **aReturn)
{
return nsGenericElement::doQuerySelector(mContent, aSelector, aReturn);
}
NS_IMETHODIMP
nsNodeSelectorTearoff::QuerySelectorAll(const nsAString& aSelector,
nsIDOMNodeList **aReturn)
{
return nsGenericElement::doQuerySelectorAll(mContent, aSelector, aReturn);
}
//----------------------------------------------------------------------
NS_IMPL_CYCLE_COLLECTION_CLASS(nsStaticContentList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsStaticContentList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsStaticContentList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsStaticContentList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsStaticContentList)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsStaticContentList)
NS_INTERFACE_MAP_ENTRY(nsIDOMNodeList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(NodeList)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsStaticContentList::GetLength(PRUint32* aLength)
{
*aLength = mList.Count();
return NS_OK;
}
NS_IMETHODIMP
nsStaticContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
{
nsIContent* c = mList.SafeObjectAt(aIndex);
if (!c) {
*aReturn = nsnull;
return NS_OK;
}
return CallQueryInterface(c, aReturn);
}
//----------------------------------------------------------------------
PRUint32 nsMutationGuard::sMutationCount = 0;
nsGenericElement::nsDOMSlots::nsDOMSlots(PtrBits aFlags)
@ -2026,11 +2088,11 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
NS_PRECONDITION(!aParent || !aDocument ||
!aParent->HasFlag(NODE_FORCE_XBL_BINDINGS),
"Parent in document but flagged as forcing XBL");
NS_PRECONDITION(aBindingParent != this || IsNativeAnonymous(),
"Only native anonymous content should have itself as its "
"own binding parent");
NS_PRECONDITION(!IsNativeAnonymous() || aBindingParent == this,
"Native anonymous content must have itself as its "
NS_PRECONDITION(aBindingParent != this,
"Content must not be its own binding parent");
NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
aBindingParent == aParent,
"Native anonymous content must have its parent as its "
"own binding parent");
if (!aBindingParent && aParent) {
@ -2056,13 +2118,13 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
}
}
NS_ASSERTION(!aBindingParent || IsNativeAnonymous() ||
NS_ASSERTION(!aBindingParent || IsRootOfNativeAnonymousSubtree() ||
!HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
aBindingParent->IsInNativeAnonymousSubtree(),
"Trying to re-bind content from native anonymous subtree to"
"non-native anonymous parent!");
if (IsNativeAnonymous() ||
aBindingParent && aBindingParent->IsInNativeAnonymousSubtree()) {
if (IsRootOfNativeAnonymousSubtree() ||
aParent && aParent->IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
}
@ -2237,7 +2299,7 @@ FindNativeAnonymousSubtreeOwner(nsIContent* aContent)
if (aContent->IsInNativeAnonymousSubtree()) {
PRBool isNativeAnon = PR_FALSE;
while (aContent && !isNativeAnon) {
isNativeAnon = aContent->IsNativeAnonymous();
isNativeAnon = aContent->IsRootOfNativeAnonymousSubtree();
aContent = aContent->GetParent();
}
}
@ -2253,7 +2315,7 @@ nsGenericElement::doPreHandleEvent(nsIContent* aContent,
// Don't propagate mouseover and mouseout events when mouse is moving
// inside native anonymous content.
PRBool isAnonForEvents = aContent->IsNativeAnonymous();
PRBool isAnonForEvents = aContent->IsRootOfNativeAnonymousSubtree();
if ((aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH ||
aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH) &&
// This is an optimization - try to stop event propagation when
@ -3583,6 +3645,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGenericElement)
nsDOMEventRTTearoff::Create(this))
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
new nsNodeSupportsWeakRefTearoff(this))
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNodeSelector,
new nsNodeSelectorTearoff(this))
// nsNodeSH::PreCreate() depends on the identity pointer being the
// same as nsINode (which nsIContent inherits), so if you change the
// below line, make sure nsNodeSH::PreCreate() still does the right
@ -4529,3 +4593,198 @@ nsGenericElement::GetLinkTarget(nsAString& aTarget)
aTarget.Truncate();
}
// NOTE: The aPresContext pointer is NOT addrefed.
static nsresult
ParseSelectorList(nsINode* aNode,
const nsAString& aSelectorString,
nsCSSSelectorList** aSelectorList,
nsPresContext** aPresContext)
{
NS_ENSURE_ARG(aNode);
nsIDocument* doc = aNode->GetOwnerDoc();
NS_ENSURE_STATE(doc);
nsCOMPtr<nsICSSParser> parser;
nsresult rv = doc->CSSLoader()->GetParserFor(nsnull, getter_AddRefs(parser));
NS_ENSURE_SUCCESS(rv, rv);
rv = parser->ParseSelectorString(aSelectorString,
doc->GetDocumentURI(),
0, // XXXbz get the right line number!
aSelectorList);
doc->CSSLoader()->RecycleParser(parser);
NS_ENSURE_SUCCESS(rv, rv);
// It's not strictly necessary to have a prescontext here, but it's
// a bit of an optimization for various stuff.
*aPresContext = nsnull;
nsIPresShell* shell = doc->GetPrimaryShell();
if (shell) {
*aPresContext = shell->GetPresContext();
}
return NS_OK;
}
/*
* Callback to be called as we iterate over the tree and match elements. If
* the callbacks returns false, the iteration should be stopped.
*/
typedef PRBool
(* PR_CALLBACK ElementMatchedCallback)(nsIContent* aMatchingElement,
void* aClosure);
// returning false means stop iteration
static PRBool
TryMatchingElementsInSubtree(nsINode* aRoot,
RuleProcessorData* aParentData,
nsPresContext* aPresContext,
nsCSSSelectorList* aSelectorList,
ElementMatchedCallback aCallback,
void* aClosure)
{
PRUint32 count = aRoot->GetChildCount();
/* To improve the performance of '+' and '~' combinators and the :nth-*
* selectors, we keep track of the immediately previous sibling data. That's
* cheaper than heap-allocating all the datas and keeping track of them all,
* and helps a good bit in the common cases. We also keep track of the whole
* parent data chain, since we have those Around anyway */
char databuf[2 * sizeof(RuleProcessorData)];
RuleProcessorData* prevSibling = nsnull;
RuleProcessorData* data = reinterpret_cast<RuleProcessorData*>(databuf);
nsIContent * const * kidSlot = aRoot->GetChildArray();
nsIContent * const * end = kidSlot + count;
PRBool continueIteration = PR_TRUE;
for (; kidSlot != end; ++kidSlot) {
nsIContent* kid = *kidSlot;
if (!kid->IsNodeOfType(nsINode::eELEMENT)) {
continue;
}
/* See whether we match */
new (data) RuleProcessorData(aPresContext, kid, nsnull);
NS_ASSERTION(!data->mParentData, "Shouldn't happen");
NS_ASSERTION(!data->mPreviousSiblingData, "Shouldn't happen");
data->mParentData = aParentData;
data->mPreviousSiblingData = prevSibling;
if (nsCSSRuleProcessor::SelectorListMatches(*data, aSelectorList)) {
continueIteration = (*aCallback)(kid, aClosure);
}
if (continueIteration) {
continueIteration =
TryMatchingElementsInSubtree(kid, data, aPresContext, aSelectorList,
aCallback, aClosure);
}
/* Clear out the parent and previous sibling data if we set them, so that
* ~RuleProcessorData won't try to delete a placement-new'd object. Make
* sure this happens before our possible early break. Note that we can
* have null aParentData but non-null data->mParentData if we're scoped to
* an element. However, prevSibling and data->mPreviousSiblingData must
* always match.
*/
NS_ASSERTION(!aParentData || data->mParentData == aParentData,
"Unexpected parent");
NS_ASSERTION(data->mPreviousSiblingData == prevSibling,
"Unexpected prev sibling");
data->mPreviousSiblingData = nsnull;
if (prevSibling) {
if (aParentData) {
prevSibling->mParentData = nsnull;
}
prevSibling->~RuleProcessorData();
} else {
/* This is the first time through, so point |prevSibling| to the location
we want to have |data| end up pointing to. */
prevSibling = data + 1;
}
/* Now swap |prevSibling| and |data|. Again, before the early break */
RuleProcessorData* temp = prevSibling;
prevSibling = data;
data = temp;
if (!continueIteration) {
break;
}
}
if (prevSibling) {
if (aParentData) {
prevSibling->mParentData = nsnull;
}
/* Make sure to clean this up */
prevSibling->~RuleProcessorData();
}
return continueIteration;
}
PR_STATIC_CALLBACK(PRBool)
FindFirstMatchingElement(nsIContent* aMatchingElement,
void* aClosure)
{
NS_PRECONDITION(aMatchingElement && aClosure, "How did that happen?");
nsIContent** slot = static_cast<nsIContent**>(aClosure);
*slot = aMatchingElement;
return PR_FALSE;
}
/* static */
nsresult
nsGenericElement::doQuerySelector(nsINode* aRoot, const nsAString& aSelector,
nsIDOMElement **aReturn)
{
NS_PRECONDITION(aReturn, "Null out param?");
nsAutoPtr<nsCSSSelectorList> selectorList;
nsPresContext* presContext;
nsresult rv = ParseSelectorList(aRoot, aSelector,
getter_Transfers(selectorList),
&presContext);
NS_ENSURE_SUCCESS(rv, rv);
nsIContent* foundElement = nsnull;
TryMatchingElementsInSubtree(aRoot, nsnull, presContext, selectorList,
FindFirstMatchingElement, &foundElement);
if (foundElement) {
return CallQueryInterface(foundElement, aReturn);
}
*aReturn = nsnull;
return NS_OK;
}
PR_STATIC_CALLBACK(PRBool)
AppendAllMatchingElements(nsIContent* aMatchingElement,
void* aClosure)
{
NS_PRECONDITION(aMatchingElement && aClosure, "How did that happen?");
static_cast<nsStaticContentList*>(aClosure)->AppendContent(aMatchingElement);
return PR_TRUE;
}
/* static */
nsresult
nsGenericElement::doQuerySelectorAll(nsINode* aRoot,
const nsAString& aSelector,
nsIDOMNodeList **aReturn)
{
NS_PRECONDITION(aReturn, "Null out param?");
nsStaticContentList* contentList = new nsStaticContentList();
NS_ENSURE_TRUE(contentList, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aReturn = contentList);
nsAutoPtr<nsCSSSelectorList> selectorList;
nsPresContext* presContext;
nsresult rv = ParseSelectorList(aRoot, aSelector,
getter_Transfers(selectorList),
&presContext);
NS_ENSURE_SUCCESS(rv, rv);
TryMatchingElementsInSubtree(aRoot, nsnull, presContext, selectorList,
AppendAllMatchingElements, contentList);
return NS_OK;
}

View File

@ -64,6 +64,7 @@
#include "nsIWeakReference.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDocument.h"
#include "nsIDOMNodeSelector.h"
class nsIDOMAttr;
class nsIDOMEventListener;
@ -268,6 +269,51 @@ private:
nsCOMPtr<nsIContent> mContent;
};
/**
* A tearoff class for nsGenericElement to implement NodeSelector
*/
class nsNodeSelectorTearoff : public nsIDOMNodeSelector
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOMNODESELECTOR
NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeSelectorTearoff)
nsNodeSelectorTearoff(nsIContent *aContent) : mContent(aContent)
{
}
private:
~nsNodeSelectorTearoff() {}
private:
nsCOMPtr<nsIContent> mContent;
};
/**
* A static NodeList class, which just holds a COMArray of nodes
*/
class nsStaticContentList : public nsIDOMNodeList {
public:
nsStaticContentList() {}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOMNODELIST
NS_DECL_CYCLE_COLLECTION_CLASS(nsStaticContentList)
PRBool AppendContent(nsIContent* aContent) {
return mList.AppendObject(aContent);
}
private:
~nsStaticContentList() {}
nsCOMArray<nsIContent> mList;
};
/**
* Class used to detect unexpected mutations. To use the class create an
* nsMutationGuard on the stack before unexpected mutations could occur.
@ -671,6 +717,15 @@ public:
nsIDocument* aDocument,
nsAttrAndChildArray& aChildArray);
/**
* Helper methods for implementing querySelector/querySelectorAll
*/
static nsresult doQuerySelector(nsINode* aRoot, const nsAString& aSelector,
nsIDOMElement **aReturn);
static nsresult doQuerySelectorAll(nsINode* aRoot,
const nsAString& aSelector,
nsIDOMNodeList **aReturn);
/**
* Default event prehandling for content objects. Handles event retargeting.
*/

View File

@ -495,6 +495,7 @@ GK_ATOM(marquee, "marquee")
GK_ATOM(match, "match")
GK_ATOM(max, "max")
GK_ATOM(maxheight, "maxheight")
GK_ATOM(maximum_scale, "maximum-scale")
GK_ATOM(maxlength, "maxlength")
GK_ATOM(maxpos, "maxpos")
GK_ATOM(maxwidth, "maxwidth")
@ -1315,7 +1316,6 @@ GK_ATOM(mathcolor_, "mathcolor")
GK_ATOM(mathsize_, "mathsize")
GK_ATOM(mathvariant_, "mathvariant")
GK_ATOM(matrixrow_, "matrixrow")
GK_ATOM(maximum_scale, "maximum-scale")
GK_ATOM(maxsize_, "maxsize")
GK_ATOM(mean_, "mean")
GK_ATOM(median_, "median")

View File

@ -0,0 +1,378 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is this file as it was released on July 19 2008.
*
* The Initial Developer of the Original Code is
* Craig Topper.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Craig Topper <craig.topper@gmail.com> (Original Author)
*
* 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 ***** */
/*
* Implementation of DOM Traversal's nsIDOMNodeIterator
*/
#include "nsNodeIterator.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeFilter.h"
#include "nsDOMError.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsContentUtils.h"
#include "nsCOMPtr.h"
/*
* NodePointer implementation
*/
nsNodeIterator::NodePointer::NodePointer(nsINode *aNode,
PRBool aBeforeNode) :
mNode(aNode),
mBeforeNode(aBeforeNode)
{
}
PRBool nsNodeIterator::NodePointer::MoveToNext(nsINode *aRoot)
{
if (mBeforeNode) {
mBeforeNode = PR_FALSE;
return PR_TRUE;
}
return MoveForward(aRoot, mNode, -1);
}
PRBool nsNodeIterator::NodePointer::MoveToPrevious(nsINode *aRoot)
{
if (!mBeforeNode) {
mBeforeNode = PR_TRUE;
return PR_TRUE;
}
if (mNode == aRoot)
return PR_FALSE;
NS_ASSERTION(mNodeParent == mNode->GetNodeParent(), "Parent node incorrect in MoveToPrevious");
NS_ASSERTION(mIndexInParent == mNodeParent->IndexOf(mNode), "Index mismatch in MoveToPrevious");
MoveBackward(mNodeParent, mIndexInParent);
return PR_TRUE;
}
void nsNodeIterator::NodePointer::AdjustAfterInsertion(nsINode *aContainer, PRInt32 aIndexInContainer)
{
if (!mNode)
return;
// check if earlier sibling was added
if (aContainer == mNodeParent && aIndexInContainer <= mIndexInParent)
mIndexInParent++;
}
void nsNodeIterator::NodePointer::AdjustAfterRemoval(nsINode* aRoot, nsINode *aContainer, nsIContent *aChild, PRInt32 aIndexInContainer)
{
if (!mNode)
return;
// check if earlier sibling was removed
if (aContainer == mNodeParent && aIndexInContainer < mIndexInParent)
mIndexInParent--;
// check if ancestor was removed
if (!nsContentUtils::ContentIsDescendantOf(mNode, aChild))
return;
if (mBeforeNode) {
if (MoveForward(aRoot, aContainer, aIndexInContainer-1))
return;
// No suitable node was found so try going backwards
mBeforeNode = PR_FALSE;
}
MoveBackward(aContainer, aIndexInContainer);
}
PRBool nsNodeIterator::NodePointer::MoveForward(nsINode *aRoot, nsINode *aParent, PRInt32 aChildNum)
{
while (1) {
nsINode *node = aParent->GetChildAt(aChildNum+1);
if (node) {
mNode = node;
mIndexInParent = aChildNum+1;
mNodeParent = aParent;
return PR_TRUE;
}
if (aParent == aRoot)
break;
node = aParent;
if (node == mNode) {
NS_ASSERTION(mNodeParent == mNode->GetNodeParent(), "Parent node incorrect in MoveForward");
NS_ASSERTION(mIndexInParent == mNodeParent->IndexOf(mNode), "Index mismatch in MoveForward");
aParent = mNodeParent;
aChildNum = mIndexInParent;
} else {
aParent = node->GetNodeParent();
aChildNum = aParent->IndexOf(node);
}
}
return PR_FALSE;
}
void nsNodeIterator::NodePointer::MoveBackward(nsINode *aParent, PRInt32 aChildNum)
{
nsINode *sibling = aParent->GetChildAt(aChildNum-1);
mNode = aParent;
if (sibling) {
do {
mIndexInParent = aChildNum-1;
mNodeParent = mNode;
mNode = sibling;
aChildNum = mNode->GetChildCount();
sibling = mNode->GetChildAt(aChildNum-1);
} while (sibling);
} else {
mNodeParent = mNode->GetNodeParent();
if (mNodeParent)
mIndexInParent = mNodeParent->IndexOf(mNode);
}
}
/*
* Factories, constructors and destructors
*/
nsNodeIterator::nsNodeIterator(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
PRBool aExpandEntityReferences) :
nsTraversal(aRoot, aWhatToShow, aFilter, aExpandEntityReferences),
mDetached(PR_FALSE),
mPointer(mRoot, PR_TRUE)
{
aRoot->AddMutationObserver(this);
}
nsNodeIterator::~nsNodeIterator()
{
/* destructor code */
if (!mDetached && mRoot)
mRoot->RemoveMutationObserver(this);
}
/*
* nsISupports and cycle collection stuff
*/
NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeIterator)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsNodeIterator)
if (!tmp->mDetached && tmp->mRoot)
tmp->mRoot->RemoveMutationObserver(tmp);
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRoot)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFilter)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsNodeIterator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFilter)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
// QueryInterface implementation for nsNodeIterator
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNodeIterator)
NS_INTERFACE_MAP_ENTRY(nsIDOMNodeIterator)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNodeIterator)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(NodeIterator)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeIterator)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNodeIterator)
/* readonly attribute nsIDOMNode root; */
NS_IMETHODIMP nsNodeIterator::GetRoot(nsIDOMNode * *aRoot)
{
if (mRoot)
return CallQueryInterface(mRoot, aRoot);
*aRoot = nsnull;
return NS_OK;
}
/* readonly attribute unsigned long whatToShow; */
NS_IMETHODIMP nsNodeIterator::GetWhatToShow(PRUint32 *aWhatToShow)
{
*aWhatToShow = mWhatToShow;
return NS_OK;
}
/* readonly attribute nsIDOMNodeFilter filter; */
NS_IMETHODIMP nsNodeIterator::GetFilter(nsIDOMNodeFilter **aFilter)
{
NS_ENSURE_ARG_POINTER(aFilter);
nsCOMPtr<nsIDOMNodeFilter> filter = mFilter;
filter.swap((*aFilter = nsnull));
return NS_OK;
}
/* readonly attribute boolean expandEntityReferences; */
NS_IMETHODIMP nsNodeIterator::GetExpandEntityReferences(PRBool *aExpandEntityReferences)
{
*aExpandEntityReferences = mExpandEntityReferences;
return NS_OK;
}
/* nsIDOMNode nextNode () raises (DOMException); */
NS_IMETHODIMP nsNodeIterator::NextNode(nsIDOMNode **_retval)
{
nsresult rv;
PRInt16 filtered;
*_retval = nsnull;
if (mDetached)
return NS_ERROR_DOM_INVALID_STATE_ERR;
mWorkingPointer = mPointer;
while (mWorkingPointer.MoveToNext(mRoot)) {
nsCOMPtr<nsINode> testNode = mWorkingPointer.mNode;
rv = TestNode(testNode, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
mPointer = mWorkingPointer;
mWorkingPointer.Clear();
return CallQueryInterface(testNode, _retval);
}
}
mWorkingPointer.Clear();
return NS_OK;
}
/* nsIDOMNode previousNode () raises (DOMException); */
NS_IMETHODIMP nsNodeIterator::PreviousNode(nsIDOMNode **_retval)
{
nsresult rv;
PRInt16 filtered;
*_retval = nsnull;
if (mDetached)
return NS_ERROR_DOM_INVALID_STATE_ERR;
mWorkingPointer = mPointer;
while (mWorkingPointer.MoveToPrevious(mRoot)) {
nsCOMPtr<nsINode> testNode = mWorkingPointer.mNode;
rv = TestNode(testNode, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
mPointer = mWorkingPointer;
mWorkingPointer.Clear();
return CallQueryInterface(testNode, _retval);
}
}
mWorkingPointer.Clear();
return NS_OK;
}
/* void detach (); */
NS_IMETHODIMP nsNodeIterator::Detach(void)
{
if (!mDetached) {
mRoot->RemoveMutationObserver(this);
mPointer.Clear();
mDetached = PR_TRUE;
}
return NS_OK;
}
/* readonly attribute nsIDOMNode referenceNode; */
NS_IMETHODIMP nsNodeIterator::GetReferenceNode(nsIDOMNode * *aRefNode)
{
if (mPointer.mNode)
return CallQueryInterface(mPointer.mNode, aRefNode);
*aRefNode = nsnull;
return NS_OK;
}
/* readonly attribute boolean pointerBeforeReferenceNode; */
NS_IMETHODIMP nsNodeIterator::GetPointerBeforeReferenceNode(PRBool *aBeforeNode)
{
*aBeforeNode = mPointer.mBeforeNode;
return NS_OK;
}
/*
* nsIMutationObserver interface
*/
void nsNodeIterator::ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
nsINode *container = NODE_FROM(aContainer, aDocument);
mPointer.AdjustAfterInsertion(container, aIndexInContainer);
mWorkingPointer.AdjustAfterInsertion(container, aIndexInContainer);
}
void nsNodeIterator::ContentRemoved(nsIDocument *aDocument,
nsIContent *aContainer,
nsIContent *aChild,
PRInt32 aIndexInContainer)
{
nsINode *container = NODE_FROM(aContainer, aDocument);
mPointer.AdjustAfterRemoval(mRoot, container, aChild, aIndexInContainer);
mWorkingPointer.AdjustAfterRemoval(mRoot, container, aChild, aIndexInContainer);
}

View File

@ -0,0 +1,103 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is this file as it was released on July 19 2008.
*
* The Initial Developer of the Original Code is
* Craig Toppper.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Craig Topper <craig.topper@gmail.com> (Original Author)
*
* 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 ***** */
/*
* Implementation of DOM Traversal's nsIDOMNodeIterator
*/
#ifndef nsNodeIterator_h___
#define nsNodeIterator_h___
#include "nsIDOMNodeIterator.h"
#include "nsTraversal.h"
#include "nsCycleCollectionParticipant.h"
#include "nsStubMutationObserver.h"
class nsINode;
class nsIDOMNode;
class nsIDOMNodeFilter;
class nsNodeIterator : public nsIDOMNodeIterator,
public nsTraversal,
public nsStubMutationObserver
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOMNODEITERATOR
nsNodeIterator(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
PRBool aExpandEntityReferences);
virtual ~nsNodeIterator();
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNodeIterator, nsIDOMNodeIterator)
private:
struct NodePointer {
NodePointer() : mNode(nsnull) {};
NodePointer(nsINode *aNode, PRBool aBeforeNode);
PRBool MoveToNext(nsINode *aRoot);
PRBool MoveToPrevious(nsINode *aRoot);
PRBool MoveForward(nsINode *aRoot, nsINode *aParent, PRInt32 aChildNum);
void MoveBackward(nsINode *aParent, PRInt32 aChildNum);
void AdjustAfterInsertion(nsINode *aContainer, PRInt32 aIndexInContainer);
void AdjustAfterRemoval(nsINode *aRoot, nsINode *aContainer, nsIContent *aChild, PRInt32 aIndexInContainer);
void Clear() { mNode = nsnull; }
nsINode *mNode;
// pointer to the parent of mNode. Can be dangling if mNode is null or points to the root
nsINode *mNodeParent;
PRBool mBeforeNode;
PRInt32 mIndexInParent;
};
PRBool mDetached;
NodePointer mPointer;
NodePointer mWorkingPointer;
};
#endif

View File

@ -0,0 +1,122 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is this file as it was released on May 1 2001.
*
* The Initial Developer of the Original Code is
* Jonas Sicking.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jonas Sicking <sicking@bigfoot.com> (Original Author)
*
* 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 "nsTraversal.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeFilter.h"
#include "nsDOMError.h"
#include "nsIContent.h"
#include "nsGkAtoms.h"
nsTraversal::nsTraversal(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
PRBool aExpandEntityReferences) :
mRoot(aRoot),
mWhatToShow(aWhatToShow),
mFilter(aFilter),
mExpandEntityReferences(aExpandEntityReferences)
{
NS_ASSERTION(aRoot, "invalid root in call to nsTraversal constructor");
}
nsTraversal::~nsTraversal()
{
/* destructor code */
}
/*
* Tests if and how a node should be filtered. Uses mWhatToShow and
* mFilter to test the node.
* @param aNode Node to test
* @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl
* @returns Errorcode
*/
nsresult nsTraversal::TestNode(nsINode* aNode, PRInt16* _filtered)
{
nsresult rv;
*_filtered = nsIDOMNodeFilter::FILTER_SKIP;
PRUint16 nodeType = 0;
// Check the most common cases
if (aNode->IsNodeOfType(nsINode::eELEMENT)) {
nodeType = nsIDOMNode::ELEMENT_NODE;
}
else if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
nsIAtom* tag = static_cast<nsIContent*>(aNode)->Tag();
if (tag == nsGkAtoms::textTagName) {
nodeType = nsIDOMNode::TEXT_NODE;
}
else if (tag == nsGkAtoms::cdataTagName) {
nodeType = nsIDOMNode::CDATA_SECTION_NODE;
}
else if (tag == nsGkAtoms::commentTagName) {
nodeType = nsIDOMNode::COMMENT_NODE;
}
else if (tag == nsGkAtoms::processingInstructionTagName) {
nodeType = nsIDOMNode::PROCESSING_INSTRUCTION_NODE;
}
}
nsCOMPtr<nsIDOMNode> domNode;
if (!nodeType) {
domNode = do_QueryInterface(aNode);
rv = domNode->GetNodeType(&nodeType);
NS_ENSURE_SUCCESS(rv, rv);
}
if (nodeType <= 12 && !((1 << (nodeType-1)) & mWhatToShow)) {
return NS_OK;
}
if (mFilter) {
if (!domNode) {
domNode = do_QueryInterface(aNode);
}
return mFilter->AcceptNode(domNode, _filtered);
}
*_filtered = nsIDOMNodeFilter::FILTER_ACCEPT;
return NS_OK;
}

View File

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is this file as it was released on May 1 2001.
*
* The Initial Developer of the Original Code is
* Jonas Sicking.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jonas Sicking <sicking@bigfoot.com> (Original Author)
*
* 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 ***** */
/*
* Implementation of DOM Traversal's nsIDOMTreeWalker
*/
#ifndef nsTraversal_h___
#define nsTraversal_h___
#include "nsCOMPtr.h"
class nsINode;
class nsIDOMNodeFilter;
class nsTraversal
{
public:
nsTraversal(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
PRBool aExpandEntityReferences);
virtual ~nsTraversal();
protected:
nsCOMPtr<nsINode> mRoot;
PRUint32 mWhatToShow;
nsCOMPtr<nsIDOMNodeFilter> mFilter;
PRBool mExpandEntityReferences;
/*
* Tests if and how a node should be filtered. Uses mWhatToShow and
* mFilter to test the node.
* @param aNode Node to test
* @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl
* @returns Errorcode
*/
nsresult TestNode(nsINode* aNode, PRInt16* _filtered);
};
#endif

View File

@ -51,47 +51,19 @@
#include "nsIDocument.h"
#include "nsContentUtils.h"
#include "nsMemory.h"
#include "nsCOMArray.h"
#include "nsGkAtoms.h"
/*
* Factories, constructors and destructors
*/
nsresult
NS_NewTreeWalker(nsIDOMNode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
PRBool aEntityReferenceExpansion,
nsIDOMTreeWalker **aInstancePtrResult)
{
NS_ENSURE_ARG_POINTER(aInstancePtrResult);
nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
NS_ENSURE_TRUE(root, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
nsTreeWalker* walker = new nsTreeWalker(root,
aWhatToShow,
aFilter,
aEntityReferenceExpansion);
NS_ENSURE_TRUE(walker, NS_ERROR_OUT_OF_MEMORY);
return CallQueryInterface(walker, aInstancePtrResult);
}
nsTreeWalker::nsTreeWalker(nsINode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
PRBool aExpandEntityReferences) :
mRoot(aRoot),
mWhatToShow(aWhatToShow),
mFilter(aFilter),
mExpandEntityReferences(aExpandEntityReferences),
nsTraversal(aRoot, aWhatToShow, aFilter, aExpandEntityReferences),
mCurrentNode(aRoot),
mPossibleIndexesPos(-1)
{
NS_ASSERTION(aRoot, "invalid root in call to nsTreeWalker constructor");
}
nsTreeWalker::~nsTreeWalker()
@ -572,63 +544,6 @@ nsTreeWalker::ChildOf(nsINode* aNode,
return NS_OK;
}
/*
* Tests if and how a node should be filtered. Uses mWhatToShow and
* mFilter to test the node.
* @param aNode Node to test
* @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl
* @returns Errorcode
*/
nsresult nsTreeWalker::TestNode(nsINode* aNode, PRInt16* _filtered)
{
nsresult rv;
*_filtered = nsIDOMNodeFilter::FILTER_SKIP;
PRUint16 nodeType = 0;
// Check the most common cases
if (aNode->IsNodeOfType(nsINode::eELEMENT)) {
nodeType = nsIDOMNode::ELEMENT_NODE;
}
else if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
nsIAtom* tag = static_cast<nsIContent*>(aNode)->Tag();
if (tag == nsGkAtoms::textTagName) {
nodeType = nsIDOMNode::TEXT_NODE;
}
else if (tag == nsGkAtoms::cdataTagName) {
nodeType = nsIDOMNode::CDATA_SECTION_NODE;
}
else if (tag == nsGkAtoms::commentTagName) {
nodeType = nsIDOMNode::COMMENT_NODE;
}
else if (tag == nsGkAtoms::processingInstructionTagName) {
nodeType = nsIDOMNode::PROCESSING_INSTRUCTION_NODE;
}
}
nsCOMPtr<nsIDOMNode> domNode;
if (!nodeType) {
domNode = do_QueryInterface(aNode);
rv = domNode->GetNodeType(&nodeType);
NS_ENSURE_SUCCESS(rv, rv);
}
if (nodeType <= 12 && !((1 << (nodeType-1)) & mWhatToShow)) {
return NS_OK;
}
if (mFilter) {
if (!domNode) {
domNode = do_QueryInterface(aNode);
}
return mFilter->AcceptNode(domNode, _filtered);
}
*_filtered = nsIDOMNodeFilter::FILTER_ACCEPT;
return NS_OK;
}
/*
* Gets the child index of a node within it's parent. Gets a possible index
* from mPossibleIndexes to gain speed. If the value in mPossibleIndexes

View File

@ -45,16 +45,16 @@
#define nsTreeWalker_h___
#include "nsIDOMTreeWalker.h"
#include "nsTraversal.h"
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
#include "nsJSUtils.h"
#include "nsCycleCollectionParticipant.h"
class nsINode;
class nsIDOMNode;
class nsIDOMNodeFilter;
class nsTreeWalker : public nsIDOMTreeWalker
class nsTreeWalker : public nsIDOMTreeWalker, public nsTraversal
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -69,10 +69,6 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS(nsTreeWalker)
private:
nsCOMPtr<nsINode> mRoot;
PRUint32 mWhatToShow;
nsCOMPtr<nsIDOMNodeFilter> mFilter;
PRBool mExpandEntityReferences;
nsCOMPtr<nsINode> mCurrentNode;
/*
@ -150,15 +146,6 @@ private:
PRInt32 aIndexPos,
nsINode** _retval);
/*
* Tests if and how a node should be filtered. Uses mWhatToShow and
* mFilter to test the node.
* @param aNode Node to test
* @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl
* @returns Errorcode
*/
nsresult TestNode(nsINode* aNode, PRInt16* _filtered);
/*
* Gets the child index of a node within it's parent. Gets a possible index
* from mPossibleIndexes to gain speed. If the value in mPossibleIndexes
@ -187,12 +174,5 @@ private:
}
};
// Make a new nsIDOMTreeWalker object
nsresult NS_NewTreeWalker(nsIDOMNode *aRoot,
PRUint32 aWhatToShow,
nsIDOMNodeFilter *aFilter,
PRBool aEntityReferenceExpansion,
nsIDOMTreeWalker **aInstancePtrResult);
#endif

View File

@ -151,6 +151,9 @@ _TEST_FILES = test_bug5141.html \
test_bug415860.html \
test_bug414190.html \
test_bug414796.html \
test_bug416317-1.html \
test_bug416317-2.html \
file_bug416317.xhtml \
test_bug416383.html \
test_bug417255.html \
test_bug417384.html \
@ -186,6 +189,9 @@ _TEST_FILES = test_bug5141.html \
test_text_wholeText.html \
wholeTexty-helper.xml \
test_bug444030.xhtml \
test_NodeIterator_basics_filters.xhtml \
test_NodeIterator_mutations_1.xhtml \
test_NodeIterator_mutations_2.html \
$(NULL)
libs:: $(_TEST_FILES)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- NodeIterator basics and filters tests.
Originally written by Ian Hickson, Mochi-ified by Zack Weinberg.
This file based on 001.xml, 002.xml, and 010.xml from
http://hixie.ch/tests/adhoc/dom/traversal/node-iterator/
with some additional cases.
-->
<head>
<title>DOM Traversal: NodeIterator: Basics and Filters</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<!-- comment -->
<?body processing instruction?>
</div>
<pre id="test">
<script class="testbody" type="text/javascript"><![CDATA[
function compare_arrays(e, f, label) {
var length = (e.length > f.length) ? e.length : f.length;
for (var i = 0; i < length; i += 1) {
if (e[i] > 0)
is(f[i], e[i], label + " - index " + i + ": ");
else
todo_is(f[i], -e[i], label + " - index " + i + ": ");
}
}
/** DOM Traversal: NodeIterator: Basics **/
// NOTE: If you change the document structure, you have to make sure
// the magic numbers in this array (and 'expected_f', below) match.
var expected = new Array(9, // document
1, // html
3, 8, // leading comment
3, 1, // head
3, 1, 3, // title
3, 1, // first script tag
3, 1, // second script tag
3, 1, // stylesheet tag
3, // close head
3, 1, // body
3, 1, // p#display
3, 1, // div#content
3, 8, // comment
3, 7, // processing instruction
3, // close div
3, 1, // pre#test
3, 1, 4, // script and CDATA block
-3, -3, -3); // close close close
// these aren't there
// not sure why
var found = new Array();
var iterator = document.createNodeIterator(document,
NodeFilter.SHOW_ALL,
null, false);
var node;
// forwards
while (node = iterator.nextNode())
found.push(node.nodeType);
compare_arrays(expected, found, 'basics forward');
// backwards
found.length = 0;
while (node = iterator.previousNode())
found.unshift(node.nodeType);
compare_arrays(expected, found, 'basics backward');
/** DOM Traversal: NodeIterator: Filters **/
function filter(n) {
if (n.nodeType == 3) {
return NodeFilter.FILTER_SKIP;
} else if (n.nodeName == 'body') {
return NodeFilter.FILTER_REJECT; // same as _SKIP
}
return 1; // FILTER_ACCEPT
}
// Same warning applies to this array as to 'expected'.
var expect_f = new Array(9, // document
1, // html
8, // leading comment
1, // head
1, // title
1, // first script tag
1, // second script tag
1, // stylesheet tag
// body skipped
1, // p#display
1, // div#content
8, // comment
// processing instruction skipped
1, // pre#test
1, 4); // script and CDATA block
found.length = 0;
iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL,
filter, false);
// forwards
while (node = iterator.nextNode())
found.push(node.nodeType);
compare_arrays(expect_f, found, 'filtered forward');
// backwards
found.length = 0;
while (node = iterator.previousNode())
found.unshift(node.nodeType);
compare_arrays(expect_f, found, 'filtered backward');
]]></script>
</pre>
</body>
</html>

View File

@ -0,0 +1,205 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- NodeIterator mutation tests.
Originally written by Ian Hickson, Mochi-ified by Zack Weinberg.
This file based on 00[3-9].xml from
http://hixie.ch/tests/adhoc/dom/traversal/node-iterator/
-->
<head>
<title>DOM Traversal: NodeIterator: Mutations (1/x)</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<span id="X"></span><span id="Y"><span id="root1"><span id="A"><span id="B"><span id="C"><span id="D"><span id="E"></span></span></span></span></span></span></span>
<span id="root2"><span id="F"><span id="FF"></span></span><span id="G"></span><span id="H"><span id="HH"></span></span></span>
<span id="root3"><span id="I"><span id="II"></span></span><span id="J"></span><span id="K"><span id="KK"></span></span></span>
<span id="root4"><span id="L"></span><span id="M"><span id="MM"></span></span><span id="N"></span></span>
<span id="root5"><span id="O"></span><span id="P"><span id="PP"></span></span><span id="Q"></span></span>
<span id="root6"><span id="R"></span><span id="S"><span id="SS"></span></span><span id="T"></span></span>
<span id="root7"><span id="U"></span><span id="V"><span id="VV"></span></span><span id="W"></span></span>
</div>
<pre id="test">
<script class="testbody" type="text/javascript"><![CDATA[
/** Originally written by Ian Hickson. **/
function check(f, e, label) {
var eid = e.id;
var fid = f ? f.id : 'null';
is(f, e, label + ': expected ' + eid + ' have ' + fid);
}
var childid = 0;
function addChildTo(a) {
var x = document.createElementNS('http://www.w3.org/1999/xhtml', 'span');
x.id = 'X' + childid;
childid++;
ok(a, 'parent ' + (a?a.id:'undefined') + ' for child ' + x.id);
if (a)
a.appendChild(x);
return x;
}
function remove(a) {
var p = a.parentNode;
ok(a && p,
'removing ' + ( a?(a.id?a.id:'(no id)'):'undefined' )
+ ' with parent ' + ( p?(p.id?p.id:'(no id)'):'undefined' ));
if (a && p)
p.removeChild(a);
}
/** Removal of nodes that should have no effect **/
(function () {
var root = $('root1');
var A = $('A');
var B = $('B');
var C = $('C');
var D = $('D');
var E = $('E');
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
null, false);
check(iterator.nextNode(), root, '1.0');
// 1. Remove a node unrelated to the reference node
remove($('X'));
check(iterator.nextNode(), A, '1.1');
// 2. Remove an ancestor of the root node
remove($('Y'));
check(iterator.nextNode(), B, '1.2');
// 3. Remove the root node itself
remove(root);
check(iterator.nextNode(), C, '1.3');
// 4. Remove a descendant of the reference node
remove(E);
check(iterator.nextNode(), D, '1.4');
})();
/** Removal of the reference node **/
(function () {
var root = $('root2');
var F = $('F');
var FF = $('FF');
var G = $('G');
var H = $('H');
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
null, false);
check(iterator.nextNode(), root, '2.0');
check(iterator.nextNode(), F, '2.1');
check(iterator.nextNode(), FF, '2.2');
check(iterator.nextNode(), G, '2.3');
remove(G);
check(iterator.previousNode(), FF, '2.4');
remove(FF);
check(iterator.nextNode(), H, '2.5');
})();
/** Removal of the reference node (deep check) **/
(function () {
var root = $('root3');
var I = $('I');
var II = $('II');
var J = $('J');
var K = $('K');
var KK = $('KK');
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
null, false);
check(iterator.nextNode(), root, '3.0');
check(iterator.nextNode(), I, '3.1');
check(iterator.nextNode(), II, '3.2');
check(iterator.nextNode(), J, '3.3');
remove(J);
var X = addChildTo(II);
check(iterator.nextNode(), X, '3.4');
check(iterator.previousNode(), X, '3.5');
remove(X);
var Y = addChildTo(II);
check(iterator.previousNode(), Y, '3.6');
check(iterator.nextNode(), Y, '3.7');
check(iterator.nextNode(), K, '3.8');
check(iterator.nextNode(), KK, '3.9');
})();
/** Removal of an ancestor of the Reference Node (forwards) **/
(function () {
var root = $('root4');
var L = $('L');
var M = $('M');
var MM = $('MM');
var N = $('N');
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
null, false);
check(iterator.nextNode(), root, '4.1');
check(iterator.nextNode(), L, '4.2');
check(iterator.nextNode(), M, '4.3');
check(iterator.nextNode(), MM, '4.4');
remove(M);
check(iterator.previousNode(), L, '4.5');
})();
/** Removal of an ancestor of the Reference Node (forwards) (deep check) **/
(function () {
var root = $('root5');
var O = $('O');
var P = $('P');
var PP = $('PP');
var Q = $('Q');
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
null, false);
check(iterator.nextNode(), root, '5.1');
check(iterator.nextNode(), O, '5.2');
check(iterator.nextNode(), P, '5.3');
check(iterator.nextNode(), PP, '5.4');
remove(P);
var X = addChildTo(O);
check(iterator.nextNode(), X, '5.5');
})();
/** Removal of an ancestor of the Reference Node (backwards) **/
(function () {
var root = $('root6');
var R = $('R');
var S = $('S');
var SS = $('SS');
var T = $('T');
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
null, false);
check(iterator.nextNode(), root, '6.1');
check(iterator.nextNode(), R, '6.2');
check(iterator.nextNode(), S, '6.3');
check(iterator.nextNode(), SS, '6.4');
check(iterator.previousNode(), SS, '6.5');
remove(S);
check(iterator.nextNode(), T, '6.6');
})();
/** Removal of an ancestor of the Reference Node (backwards) (deep check) **/
(function () {
var root = $('root7');
var U = $('U');
var V = $('V');
var VV = $('VV');
var W = $('W');
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
null, false);
check(iterator.nextNode(), root, '7.1');
check(iterator.nextNode(), U, '7.2');
check(iterator.nextNode(), V, '7.3');
check(iterator.nextNode(), VV, '7.4');
check(iterator.previousNode(), VV, '7.5');
remove(V);
var X = addChildTo(U);
check(iterator.previousNode(), X, '7.6');
})();
]]></script></pre></body></html>

View File

@ -0,0 +1,113 @@
<!DOCTYPE HTML>
<html>
<!-- NodeIterator mutation tests, 2.
Originally part of WebKit, Mochi-ified by Zack Weinberg.
This file based on node-iterator-00[...].html from
http://svn.webkit.org/repository/webkit/trunk/LayoutTests/traversal/
-->
<head>
<title>DOM Traversal: NodeIterator: Mutations (2/x)</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
</head>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
function resetContent() {
var content = $('content');
content.innerHTML = ('<span id="A"><\/span><span id="B"><\/span>'
+ '<span id="C"><\/span><span id="D"><\/span>'
+ '<span id="E"><\/span><span id="F"><\/span>'
+ '<span id="G"><\/span><span id="H"><\/span>'
+ '<span id="I"><\/span>');
return content;
}
function makeSpan(id) {
var e = document.createElement('span');
e.id = id;
return e;
}
function testNodeFilter(n) {
if (n.tagName == 'SPAN')
return NodeFilter.FILTER_ACCEPT;
return NodeFilter.FILTER_SKIP;
}
function checkseq(it, root, expect) {
var checkIt = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
testNodeFilter, false);
var printedPointer = (it.referenceNode == undefined);
var string = '';
var node;
while ((node = checkIt.nextNode()) != null) {
if (!printedPointer && it.referenceNode == node) {
printedPointer = true;
var s = '[' + node.id + '] ';
if (it.pointerBeforeReferenceNode)
string += "* " + s;
else
string += s + "* ";
} else {
string += node.id + " ";
}
}
is(string.slice(0, -1), expect, "sequence check");
}
// first a basic sanity check [node-iterator-001]
(function(){
var root = resetContent();
var it = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
testNodeFilter, false);
checkseq(it, root, 'A B C D E F G H I');
it.nextNode();
checkseq(it, root, '[A] * B C D E F G H I');
it.previousNode();
checkseq(it, root, '* [A] B C D E F G H I');
it.previousNode();
checkseq(it, root, '* [A] B C D E F G H I');
})();
// Mutations that should not move the iterator [node-iterator-002]
(function(){
var root = resetContent();
var it = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
testNodeFilter, false);
for (var i = 0; i < 4; i++)
it.nextNode();
checkseq(it, root, 'A B C [D] * E F G H I');
root.removeChild($('E'));
checkseq(it, root, 'A B C [D] * F G H I');
var X = makeSpan('X');
root.insertBefore(X, $('F'));
checkseq(it, root, 'A B C [D] * X F G H I');
var I = $('I');
root.removeChild(I);
root.insertBefore(I, X);
checkseq(it, root, 'A B C [D] * I X F G H');
})();
// 002 complete
/* Template
(function(){
var root = resetContent();
var it = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
testNodeFilter, false);
})();
*/
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=416317
-->
<head>
<title>Test for Bug 416317</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script>
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=416317">Mozilla Bug 416317</a>
<p id="display">
<iframe src="file_bug416317.xhtml#target"></iframe>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 416317 **/
// Subframe handles the test
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=416317
-->
<head>
<title>Test for Bug 416317</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script>
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=416317">Mozilla Bug 416317</a>
<p id="display">
<iframe style="display: none" src="file_bug416317.xhtml#target"></iframe>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 416317 **/
// Subframe handles the test
</script>
</pre>
</body>
</html>

View File

@ -63,7 +63,6 @@ REQUIRES = \
xpconnect \
caps \
imglib2 \
cairo \
thebes \
view \
$(NULL)

File diff suppressed because it is too large Load Diff

View File

@ -134,10 +134,8 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
mExplicitOriginalTarget = GetTargetFromFrame();
mTmpRealOriginalTarget = mExplicitOriginalTarget;
nsCOMPtr<nsIContent> content = do_QueryInterface(mExplicitOriginalTarget);
if (content) {
if (content->IsNativeAnonymous() || content->GetBindingParent()) {
mExplicitOriginalTarget = nsnull;
}
if (content && content->IsInAnonymousSubtree()) {
mExplicitOriginalTarget = nsnull;
}
}
}

View File

@ -36,7 +36,8 @@ function HTML_TAG(aTagName, aImplClass) {
"nsIDOMNSElement",
"nsIDOMEventTarget",
"nsIDOMNSHTMLElement",
"nsIDOMElementCSSInlineStyle" ];
"nsIDOMElementCSSInlineStyle",
"nsIDOMNodeSelector" ];
// Some interfaces don't appear in classinfo because other interfaces that
// inherit from them do.

View File

@ -241,6 +241,17 @@ nsSVGFE::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
}
}
nsIntRect
nsSVGFE::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance)
{
nsIntRect r;
for (PRUint32 i = 0; i < aSourceChangeBoxes.Length(); ++i) {
r.UnionRect(r, aSourceChangeBoxes[i]);
}
return r;
}
void
nsSVGFE::GetSourceImageNames(nsTArray<nsSVGString*>* aSources)
{
@ -319,6 +330,8 @@ public:
const nsSVGFilterInstance& aInstance);
virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance);
// Gaussian
NS_DECL_NSIDOMSVGFEGAUSSIANBLURELEMENT
@ -344,7 +357,7 @@ protected:
private:
nsresult GetDXY(PRUint32 *aDX, PRUint32 *aDY, const nsSVGFilterInstance& aInstance);
void InflateRectForBlur(nsIntRect* aRect, const nsSVGFilterInstance& aInstance);
nsIntRect InflateRectForBlur(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance);
void GaussianBlur(const Image *aSource, const Image *aTarget,
const nsIntRect& aDataRect,
@ -695,33 +708,38 @@ nsSVGFEGaussianBlurElement::GetSourceImageNames(nsTArray<nsSVGString*>* aSources
aSources->AppendElement(&mStringAttributes[IN1]);
}
void
nsSVGFEGaussianBlurElement::InflateRectForBlur(nsIntRect* aRect,
nsIntRect
nsSVGFEGaussianBlurElement::InflateRectForBlur(const nsIntRect& aRect,
const nsSVGFilterInstance& aInstance)
{
PRUint32 dX, dY;
nsresult rv = GetDXY(&dX, &dY, aInstance);
nsIntRect result = aRect;
if (NS_SUCCEEDED(rv)) {
InflateRectForBlurDXY(aRect, dX, dY);
InflateRectForBlurDXY(&result, dX, dY);
}
return result;
}
nsIntRect
nsSVGFEGaussianBlurElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
const nsSVGFilterInstance& aInstance)
{
nsIntRect r = aSourceBBoxes[0];
InflateRectForBlur(&r, aInstance);
return r;
return InflateRectForBlur(aSourceBBoxes[0], aInstance);
}
void
nsSVGFEGaussianBlurElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
{
nsIntRect r = aTargetBBox;
InflateRectForBlur(&r, aInstance);
aSourceBBoxes[0] = r;
aSourceBBoxes[0] = InflateRectForBlur(aTargetBBox, aInstance);
}
nsIntRect
nsSVGFEGaussianBlurElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance)
{
return InflateRectForBlur(aSourceChangeBoxes[0], aInstance);
}
//----------------------------------------------------------------------
@ -2389,6 +2407,8 @@ public:
const nsSVGFilterInstance& aInstance);
virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance);
// Offset
NS_DECL_NSIDOMSVGFEOFFSETELEMENT
@ -2526,6 +2546,13 @@ nsSVGFEOffsetElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes
return aSourceBBoxes[0] + GetOffset(aInstance);
}
nsIntRect
nsSVGFEOffsetElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance)
{
return aSourceChangeBoxes[0] + GetOffset(aInstance);
}
void
nsSVGFEOffsetElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
@ -2722,6 +2749,8 @@ public:
const nsSVGFilterInstance& aInstance);
virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance);
// Tile
NS_DECL_NSIDOMSVGFETILEELEMENT
@ -2800,6 +2829,13 @@ nsSVGFETileElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
// Just assume we need the entire source bounding box, so do nothing.
}
nsIntRect
nsSVGFETileElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance)
{
return GetMaxRect();
}
static PRInt32 WrapInterval(PRInt32 aVal, PRInt32 aMax)
{
aVal = aVal % aMax;
@ -3413,6 +3449,8 @@ public:
const nsSVGFilterInstance& aInstance);
virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance);
// Morphology
NS_DECL_NSIDOMSVGFEMORPHOLOGYELEMENT
@ -3426,7 +3464,7 @@ public:
protected:
void GetRXY(PRInt32 *aRX, PRInt32 *aRY, const nsSVGFilterInstance& aInstance);
void InflateRect(nsIntRect* aRect, const nsSVGFilterInstance& aInstance);
nsIntRect InflateRect(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance);
virtual NumberAttributesInfo GetNumberInfo();
virtual EnumAttributesInfo GetEnumInfo();
@ -3538,31 +3576,36 @@ nsSVGFEMorphologyElement::GetSourceImageNames(nsTArray<nsSVGString*>* aSources)
aSources->AppendElement(&mStringAttributes[IN1]);
}
void
nsSVGFEMorphologyElement::InflateRect(nsIntRect* aRect,
nsIntRect
nsSVGFEMorphologyElement::InflateRect(const nsIntRect& aRect,
const nsSVGFilterInstance& aInstance)
{
PRInt32 rx, ry;
GetRXY(&rx, &ry, aInstance);
aRect->Inflate(PR_MAX(0, rx), PR_MAX(0, ry));
nsIntRect result = aRect;
result.Inflate(PR_MAX(0, rx), PR_MAX(0, ry));
return result;
}
nsIntRect
nsSVGFEMorphologyElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
const nsSVGFilterInstance& aInstance)
{
nsIntRect r = aSourceBBoxes[0];
InflateRect(&r, aInstance);
return r;
return InflateRect(aSourceBBoxes[0], aInstance);
}
void
nsSVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
{
nsIntRect r = aTargetBBox;
InflateRect(&r, aInstance);
aSourceBBoxes[0] = r;
aSourceBBoxes[0] = InflateRect(aTargetBBox, aInstance);
}
nsIntRect
nsSVGFEMorphologyElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance)
{
return InflateRect(aSourceChangeBoxes[0], aInstance);
}
#define MORPHOLOGY_EPSILON 0.0001
@ -3728,6 +3771,8 @@ public:
const nsSVGFilterInstance& aInstance);
virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance);
// Color Matrix
NS_DECL_NSIDOMSVGFECONVOLVEMATRIXELEMENT
@ -3959,6 +4004,15 @@ nsSVGFEConvolveMatrixElement::ComputeNeededSourceBBoxes(const nsIntRect& aTarget
// source's output bounding box.
}
nsIntRect
nsSVGFEConvolveMatrixElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance)
{
// XXX Precise results are possible but we're going to skip that work
// for now.
return GetMaxRect();
}
static PRInt32 BoundInterval(PRInt32 aVal, PRInt32 aMax)
{
aVal = PR_MAX(aVal, 0);
@ -4492,8 +4546,12 @@ public:
const nsIntRect& aDataRect);
virtual nsSVGString* GetResultImageName() { return &mStringAttributes[RESULT]; }
virtual void GetSourceImageNames(nsTArray<nsSVGString*>* aSources);
// XXX shouldn't we have ComputeTargetBBox here, since the output can
// extend beyond the bounds of the inputs thanks to the convolution kernel?
virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance);
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFELightingElementBase::)
NS_FORWARD_NSIDOMNODE(nsSVGFELightingElementBase::)
@ -4541,7 +4599,7 @@ nsSVGElement::StringInfo nsSVGFELightingElement::sStringInfo[2] =
NS_IMPL_ADDREF_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase)
NS_IMPL_RELEASE_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase)
NS_INTERFACE_MAP_BEGIN(nsSVGFELightingElement)
NS_INTERFACE_MAP_BEGIN(nsSVGFELightingElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGFELightingElementBase)
//----------------------------------------------------------------------
@ -4573,6 +4631,14 @@ nsSVGFELightingElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
// but just leave it and assume we use the entire source bounding box.
}
nsIntRect
nsSVGFELightingElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance)
{
// XXX be conservative for now
return GetMaxRect();
}
#define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
#define NORMALIZE(vec) \
PR_BEGIN_MACRO \
@ -5444,6 +5510,8 @@ public:
const nsSVGFilterInstance& aInstance);
virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance);
// DisplacementMap
NS_DECL_NSIDOMSVGFEDISPLACEMENTMAPELEMENT
@ -5665,6 +5733,15 @@ nsSVGFEDisplacementMapElement::ComputeNeededSourceBBoxes(const nsIntRect& aTarge
// If we change this, we need to change coordinate assumptions above
}
nsIntRect
nsSVGFEDisplacementMapElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance)
{
// XXX we could do something clever here involving analysis of 'scale'
// to figure out the maximum displacement
return GetMaxRect();
}
//----------------------------------------------------------------------
// nsSVGElement methods

View File

@ -140,15 +140,15 @@ public:
// Return a list of all image names used as sources. Default is to
// return no sources.
virtual void GetSourceImageNames(nsTArray<nsSVGString*>* aSources);
// Compute the bounding-box of the filter output. The default is just the
// union of the source bounding-boxes. The caller is
// Compute the bounding box of the filter output. The default is just the
// union of the source bounding boxes. The caller is
// responsible for clipping this to the filter primitive subregion, so
// if the filter fills its filter primitive subregion, it can just
// return GetMaxRect() here.
// The source bounding-boxes are ordered corresponding to GetSourceImageNames.
// The source bounding boxes are ordered corresponding to GetSourceImageNames.
virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
const nsSVGFilterInstance& aInstance);
// Given a bounding-box for what we need to compute in the target,
// Given a bounding box for what we need to compute in the target,
// compute which regions of the inputs are needed. On input
// aSourceBBoxes contains the bounding box of what's rendered by
// each source; this function should change those boxes to indicate
@ -157,7 +157,14 @@ public:
// target bbox.
virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
// Given the bounding boxes for the pixels that have changed in the inputs,
// compute the bounding box of the changes in this primitive's output.
// The result will be clipped by the caller to the result of ComputeTargetBBox
// since there's no way anything outside that can change.
// The default implementation returns the union of the source change boxes.
virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
const nsSVGFilterInstance& aInstance);
// Perform the actual filter operation.
// We guarantee that every mImage from aSources and aTarget has the
// same width, height, stride and device offset.

View File

@ -1263,15 +1263,11 @@ nsBindingManager::WalkRules(nsStyleSet* aStyleSet,
}
}
nsIContent* parent = content->GetBindingParent();
if (parent == content) {
NS_ASSERTION(content->IsNativeAnonymous(), "Unexpected binding parent");
break; // The anonymous content case is often deliberately hacked to
// return itself to cut off style inheritance here. Do that.
if (content->IsRootOfNativeAnonymousSubtree()) {
break; // Deliberately cut off style inheritance here.
}
content = parent;
content = content->GetBindingParent();
} while (content);
// If "content" is non-null that means we cut off inheritance at some point

View File

@ -110,11 +110,10 @@ IsAncestorBinding(nsIDocument* aDocument,
NS_ASSERTION(aChild, "expected a child content");
PRUint32 bindingRecursion = 0;
nsIContent* bindingParent = aChild->GetBindingParent();
nsBindingManager* bindingManager = aDocument->BindingManager();
for (nsIContent* prev = aChild;
bindingParent && prev != bindingParent;
prev = bindingParent, bindingParent = bindingParent->GetBindingParent()) {
for (nsIContent *bindingParent = aChild->GetBindingParent();
bindingParent;
bindingParent = bindingParent->GetBindingParent()) {
nsXBLBinding* binding = bindingManager->GetBinding(bindingParent);
if (!binding) {
continue;

View File

@ -1086,6 +1086,7 @@ nsXULElement::UnregisterAccessKey(const nsAString& aOldValue)
if (mNodeInfo->Equals(nsGkAtoms::label)) {
// For anonymous labels the unregistering must
// occur on the binding parent control.
// XXXldb: And what if the binding parent is null?
content = GetBindingParent();
}

View File

@ -80,6 +80,7 @@ XPIDLSRCS = \
nsIDOMDOMConfiguration.idl \
nsIDOMNSEditableElement.idl \
nsIDOMNSElement.idl \
nsIDOMNodeSelector.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,53 @@
/* -*- Mode: IDL; 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
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Boris Zbarsky <bzbarsky@mit.edu> (original author)
*
* 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 "domstubs.idl"
/**
* The nsIDOMNodeSelector interface is an interface for getting nodes
* that mtch a given CSS selector.
*
* For more information on this interface please see
* http://www.w3.org/TR/selectors-api/
*/
[scriptable, uuid(7cebc153-168a-416c-ba5a-56a8c2ddb2ec)]
interface nsIDOMNodeSelector : nsISupports
{
nsIDOMElement querySelector(in DOMString selectors);
nsIDOMNodeList querySelectorAll(in DOMString selectors);
};

View File

@ -56,4 +56,8 @@ interface nsIDOMNodeIterator : nsISupports
nsIDOMNode previousNode()
raises(DOMException);
void detach();
// WebKit extensions, convenient for debugging.
readonly attribute nsIDOMNode referenceNode;
readonly attribute boolean pointerBeforeReferenceNode;
};

View File

@ -437,6 +437,9 @@ enum nsDOMClassInfoID {
eDOMClassInfo_HTMLAudioElement_id,
#endif
// DOM Traversal NodeIterator class
eDOMClassInfo_NodeIterator_id,
// This one better be the last one in this list
eDOMClassInfoIDCount
};

View File

@ -333,6 +333,7 @@
#include "nsIDOMRange.h"
#include "nsIDOMNSRange.h"
#include "nsIDOMRangeException.h"
#include "nsIDOMNodeIterator.h"
#include "nsIDOMTreeWalker.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMXULElement.h"
@ -1264,6 +1265,10 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(HTMLAudioElement, nsHTMLElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
#endif
// DOM Traversal NodeIterator class
NS_DEFINE_CLASSINFO_DATA(NodeIterator, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
};
// Objects that shuld be constructable through |new Name();|
@ -1852,14 +1857,17 @@ nsDOMClassInfo::RegisterExternalClasses()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Document) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathEvaluator)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathEvaluator) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
#define DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLElement) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementCSSInlineStyle) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
#define DOM_CLASSINFO_EVENT_MAP_ENTRIES \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent) \
@ -2000,6 +2008,7 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(DocumentFragment, nsIDOMDocumentFragment)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentFragment)
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(Element, nsIDOMElement)
@ -2007,6 +2016,7 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(Attr, nsIDOMAttr)
@ -2512,6 +2522,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSRange)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(NodeIterator, nsIDOMNodeIterator)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeIterator)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(TreeWalker, nsIDOMTreeWalker)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMTreeWalker)
DOM_CLASSINFO_MAP_END
@ -2533,6 +2547,7 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementCSSInlineStyle)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(XULCommandDispatcher, nsIDOMXULCommandDispatcher)
@ -2648,7 +2663,8 @@ nsDOMClassInfo::Init()
#define DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGElement) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
#define DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) \

View File

@ -440,7 +440,7 @@ nsEditor::GetDesiredSpellCheckState()
return PR_FALSE;
}
if (content->IsNativeAnonymous()) {
if (content->IsRootOfNativeAnonymousSubtree()) {
content = content->GetParent();
}
@ -5241,7 +5241,7 @@ nsEditor::GetPIDOMEventTarget()
nsCOMPtr<nsIContent> content = do_QueryInterface(rootElement);
if (content && content->IsNativeAnonymous())
if (content && content->IsRootOfNativeAnonymousSubtree())
{
mEventTarget = do_QueryInterface(content->GetParent());
piTarget = mEventTarget;

View File

@ -188,7 +188,7 @@ nsHTMLEditor::CreateAnonymousElement(const nsAString & aTag, nsIDOMNode * aPare
// establish parenthood of the element
newContent->SetNativeAnonymous();
res = newContent->BindToTree(doc, parentContent, newContent, PR_TRUE);
res = newContent->BindToTree(doc, parentContent, parentContent, PR_TRUE);
if (NS_FAILED(res)) {
newContent->UnbindFromTree();
return res;

View File

@ -5928,7 +5928,7 @@ nsHTMLEditor::IsAnonymousElement(nsIDOMElement * aElement, PRBool * aReturn)
{
NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
*aReturn = content->IsNativeAnonymous();
*aReturn = content->IsRootOfNativeAnonymousSubtree();
return NS_OK;
}

View File

@ -366,7 +366,7 @@ nsFindContentIterator::SetupInnerIterator(nsIContent* aContent)
if (!aContent) {
return;
}
NS_ASSERTION(!aContent->IsNativeAnonymous(), "invalid call");
NS_ASSERTION(!aContent->IsRootOfNativeAnonymousSubtree(), "invalid call");
nsIDocument* doc = aContent->GetDocument();
nsIPresShell* shell = doc ? doc->GetPrimaryShell() : nsnull;

View File

@ -411,21 +411,6 @@ FocusElementButNotDocument(nsIDocument* aDocument, nsIContent* aContent)
esm->SetFocusedContent(nsnull);
}
static PRBool
IsInNativeAnonymousSubtree(nsIContent* aContent)
{
while (aContent) {
nsIContent* bindingParent = aContent->GetBindingParent();
if (bindingParent == aContent) {
return PR_TRUE;
}
aContent = bindingParent;
}
return PR_FALSE;
}
void nsWebBrowserFind::SetSelectionAndScroll(nsIDOMWindow* aWindow,
nsIDOMRange* aRange)
{
@ -451,7 +436,7 @@ void nsWebBrowserFind::SetSelectionAndScroll(nsIDOMWindow* aWindow,
// <textarea> or text <input>, we need to get the outer frame
nsITextControlFrame *tcFrame = nsnull;
for ( ; content; content = content->GetParent()) {
if (!IsInNativeAnonymousSubtree(content)) {
if (!content->IsInNativeAnonymousSubtree()) {
nsIFrame* f = presShell->GetPrimaryFrameFor(content);
if (!f)
return;

View File

@ -7,9 +7,8 @@ http://www.cairographics.org/.
VERSIONS:
cairo (1.6.4 - 1.6.4)
pixman (0.10.x - pixman-0.10.0-8-g0b207ae)
glitz 0.5.2 (cvs - 2006-01-10)
cairo (1.6.4-350-g1a9809b)
pixman (pixman-0.11.8-7-gdb3fb5e)
***** NOTE FOR VISUAL C++ 6.0 *****
@ -19,21 +18,6 @@ VC6 is not supported. Please upgrade to VC8.
Some specific things:
cairo git commit ea6dbfd36f2182fda16cb82bca92007e0f7b8d77 -
[cairo-meta-surface] Save and restore the original clip.
cairo git commit d96fdd58abf8d6c8692dbb08ec54cdd80accba79 -
win32: Fix broken printing of type1 fonts
cairo git commit 547e2f552cff264b943803d3a1ff03d05bde35c0
Fix win32-printing show_glyphs analysis for Type 1 fonts
cairo git commit 158d24412bba99a4f57907d7fd22a86aae6e87af
Make win32-printing surface work with bitmap fonts
cairo git commit d35d6eec24c1b7ab0a49149a51bf65ea8e223203
Fix win32 bitmap font metrics when device scale != 1
max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues
win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1
@ -42,10 +26,6 @@ nonfatal-assertions.patch: Make assertions non-fatal
buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug 413583.
clip-clone.patch: _cairo_clip_init_deep_copy should pass 0,0 as the
source coordinates to clone from since it wants an exact copy of the
source's clipping surface
==== pixman patches ====
endian.patch: include cairo-platform.h for endian macros

View File

@ -118,6 +118,7 @@ CSRCS = \
cairo-surface-fallback.c \
cairo-traps.c \
cairo-unicode.c \
cairo-user-font.c \
cairo-wideint.c \
$(NULL)
@ -128,6 +129,7 @@ EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-ren
PSPDF_BASE_CSRCS = \
cairo-base85-stream.c \
cairo-type1-fallback.c \
cairo-type3-glyph-surface.c \
cairo-truetype-subset.c \
cairo-cff-subset.c \
$(NULL)

View File

@ -42,6 +42,14 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
int width,
int height);
cairo_private void
_cairo_analysis_surface_set_ctm (cairo_surface_t *surface,
cairo_matrix_t *ctm);
cairo_private void
_cairo_analysis_surface_get_ctm (cairo_surface_t *surface,
cairo_matrix_t *ctm);
cairo_private cairo_region_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *surface);
@ -58,4 +66,8 @@ cairo_private void
_cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface,
cairo_box_t *bbox);
cairo_private cairo_surface_t *
_cairo_null_surface_create (cairo_content_t content);
#endif /* CAIRO_ANALYSIS_SURFACE_H */

View File

@ -84,7 +84,7 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *
old_height = surface->height;
old_clip = surface->current_clip;
status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents);
if (status)
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
surface->width = meta_extents.width;
@ -140,22 +140,13 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
}
}
_cairo_box_from_rectangle (&bbox, rect);
if (surface->has_ctm) {
double x1, y1, x2, y2;
x1 = rect->x;
y1 = rect->y;
x2 = rect->x + rect->width;
y2 = rect->y + rect->height;
_cairo_matrix_transform_bounding_box (&surface->ctm,
&x1, &y1, &x2, &y2,
NULL);
rect->x = floor (x1);
rect->y = floor (y1);
_cairo_matrix_transform_bounding_box_fixed (&surface->ctm, &bbox, NULL);
x2 = ceil (x2) - rect->x;
y2 = ceil (y2) - rect->y;
if (x2 <= 0 || y2 <= 0) {
if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) {
/* Even though the operation is not visible we must be
* careful to not allow unsupported operations to be
* replayed to the backend during
@ -171,15 +162,9 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
}
}
rect->width = x2;
rect->height = y2;
_cairo_box_round_to_rectangle (&bbox, rect);
}
bbox.p1.x = _cairo_fixed_from_int (rect->x);
bbox.p1.y = _cairo_fixed_from_int (rect->y);
bbox.p2.x = _cairo_fixed_from_int (rect->x + rect->width);
bbox.p2.y = _cairo_fixed_from_int (rect->y + rect->height);
if (surface->first_op) {
surface->first_op = FALSE;
surface->page_bbox = bbox;
@ -253,6 +238,8 @@ _cairo_analysis_surface_finish (void *abstract_surface)
_cairo_region_fini (&surface->supported_region);
_cairo_region_fini (&surface->fallback_region);
cairo_surface_destroy (surface->target);
return CAIRO_STATUS_SUCCESS;
}
@ -319,7 +306,7 @@ _cairo_analysis_surface_paint (void *abstract_surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -377,7 +364,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
}
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -432,7 +419,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -511,7 +498,7 @@ _cairo_analysis_surface_fill (void *abstract_surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -569,26 +556,120 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_rectangle_int_t extents, glyph_extents;
if (!surface->target->backend->show_glyphs)
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
else
/* Adapted from _cairo_surface_show_glyphs */
if (surface->target->backend->show_glyphs)
backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
source,
glyphs, num_glyphs,
scaled_font);
source,
glyphs, num_glyphs,
scaled_font,
remaining_glyphs);
else if (surface->target->backend->show_text_glyphs)
backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
source,
NULL, 0,
glyphs, num_glyphs,
NULL, 0,
FALSE,
scaled_font);
else
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
status = _cairo_pattern_get_extents (source, &source_extents);
if (status)
return status;
_cairo_rectangle_intersect (&extents, &source_extents);
}
_cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs,
num_glyphs,
&glyph_extents);
if (status)
return status;
_cairo_rectangle_intersect (&extents, &glyph_extents);
}
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
return status;
}
static cairo_bool_t
_cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface)
{
cairo_analysis_surface_t *surface = abstract_surface;
return _cairo_surface_has_show_text_glyphs (surface->target);
}
static cairo_int_status_t
_cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_rectangle_int_t extents, glyph_extents;
/* Adapted from _cairo_surface_show_glyphs */
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->target->backend->show_text_glyphs)
backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
scaled_font);
if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
int remaining_glyphs = num_glyphs;
backend_status = surface->target->backend->show_glyphs (surface->target, op,
source,
glyphs, num_glyphs,
scaled_font,
&remaining_glyphs);
glyphs += num_glyphs - remaining_glyphs;
num_glyphs = remaining_glyphs;
if (remaining_glyphs == 0)
backend_status = CAIRO_STATUS_SUCCESS;
}
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -650,6 +731,9 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = {
NULL, /* is_similar */
NULL, /* reset */
NULL, /* fill_stroke */
NULL, /* create_solid_pattern_surface */
_cairo_analysis_surface_has_show_text_glyphs,
_cairo_analysis_surface_show_text_glyphs
};
cairo_surface_t *
@ -673,21 +757,54 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
cairo_matrix_init_identity (&surface->ctm);
surface->has_ctm = FALSE;
surface->target = target;
surface->target = cairo_surface_reference (target);
surface->first_op = TRUE;
surface->has_supported = FALSE;
surface->has_unsupported = FALSE;
surface->page_bbox.p1.x = 0;
surface->page_bbox.p1.y = 0;
surface->page_bbox.p2.x = 0;
surface->page_bbox.p2.y = 0;
_cairo_region_init (&surface->supported_region);
_cairo_region_init (&surface->fallback_region);
surface->current_clip.x = 0;
surface->current_clip.y = 0;
surface->current_clip.width = width;
surface->current_clip.height = height;
if (width == -1 && height == -1) {
surface->current_clip.x = CAIRO_RECT_INT_MIN;
surface->current_clip.y = CAIRO_RECT_INT_MIN;
surface->current_clip.width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
surface->current_clip.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
} else {
surface->current_clip.x = 0;
surface->current_clip.y = 0;
surface->current_clip.width = width;
surface->current_clip.height = height;
}
return &surface->base;
}
cairo_private void
_cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
cairo_matrix_t *ctm)
{
cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface;
surface->ctm = *ctm;
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
}
cairo_private void
_cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface,
cairo_matrix_t *ctm)
{
cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface;
*ctm = surface->ctm;
}
cairo_region_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
{
@ -728,3 +845,108 @@ _cairo_analysis_surface_get_bounding_box (cairo_surface_t *abstract_surface,
*bbox = surface->page_bbox;
}
/* null surface type: a surface that does nothing (has no side effects, yay!) */
static cairo_int_status_t
_return_success (void)
{
return CAIRO_STATUS_SUCCESS;
}
/* These typedefs are just to silence the compiler... */
typedef cairo_int_status_t
(*_set_clip_region_func) (void *surface,
cairo_region_t *region);
typedef cairo_int_status_t
(*_paint_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source);
typedef cairo_int_status_t
(*_mask_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask);
typedef cairo_int_status_t
(*_stroke_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias);
typedef cairo_int_status_t
(*_fill_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias);
typedef cairo_int_status_t
(*_show_glyphs_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs);
static const cairo_surface_backend_t cairo_null_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
NULL, /* create_similar */
NULL, /* finish */
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
NULL, /* copy_page */
NULL, /* show_page */
(_set_clip_region_func) _return_success, /* set_clip_region */
NULL, /* intersect_clip_path */
NULL, /* get_extents */
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
(_paint_func) _return_success, /* paint */
(_mask_func) _return_success, /* mask */
(_stroke_func) _return_success, /* stroke */
(_fill_func) _return_success, /* fill */
(_show_glyphs_func) _return_success, /* show_glyphs */
NULL, /* snapshot */
NULL, /* is_similar */
NULL, /* reset */
NULL, /* fill_stroke */
NULL, /* create_solid_pattern_surface */
NULL, /* has_show_text_glyphs */
NULL /* show_text_glyphs */
};
cairo_surface_t *
_cairo_null_surface_create (cairo_content_t content)
{
cairo_surface_t *surface;
surface = malloc (sizeof (cairo_surface_t));
if (surface == NULL) {
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
_cairo_surface_init (surface, &cairo_null_surface_backend, content);
return surface;
}

View File

@ -181,13 +181,15 @@ _cairo_arc_in_direction (cairo_t *cr,
double angle_max,
cairo_direction_t dir)
{
if (cairo_status (cr))
return;
while (angle_max - angle_min > 4 * M_PI)
angle_max -= 2 * M_PI;
/* Recurse if drawing arc larger than pi */
if (angle_max - angle_min > M_PI) {
double angle_mid = angle_min + (angle_max - angle_min) / 2.0;
/* XXX: Something tells me this block could be condensed. */
if (dir == CAIRO_DIRECTION_FORWARD) {
_cairo_arc_in_direction (cr, xc, yc, radius,
angle_min, angle_mid,
@ -205,7 +207,7 @@ _cairo_arc_in_direction (cairo_t *cr,
angle_min, angle_mid,
dir);
}
} else {
} else if (angle_max != angle_min) {
cairo_matrix_t ctm;
int i, segments;
double angle, angle_step;

View File

@ -236,7 +236,7 @@ _cairo_array_copy_element (cairo_array_t *array, int index, void *dst)
* _cairo_array_index (array, _cairo_array_num_elements (array) - 1);
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* operation.
**/
cairo_status_t
@ -256,7 +256,7 @@ _cairo_array_append (cairo_array_t *array,
* @elements into the array.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* operation.
**/
cairo_status_t
@ -287,7 +287,7 @@ _cairo_array_append_multiple (cairo_array_t *array,
* for in the return value of _cairo_array_num_elements().
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* operation.
**/
cairo_status_t

View File

@ -1,4 +1,5 @@
/* cairo_output_stream.c: Output stream abstraction
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*

View File

@ -508,7 +508,7 @@ det64_128 (cairo_int64_t a,
* result is provided as a coordinate pair of 128-bit integers.
*
* Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or
* CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
* %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
*/
static cairo_bo_status_t
intersect_lines (cairo_bo_edge_t *a,
@ -1214,7 +1214,7 @@ _active_edges_to_traps (cairo_bo_edge_t *head,
int in_out = 0;
cairo_bo_edge_t *edge;
for (edge = head; edge && edge->next; edge = edge->next) {
for (edge = head; edge; edge = edge->next) {
if (fill_rule == CAIRO_FILL_RULE_WINDING) {
if (edge->reversed)
in_out++;
@ -1415,9 +1415,9 @@ update_minmax(cairo_fixed_t *inout_min,
}
cairo_status_t
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule)
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
const cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule)
{
int intersections;
cairo_status_t status;

View File

@ -36,7 +36,7 @@
#ifndef CAIRO_BEOS_H
#define CAIRO_BEOS_H
#include <cairo.h>
#include "cairo.h"
#if CAIRO_HAS_BEOS_SURFACE

View File

@ -296,7 +296,7 @@ _cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
* entry_destroy() callback will be called on it).
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
**/
cairo_status_t
_cairo_cache_insert (cairo_cache_t *cache,

View File

@ -274,13 +274,13 @@ _cairo_clip_combine_to_surface (cairo_clip_t *clip,
int dst_y,
const cairo_rectangle_int_t *extents)
{
cairo_pattern_union_t pattern;
cairo_surface_pattern_t pattern;
cairo_status_t status;
if (clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
_cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
_cairo_pattern_init_for_surface (&pattern, clip->surface);
status = _cairo_surface_composite (op,
&pattern.base,
@ -485,8 +485,7 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
CAIRO_CONTENT_ALPHA,
surface_rect.width,
surface_rect.height,
CAIRO_COLOR_TRANSPARENT,
&pattern.base);
CAIRO_COLOR_TRANSPARENT);
if (surface->status) {
_cairo_pattern_fini (&pattern.base);
return surface->status;
@ -630,7 +629,7 @@ _cairo_clip_translate (cairo_clip_t *clip,
_cairo_fixed_to_double (ty));
while (clip_path) {
_cairo_path_fixed_device_transform (&clip_path->path, &matrix);
_cairo_path_fixed_transform (&clip_path->path, &matrix);
clip_path = clip_path->prev;
}
}
@ -678,7 +677,8 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
if (other->surface) {
status = _cairo_surface_clone_similar (target, other->surface,
0, 0,
0,
0,
other->surface_rect.width,
other->surface_rect.height,
&clip->surface);

View File

@ -111,7 +111,7 @@ CAIRO_BEGIN_DECLS
#define __attribute__(x)
#endif
#if defined(__WIN32__) || defined(_MSC_VER)
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
#define snprintf _snprintf
#endif

View File

@ -61,15 +61,15 @@ cairo_debug_reset_static_data (void)
{
CAIRO_MUTEX_INITIALIZE ();
_cairo_font_reset_static_data ();
_cairo_font_face_reset_static_data ();
#if CAIRO_HAS_FT_FONT
_cairo_ft_font_reset_static_data ();
#endif
_cairo_pattern_reset_static_data ();
_cairo_scaled_font_reset_static_data ();
_cairo_pattern_reset_static_data ();
CAIRO_MUTEX_FINALIZE ();
}

View File

@ -1,4 +1,5 @@
/* cairo_deflate_stream.c: Output stream abstraction
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Adrian Johnson
*

View File

@ -52,8 +52,6 @@
#define CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_QUARTZ
#ifndef _CAIROINT_H_
/* Obsolete functions. These definitions exist to coerce the compiler
* into providing a little bit of guidance with its error
* messages. The idea is to help users port their old code without
@ -137,6 +135,4 @@
#define cairo_get_status_string cairo_get_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
#define cairo_status_string cairo_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
#endif
#endif /* CAIRO_DEPRECATED_H */

View File

@ -1606,7 +1606,8 @@ _cairo_directfb_surface_show_glyphs (void *abstract_dst,
cairo_pattern_t *pattern,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
{
cairo_directfb_surface_t *dst = abstract_dst;
cairo_directfb_font_cache_t *cache;

View File

@ -47,7 +47,7 @@
#ifndef CAIRO_DIRECTFB_H
#define CAIRO_DIRECTFB_H
#include <cairo.h>
#include "cairo.h"
#ifdef CAIRO_HAS_DIRECTFB_SURFACE

View File

@ -226,6 +226,17 @@ _cairo_fixed_mul (cairo_fixed_t a, cairo_fixed_t b)
return _cairo_int64_to_int32(_cairo_int64_rsl (temp, CAIRO_FIXED_FRAC_BITS));
}
/* computes a * b / c */
static inline cairo_fixed_t
_cairo_fixed_mul_div (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c)
{
cairo_int64_t ab = _cairo_int32x32_64_mul (a, b);
cairo_int64_t c64 = _cairo_int32_to_int64 (c);
cairo_int64_t quo = _cairo_int64_divrem (ab, c64).quo;
return _cairo_int64_to_int32(quo);
}
#else
# error Please define multiplication and other operands for your fixed-point type size
#endif

View File

@ -63,6 +63,8 @@ _cairo_font_face_set_error (cairo_font_face_t *font_face,
if (status == CAIRO_STATUS_SUCCESS)
return status;
/* Don't overwrite an existing error. This preserves the first
* error, which is the most significant. */
_cairo_status_set_error (&font_face->status, status);
return _cairo_error (status);
@ -132,7 +134,8 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
if (! _cairo_reference_count_dec_and_test (&font_face->ref_count))
return;
font_face->backend->destroy (font_face);
if (font_face->backend->destroy)
font_face->backend->destroy (font_face);
/* We allow resurrection to deal with some memory management for the
* FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
@ -534,7 +537,7 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
}
void
_cairo_font_reset_static_data (void)
_cairo_font_face_reset_static_data (void)
{
_cairo_scaled_font_map_destroy ();

View File

@ -95,7 +95,6 @@ cairo_font_options_create (void)
return options;
}
slim_hidden_def (cairo_font_options_create);
/**
* cairo_font_options_copy:
@ -144,7 +143,6 @@ cairo_font_options_destroy (cairo_font_options_t *options)
free (options);
}
slim_hidden_def (cairo_font_options_destroy);
/**
* cairo_font_options_status:

View File

@ -1,3 +1,4 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2000 Keith Packard
@ -91,7 +92,7 @@ typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
struct _cairo_ft_unscaled_font {
cairo_unscaled_font_t base;
cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */
cairo_bool_t from_face; /* was the FT_Face provided by user? */
FT_Face face; /* provided or cached face */
/* only set if from_face is false */
@ -282,17 +283,22 @@ _cairo_ft_unscaled_font_map_unlock (void)
static void
_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
cairo_bool_t from_face,
char *filename,
int id)
int id,
FT_Face face)
{
unsigned long hash;
key->from_face = from_face;
key->filename = filename;
key->id = id;
key->face = face;
/* 1607 is just an arbitrary prime. */
hash = _cairo_hash_string (filename);
/* the constants are just arbitrary primes */
hash += ((unsigned long) id) * 1607;
hash += ((unsigned long) face) * 2137;
key->base.hash_entry.hash = hash;
}
@ -320,6 +326,7 @@ _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
**/
static cairo_status_t
_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
cairo_bool_t from_face,
const char *filename,
int id,
FT_Face face)
@ -327,11 +334,9 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
_cairo_unscaled_font_init (&unscaled->base,
&cairo_ft_unscaled_font_backend);
if (face) {
if (from_face) {
unscaled->from_face = TRUE;
unscaled->face = face;
unscaled->filename = NULL;
unscaled->id = 0;
_cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, face);
} else {
char *filename_copy;
@ -341,8 +346,7 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
filename_copy = strdup (filename);
if (filename_copy == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);
_cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL);
}
unscaled->have_scale = FALSE;
@ -354,12 +358,6 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
return CAIRO_STATUS_SUCCESS;
}
cairo_bool_t
_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font)
{
return unscaled_font->backend == &cairo_ft_unscaled_font_backend;
}
/**
* _cairo_ft_unscaled_font_fini:
*
@ -391,35 +389,41 @@ _cairo_ft_unscaled_font_keys_equal (const void *key_a,
const cairo_ft_unscaled_font_t *unscaled_a = key_a;
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
unscaled_a->id == unscaled_b->id);
if (unscaled_a->id == unscaled_b->id &&
unscaled_a->from_face == unscaled_b->from_face)
{
if (unscaled_a->from_face)
return unscaled_a->face == unscaled_b->face;
if (unscaled_a->filename == NULL && unscaled_b->filename == NULL)
return TRUE;
else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL)
return FALSE;
else
return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0);
}
return FALSE;
}
/* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
* pattern. Returns a new reference to the unscaled font.
*/
static cairo_ft_unscaled_font_t *
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
_cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
char *filename,
int id,
FT_Face font_face)
{
cairo_ft_unscaled_font_t key, *unscaled;
cairo_ft_unscaled_font_map_t *font_map;
cairo_status_t status;
FcChar8 *fc_filename;
char *filename;
int id;
if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
goto UNWIND;
filename = (char *) fc_filename;
if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
goto UNWIND;
font_map = _cairo_ft_unscaled_font_map_lock ();
if (font_map == NULL)
goto UNWIND;
_cairo_ft_unscaled_font_init_key (&key, filename, id);
_cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face);
/* Return existing unscaled font if it exists in the hash table. */
if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
@ -437,7 +441,7 @@ _cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
goto UNWIND_FONT_MAP_LOCK;
}
status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);
status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face);
if (status)
goto UNWIND_UNSCALED_MALLOC;
@ -460,57 +464,66 @@ UNWIND:
return NULL;
}
static cairo_ft_unscaled_font_t *
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
{
FT_Face font_face = NULL;
char *filename = NULL;
int id = 0;
if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) != FcResultMatch) {
FcChar8 *fc_filename = NULL;
if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
goto UNWIND;
filename = (char *) fc_filename;
if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
goto UNWIND;
}
return _cairo_ft_unscaled_font_create_internal (font_face != NULL, filename, id, font_face);
UNWIND:
return NULL;
}
static cairo_ft_unscaled_font_t *
_cairo_ft_unscaled_font_create_from_face (FT_Face face)
{
cairo_status_t status;
cairo_ft_unscaled_font_t *unscaled;
unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
if (unscaled == NULL) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);
if (status) {
free (unscaled);
return NULL;
}
return unscaled;
return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face);
}
static void
_cairo_ft_unscaled_font_destroy (void *abstract_font)
{
cairo_ft_unscaled_font_t *unscaled = abstract_font;
cairo_ft_unscaled_font_map_t *font_map;
if (unscaled == NULL)
return;
font_map = _cairo_ft_unscaled_font_map_lock ();
/* All created objects must have been mapped in the font map. */
assert (font_map != NULL);
_cairo_hash_table_remove (font_map->hash_table,
&unscaled->base.hash_entry);
if (unscaled->from_face) {
/* See comments in _ft_font_face_destroy about the "zombie" state
* for a _ft_font_face.
*/
if (unscaled->faces && !unscaled->faces->unscaled)
cairo_font_face_destroy (&unscaled->faces->base);
unscaled->face = NULL;
} else {
cairo_ft_unscaled_font_map_t *font_map;
font_map = _cairo_ft_unscaled_font_map_lock ();
/* All created objects must have been mapped in the font map. */
assert (font_map != NULL);
_cairo_hash_table_remove (font_map->hash_table,
&unscaled->base.hash_entry);
_font_map_release_face_lock_held (font_map, unscaled);
_cairo_ft_unscaled_font_map_unlock ();
}
unscaled->face = NULL;
_cairo_ft_unscaled_font_map_unlock ();
_cairo_ft_unscaled_font_fini (unscaled);
}
@ -579,7 +592,7 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
return face;
}
slim_hidden_def (cairo_ft_scaled_font_lock_face);
/* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
*/
@ -592,7 +605,7 @@ _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
CAIRO_MUTEX_UNLOCK (unscaled->mutex);
}
slim_hidden_def (cairo_ft_scaled_font_unlock_face);
static cairo_status_t
_compute_transform (cairo_ft_font_transform_t *sf,
@ -611,7 +624,7 @@ _compute_transform (cairo_ft_font_transform_t *sf,
status = _cairo_matrix_compute_scale_factors (scale,
&x_scale, &y_scale,
/* XXX */ 1);
1);
if (status)
return status;
@ -1274,7 +1287,7 @@ typedef struct _cairo_ft_scaled_font {
cairo_ft_options_t ft_options;
} cairo_ft_scaled_font_t;
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
/* The load flags passed to FT_Load_Glyph control aspects like hinting and
* antialiasing. Here we compute them from the fields of a FcPattern.
@ -1519,7 +1532,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
status = _cairo_scaled_font_init (&scaled_font->base,
font_face,
font_matrix, ctm, options,
&cairo_ft_scaled_font_backend);
&_cairo_ft_scaled_font_backend);
if (status) {
_cairo_unscaled_font_destroy (&unscaled->base);
free (scaled_font);
@ -1597,7 +1610,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
cairo_bool_t
_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
{
return scaled_font->backend == &cairo_ft_scaled_font_backend;
return scaled_font->backend == &_cairo_ft_scaled_font_backend;
}
static cairo_status_t
@ -2169,40 +2182,36 @@ _cairo_ft_load_truetype_table (void *abstract_font,
}
static cairo_int_status_t
_cairo_ft_map_glyphs_to_unicode (void *abstract_font,
cairo_scaled_font_subset_t *font_subset)
_cairo_ft_index_to_ucs4(void *abstract_font,
unsigned long index,
uint32_t *ucs4)
{
cairo_ft_scaled_font_t *scaled_font = abstract_font;
cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
FT_Face face;
FT_UInt glyph;
unsigned long charcode;
unsigned int i;
int count;
FT_ULong charcode;
FT_UInt gindex;
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
count = font_subset->num_glyphs;
charcode = FT_Get_First_Char( face, &glyph);
while (glyph != 0 && count > 0)
{
for (i = 0; i < font_subset->num_glyphs; i++) {
if (font_subset->glyphs[i] == glyph) {
font_subset->to_unicode[i] = charcode;
count--;
break;
}
}
charcode = FT_Get_Next_Char (face, charcode, &glyph);
*ucs4 = (uint32_t) -1;
charcode = FT_Get_First_Char(face, &gindex);
while (gindex != 0) {
charcode = FT_Get_Next_Char (face, charcode, &gindex);
if (gindex == index) {
*ucs4 = charcode;
break;
}
}
_cairo_ft_unscaled_font_unlock_face (unscaled);
return CAIRO_STATUS_SUCCESS;
}
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
CAIRO_FONT_TYPE_FT,
_cairo_ft_scaled_font_create_toy,
_cairo_ft_scaled_font_fini,
@ -2211,7 +2220,7 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
_cairo_ft_ucs4_to_index,
NULL, /* show_glyphs */
_cairo_ft_load_truetype_table,
_cairo_ft_map_glyphs_to_unicode,
_cairo_ft_index_to_ucs4
};
/* #cairo_ft_font_face_t */
@ -2292,6 +2301,10 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
* derived from a pattern where the user has called
* cairo_ft_font_options_substitute(), so *just* use those load
* flags and ignore the options.
*
* XXX two points about the above comment:
* 1. I don't see how the comment is relevant here,
* 2. What if the face is coming from FC_FT_FACE of a pattern?
*/
ft_options = font_face->ft_options;
@ -2487,7 +2500,7 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
* cairo_set_font_face() or cairo_scaled_font_create(). The
* #cairo_scaled_font_t returned from cairo_scaled_font_create() is
* also for the FreeType backend and can be used with functions such
* as cairo_ft_font_lock_face().
* as cairo_ft_scaled_font_lock_face().
*
* Font rendering options are represented both here and when you
* call cairo_scaled_font_create(). Font options that have a representation
@ -2495,6 +2508,17 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
* appropriately to reflect the options in a #cairo_font_options_t, call
* cairo_ft_font_options_substitute().
*
* The pattern's FC_FT_FACE element is inspected first and if that is set,
* that will be the FreeType font face associated with the returned cairo
* font face. Otherwise the FC_FILE and FC_INDEX elements of @pattern are
* used to load a font face from file.
*
* If the FC_FT_FACE element of @pattern is set, the user is responsible
* for making sure that the referenced FT_Face remains valid for the life
* time of the returned #cairo_font_face_t. See
* cairo_ft_font_face_create_for_ft_face() for an exmaple of how to couple
* the life time of the FT_Face to that of the cairo font-face.
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
**/
@ -2539,7 +2563,23 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
* cairo_set_font_face() or cairo_scaled_font_create(). The
* #cairo_scaled_font_t returned from cairo_scaled_font_create() is
* also for the FreeType backend and can be used with functions such
* as cairo_ft_font_lock_face().
* as cairo_ft_scaled_font_lock_face().
*
* As an example, here is how one might correctly couple the lifetime of
* the FreeType face object to the #cairo_font_face_t:
*
* <informalexample><programlisting>
* static const cairo_user_data_key_t key;
*
* font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
* status = cairo_font_face_set_user_data (font_face, &key,
* ft_face, (cairo_destroy_func_t) FT_Done_Face);
* if (status) {
* cairo_font_face_destroy (font_face);
* FT_Done_Face (ft_face);
* return ERROR;
* }
* </programlisting></informalexample>
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
@ -2573,16 +2613,16 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
* @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
* object can be created by calling cairo_scaled_font_create() on a
* FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
* cairo_ft_font_face_create_for_face()).
* cairo_ft_font_face_create_for_ft_face()).
*
* cairo_ft_font_lock_face() gets the #FT_Face object from a FreeType
* cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
* backend font and scales it appropriately for the font. You must
* release the face with cairo_ft_font_unlock_face()
* release the face with cairo_ft_scaled_font_unlock_face()
* when you are done using it. Since the #FT_Face object can be
* shared between multiple #cairo_scaled_font_t objects, you must not
* lock any other font objects until you unlock this one. A count is
* kept of the number of times cairo_ft_font_lock_face() is
* called. cairo_ft_font_unlock_face() must be called the same number
* kept of the number of times cairo_ft_scaled_font_lock_face() is
* called. cairo_ft_scaled_font_unlock_face() must be called the same number
* of times.
*
* You must be careful when using this function in a library or in a
@ -2605,6 +2645,11 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
FT_Face face;
cairo_status_t status;
if (! _cairo_scaled_font_is_ft (abstract_font)) {
_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
return NULL;
}
if (scaled_font->base.status)
return NULL;
@ -2647,6 +2692,11 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
{
cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
if (! _cairo_scaled_font_is_ft (abstract_font)) {
_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
return;
}
if (scaled_font->base.status)
return;

View File

@ -37,8 +37,8 @@
#ifndef CAIRO_FT_PRIVATE_H
#define CAIRO_FT_PRIVATE_H
#include <cairo-ft.h>
#include <cairoint.h>
#include "cairo-ft.h"
#include "cairoint.h"
#if CAIRO_HAS_FT_FONT
@ -46,9 +46,6 @@ CAIRO_BEGIN_DECLS
typedef struct _cairo_ft_unscaled_font cairo_ft_unscaled_font_t;
cairo_private cairo_bool_t
_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font);
cairo_private cairo_bool_t
_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font);
@ -67,9 +64,6 @@ _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);
cairo_private cairo_bool_t
_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font);
slim_hidden_proto (cairo_ft_scaled_font_lock_face);
slim_hidden_proto (cairo_ft_scaled_font_unlock_face);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_FT_FONT */

View File

@ -37,7 +37,7 @@
#ifndef CAIRO_FT_H
#define CAIRO_FT_H
#include <cairo.h>
#include "cairo.h"
#if CAIRO_HAS_FT_FONT

View File

@ -958,7 +958,7 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
cairo_glitz_surface_attributes_t *mattr)
{
cairo_int_status_t status;
cairo_pattern_union_t tmp;
cairo_solid_pattern_t tmp;
/* If src and mask are both solid, then the mask alpha can be
* combined into src and mask can be ignored. */
@ -977,10 +977,7 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
combined = src_solid->color;
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
_cairo_pattern_init_solid (&tmp.solid, &combined,
CAIRO_COLOR_IS_OPAQUE (&combined) ?
CAIRO_CONTENT_COLOR :
CAIRO_CONTENT_COLOR_ALPHA);
_cairo_pattern_init_solid (&tmp, &combined, CAIRO_CONTENT_COLOR_ALPHA);
mask = NULL;
} else {
@ -1164,8 +1161,7 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
_cairo_surface_create_similar_solid (&dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
1, 1,
(cairo_color_t *) color,
NULL);
(cairo_color_t *) color);
if (src->base.status)
return src->base.status;

View File

@ -37,7 +37,7 @@
#ifndef CAIRO_GLITZ_H
#define CAIRO_GLITZ_H
#include <cairo.h>
#include "cairo.h"
#if CAIRO_HAS_GLITZ_SURFACE

View File

@ -64,7 +64,8 @@ static void
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_glyph_t *transformed_glyphs);
cairo_glyph_t *transformed_glyphs,
int *num_transformed_glyphs);
cairo_status_t
_cairo_gstate_init (cairo_gstate_t *gstate,
@ -203,47 +204,6 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
gstate->source = NULL;
}
static void
_cairo_gstate_destroy (cairo_gstate_t *gstate)
{
_cairo_gstate_fini (gstate);
free (gstate);
}
/**
* _cairo_gstate_clone:
* @other: a #cairo_gstate_t to be copied, not %NULL.
*
* Create a new #cairo_gstate_t setting all graphics state parameters
* to the same values as contained in @other. gstate->next will be set
* to %NULL and may be used by the caller to chain #cairo_gstate_t
* objects together.
*
* Return value: a new #cairo_gstate_t or %NULL if there is insufficient
* memory.
**/
static cairo_status_t
_cairo_gstate_clone (cairo_gstate_t *other, cairo_gstate_t **out)
{
cairo_status_t status;
cairo_gstate_t *gstate;
assert (other != NULL);
gstate = malloc (sizeof (cairo_gstate_t));
if (gstate == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_gstate_init_copy (gstate, other);
if (status) {
free (gstate);
return status;
}
*out = gstate;
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_gstate_save:
* @gstate: input/output gstate pointer
@ -253,14 +213,25 @@ _cairo_gstate_clone (cairo_gstate_t *other, cairo_gstate_t **out)
* copy into @gstate. _cairo_gstate_restore() reverses this.
**/
cairo_status_t
_cairo_gstate_save (cairo_gstate_t **gstate)
_cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
{
cairo_gstate_t *top = NULL;
cairo_gstate_t *top;
cairo_status_t status;
status = _cairo_gstate_clone (*gstate, &top);
if (status)
top = *freelist;
if (top == NULL) {
top = malloc (sizeof (cairo_gstate_t));
if (top == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
} else
*freelist = top->next;
status = _cairo_gstate_init_copy (top, *gstate);
if (status) {
top->next = *freelist;
*freelist = top;
return status;
}
top->next = *gstate;
*gstate = top;
@ -275,7 +246,7 @@ _cairo_gstate_save (cairo_gstate_t **gstate)
* Reverses the effects of one _cairo_gstate_save() call.
**/
cairo_status_t
_cairo_gstate_restore (cairo_gstate_t **gstate)
_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
{
cairo_gstate_t *top;
@ -285,7 +256,9 @@ _cairo_gstate_restore (cairo_gstate_t **gstate)
*gstate = top->next;
_cairo_gstate_destroy (top);
_cairo_gstate_fini (top);
top->next = *freelist;
*freelist = top;
return CAIRO_STATUS_SUCCESS;
}
@ -822,8 +795,7 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
if (status)
return status;
_cairo_pattern_transform (pattern, ctm_inverse);
/* apply device_transform first so that it is transformed by ctm_inverse */
if (cairo_pattern_get_type (original) == CAIRO_PATTERN_TYPE_SURFACE) {
surface_pattern = (cairo_surface_pattern_t *) original;
surface = surface_pattern->surface;
@ -831,6 +803,8 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
_cairo_pattern_transform (pattern, &surface->device_transform);
}
_cairo_pattern_transform (pattern, ctm_inverse);
return CAIRO_STATUS_SUCCESS;
}
@ -1174,6 +1148,21 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
gstate->antialias, gstate->target);
}
static cairo_status_t
_cairo_gstate_int_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_int_t *extents)
{
cairo_status_t status;
status = _cairo_surface_get_extents (gstate->target, extents);
if (status)
return status;
status = _cairo_clip_intersect_to_rectangle (&gstate->clip, extents);
return status;
}
cairo_status_t
_cairo_gstate_clip_extents (cairo_gstate_t *gstate,
double *x1,
@ -1184,11 +1173,7 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_int_t extents;
cairo_status_t status;
status = _cairo_surface_get_extents (gstate->target, &extents);
if (status)
return status;
status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents);
status = _cairo_gstate_int_clip_extents (gstate, &extents);
if (status)
return status;
@ -1513,10 +1498,21 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
return cairo_scaled_font_status (gstate->scaled_font);
}
cairo_bool_t
_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate)
{
return _cairo_surface_has_show_text_glyphs (gstate->target);
}
cairo_status_t
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
const char *utf8,
int utf8_len,
const cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward)
{
cairo_status_t status;
cairo_pattern_union_t source_pattern;
@ -1543,18 +1539,57 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
}
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs);
transformed_glyphs, &num_glyphs);
if (!num_glyphs)
goto CLEANUP_GLYPHS;
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
if (status)
goto CLEANUP_GLYPHS;
status = _cairo_surface_show_glyphs (gstate->target,
gstate->op,
&source_pattern.base,
transformed_glyphs,
num_glyphs,
gstate->scaled_font);
/* For really huge font sizes, we can just do path;fill instead of
* show_glyphs, as show_glyphs would put excess pressure on the cache,
* and moreover, not all components below us correctly handle huge font
* sizes. I wanted to set the limit at 256. But alas, seems like cairo's
* rasterizer is something like ten times slower than freetype's for huge
* sizes. So, no win just yet. For now, do it for insanely-huge sizes,
* just to make sure we don't make anyone unhappy. When we get a really
* fast rasterizer in cairo, we may want to readjust this.
*
* Needless to say, do this only if show_text_glyphs is not available. */
if (_cairo_gstate_has_show_text_glyphs (gstate) ||
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
status = _cairo_surface_show_text_glyphs (gstate->target,
gstate->op,
&source_pattern.base,
utf8, utf8_len,
transformed_glyphs, num_glyphs,
clusters, num_clusters,
backward,
gstate->scaled_font);
} else {
cairo_path_fixed_t path;
_cairo_path_fixed_init (&path);
CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
transformed_glyphs, num_glyphs,
&path);
CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_surface_fill (gstate->target,
gstate->op,
&source_pattern.base,
&path,
CAIRO_FILL_RULE_WINDING,
gstate->tolerance,
gstate->scaled_font->options.antialias);
_cairo_path_fixed_fini (&path);
}
_cairo_pattern_fini (&source_pattern.base);
@ -1587,7 +1622,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs);
transformed_glyphs, NULL);
CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
@ -1623,39 +1658,99 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
* @num_glyphs: the number of elements in @glyphs
* @transformed_glyphs: a pre-allocated array of at least @num_glyphs
* #cairo_glyph_t objects
* @num_transformed_glyphs: the number of elements in @transformed_glyphs
* after dropping out of bounds glyphs, or %NULL if glyphs shouldn't be
* dropped
*
* Transform an array of glyphs to backend space by first adding the offset
* of the font matrix, then transforming from user space to backend space.
* The result of the transformation is placed in @transformed_glyphs.
*
* This also uses information from the scaled font and the surface to
* cull/drop glyphs that will not be visible.
**/
static void
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_glyph_t *transformed_glyphs)
cairo_glyph_t *transformed_glyphs,
int *num_transformed_glyphs)
{
int i;
int i, j;
cairo_matrix_t *ctm = &gstate->ctm;
cairo_matrix_t *font_matrix = &gstate->font_matrix;
cairo_matrix_t *device_transform = &gstate->target->device_transform;
cairo_bool_t drop = FALSE;
double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
if (num_transformed_glyphs != NULL) {
cairo_rectangle_int_t surface_extents;
double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font);
drop = TRUE;
if (_cairo_gstate_int_clip_extents (gstate, &surface_extents))
drop = FALSE; /* unbounded surface */
else {
if (surface_extents.width == 0 || surface_extents.height == 0) {
/* No visible area. Don't draw anything */
*num_transformed_glyphs = 0;
return;
}
/* XXX We currently drop any glyphs that has its position outside
* of the surface boundaries by a safety margin depending on the
* font scale. This however can fail in extreme cases where the
* font has really long swashes for example... We can correctly
* handle that by looking the glyph up and using its device bbox
* to device if it's going to be visible, but I'm not inclined to
* do that now.
*/
x1 = surface_extents.x - 2*scale;
y1 = surface_extents.y - 2*scale;
x2 = surface_extents.x + surface_extents.width + scale;
y2 = surface_extents.y + surface_extents.height + scale;
}
if (!drop)
*num_transformed_glyphs = num_glyphs;
} else
num_transformed_glyphs = &j;
#define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
if (_cairo_matrix_is_identity (ctm) &&
_cairo_matrix_is_identity (device_transform) &&
gstate->font_matrix.x0 == 0 && gstate->font_matrix.y0 == 0)
font_matrix->x0 == 0 && font_matrix->y0 == 0)
{
memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
if (!drop)
memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
else {
for (j = 0, i = 0; i < num_glyphs; i++)
{
transformed_glyphs[j].index = glyphs[i].index;
transformed_glyphs[j].x = glyphs[i].x;
transformed_glyphs[j].y = glyphs[i].y;
if (KEEP_GLYPH (transformed_glyphs[j]))
j++;
}
*num_transformed_glyphs = j;
}
}
else if (_cairo_matrix_is_translation (ctm) &&
_cairo_matrix_is_translation (device_transform))
{
double tx = gstate->font_matrix.x0 + ctm->x0 + device_transform->x0;
double ty = gstate->font_matrix.y0 + ctm->y0 + device_transform->y0;
double tx = font_matrix->x0 + ctm->x0 + device_transform->x0;
double ty = font_matrix->y0 + ctm->y0 + device_transform->y0;
for (i = 0; i < num_glyphs; i++)
for (j = 0, i = 0; i < num_glyphs; i++)
{
transformed_glyphs[i].index = glyphs[i].index;
transformed_glyphs[i].x = glyphs[i].x + tx;
transformed_glyphs[i].y = glyphs[i].y + ty;
transformed_glyphs[j].index = glyphs[i].index;
transformed_glyphs[j].x = glyphs[i].x + tx;
transformed_glyphs[j].y = glyphs[i].y + ty;
if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
j++;
}
*num_transformed_glyphs = j;
}
else
{
@ -1669,12 +1764,15 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
cairo_matrix_multiply (&aggregate_transform,
&aggregate_transform, device_transform);
for (i = 0; i < num_glyphs; i++)
for (j = 0, i = 0; i < num_glyphs; i++)
{
transformed_glyphs[i] = glyphs[i];
transformed_glyphs[j] = glyphs[i];
cairo_matrix_transform_point (&aggregate_transform,
&transformed_glyphs[i].x,
&transformed_glyphs[i].y);
&transformed_glyphs[j].x,
&transformed_glyphs[j].y);
if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
j++;
}
*num_transformed_glyphs = j;
}
}

View File

@ -296,7 +296,7 @@ _cairo_hash_table_lookup_internal (cairo_hash_table_t *hash_table,
* size.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if out of memory.
* %CAIRO_STATUS_NO_MEMORY if out of memory.
**/
static cairo_status_t
_cairo_hash_table_resize (cairo_hash_table_t *hash_table)
@ -401,7 +401,7 @@ _cairo_hash_table_lookup (cairo_hash_table_t *hash_table,
*
* Return value: a random live entry or %NULL if there are no entries
* that match the given predicate. In particular, if predicate is
* NULL, a %NULL return value indicates that the table is empty.
* %NULL, a %NULL return value indicates that the table is empty.
**/
void *
_cairo_hash_table_random_entry (cairo_hash_table_t *hash_table,
@ -459,7 +459,7 @@ _cairo_hash_table_random_entry (cairo_hash_table_t *hash_table,
* necessary, use _cairo_hash_table_remove first.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
**/
cairo_status_t
_cairo_hash_table_insert (cairo_hash_table_t *hash_table,
@ -504,7 +504,7 @@ _cairo_hash_table_insert (cairo_hash_table_t *hash_table,
* _cairo_hash_table_create).
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if out of memory.
* %CAIRO_STATUS_NO_MEMORY if out of memory.
**/
void
_cairo_hash_table_remove (cairo_hash_table_t *hash_table,

View File

@ -36,22 +36,20 @@
#include "cairoint.h"
typedef struct cairo_hull
{
typedef struct cairo_hull {
cairo_point_t point;
cairo_slope_t slope;
int discard;
int id;
} cairo_hull_t;
static cairo_status_t
_cairo_hull_create (cairo_pen_vertex_t *vertices,
int num_vertices,
cairo_hull_t **out)
static void
_cairo_hull_init (cairo_hull_t *hull,
cairo_pen_vertex_t *vertices,
int num_vertices)
{
int i;
cairo_hull_t *hull;
cairo_point_t *p, *extremum, tmp;
int i;
extremum = &vertices[0].point;
for (i = 1; i < num_vertices; i++) {
@ -64,10 +62,6 @@ _cairo_hull_create (cairo_pen_vertex_t *vertices,
*extremum = vertices[0].point;
vertices[0].point = tmp;
hull = _cairo_malloc_ab (num_vertices, sizeof (cairo_hull_t));
if (hull == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
for (i = 0; i < num_vertices; i++) {
hull[i].point = vertices[i].point;
_cairo_slope_init (&hull[i].slope, &hull[0].point, &hull[i].point);
@ -82,9 +76,6 @@ _cairo_hull_create (cairo_pen_vertex_t *vertices,
if (i != 0 && hull[i].slope.dx == 0 && hull[i].slope.dy == 0)
hull[i].discard = 1;
}
*out = hull;
return CAIRO_STATUS_SUCCESS;
}
static int
@ -196,13 +187,19 @@ _cairo_hull_to_pen (cairo_hull_t *hull, cairo_pen_vertex_t *vertices, int *num_v
cairo_status_t
_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices)
{
cairo_status_t status;
cairo_hull_t *hull = NULL;
cairo_hull_t hull_stack[CAIRO_STACK_ARRAY_LENGTH (cairo_hull_t)];
cairo_hull_t *hull;
int num_hull = *num_vertices;
status = _cairo_hull_create (vertices, num_hull, &hull);
if (status)
return status;
if (num_hull > ARRAY_LENGTH (hull_stack)) {
hull = _cairo_malloc_ab (num_hull, sizeof (cairo_hull_t));
if (hull == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
} else {
hull = hull_stack;
}
_cairo_hull_init (hull, vertices, num_hull);
qsort (hull + 1, num_hull - 1,
sizeof (cairo_hull_t), _cairo_hull_vertex_compare);
@ -211,7 +208,8 @@ _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices)
_cairo_hull_to_pen (hull, vertices, num_vertices);
free (hull);
if (hull != hull_stack)
free (hull);
return CAIRO_STATUS_SUCCESS;
}

View File

@ -124,7 +124,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
if (surface == NULL)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&surface->base, &cairo_image_surface_backend,
_cairo_surface_init (&surface->base, &_cairo_image_surface_backend,
_cairo_content_from_pixman_format (pixman_format));
surface->pixman_image = pixman_image;
@ -392,7 +392,8 @@ _cairo_image_surface_create_with_content (cairo_content_t content,
* stride = cairo_format_stride_for_width (format, width);
* data = malloc (stride * height);
* surface = cairo_image_surface_create_for_data (data, format,
* width, height);
* width, height,
* stride);
* </programlisting></informalexample>
*
* Return value: the appropriate stride to use given the desired
@ -1192,7 +1193,7 @@ _cairo_image_surface_set_clip_region (void *abstract_surface,
{
cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
if (! pixman_image_set_clip_region (surface->pixman_image, &region->rgn))
if (! pixman_image_set_clip_region32 (surface->pixman_image, &region->rgn))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
surface->has_clip = region != NULL;
@ -1246,10 +1247,10 @@ _cairo_image_surface_reset (void *abstract_surface)
cairo_bool_t
_cairo_surface_is_image (const cairo_surface_t *surface)
{
return surface->backend == &cairo_image_surface_backend;
return surface->backend == &_cairo_image_surface_backend;
}
const cairo_surface_backend_t cairo_image_surface_backend = {
const cairo_surface_backend_t _cairo_image_surface_backend = {
CAIRO_SURFACE_TYPE_IMAGE,
_cairo_image_surface_create_similar,
_cairo_image_surface_finish,

View File

@ -82,7 +82,7 @@ _lzw_buf_init (lzw_buf_t *buf, int size)
/* Increase the buffer size by doubling.
*
* Returns %CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY
* Returns %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
*/
static cairo_status_t
_lzw_buf_grow (lzw_buf_t *buf)

View File

@ -423,6 +423,18 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
}
}
cairo_private void
_cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix,
cairo_box_t *bbox,
cairo_bool_t *is_tight)
{
double x1, y1, x2, y2;
_cairo_box_to_doubles (bbox, &x1, &y1, &x2, &y2);
_cairo_matrix_transform_bounding_box (matrix, &x1, &y1, &x2, &y2, is_tight);
_cairo_box_from_doubles (bbox, &x1, &y1, &x2, &y2);
}
static void
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar)
{
@ -478,10 +490,10 @@ cairo_matrix_invert (cairo_matrix_t *matrix)
_cairo_matrix_compute_determinant (matrix, &det);
if (det == 0)
if (! ISFINITE (det))
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
if (! ISFINITE (det))
if (det == 0)
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
_cairo_matrix_compute_adjoint (matrix);
@ -498,7 +510,7 @@ _cairo_matrix_is_invertible (const cairo_matrix_t *matrix)
_cairo_matrix_compute_determinant (matrix, &det);
return det != 0. && ISFINITE (det);
return ISFINITE (det) && det != 0.;
}
void
@ -713,6 +725,10 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
(Note that the minor axis length is at the minimum of the above solution,
which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)).
For another derivation of the same result, using Singular Value Decomposition,
see doc/tutorial/src/singular.c.
*/
/* determine the length of the major axis of a circle of the given radius

View File

@ -46,7 +46,7 @@ typedef enum {
CAIRO_COMMAND_MASK,
CAIRO_COMMAND_STROKE,
CAIRO_COMMAND_FILL,
CAIRO_COMMAND_SHOW_GLYPHS,
CAIRO_COMMAND_SHOW_TEXT_GLYPHS,
/* Other junk. For most of these, we should be able to assert that
* they never get called except as part of fallbacks for the 5
@ -104,14 +104,19 @@ typedef struct _cairo_command_fill {
cairo_antialias_t antialias;
} cairo_command_fill_t;
typedef struct _cairo_command_show_glyphs {
typedef struct _cairo_command_show_text_glyphs {
cairo_command_header_t header;
cairo_operator_t op;
cairo_pattern_union_t source;
char *utf8;
int utf8_len;
cairo_glyph_t *glyphs;
unsigned int num_glyphs;
cairo_text_cluster_t *clusters;
int num_clusters;
cairo_bool_t backward;
cairo_scaled_font_t *scaled_font;
} cairo_command_show_glyphs_t;
} cairo_command_show_text_glyphs_t;
typedef struct _cairo_command_intersect_clip_path {
cairo_command_header_t header;
@ -130,7 +135,7 @@ typedef union _cairo_command {
cairo_command_mask_t mask;
cairo_command_stroke_t stroke;
cairo_command_fill_t fill;
cairo_command_show_glyphs_t show_glyphs;
cairo_command_show_text_glyphs_t show_text_glyphs;
/* The other junk. */
cairo_command_intersect_clip_path_t intersect_clip_path;
@ -159,6 +164,10 @@ _cairo_meta_surface_create (cairo_content_t content,
int width_pixels,
int height_pixels);
cairo_private cairo_int_status_t
_cairo_meta_surface_get_path (cairo_surface_t *surface,
cairo_path_fixed_t *path);
cairo_private cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target);

View File

@ -39,7 +39,7 @@
/* A meta surface is a surface that records all drawing operations at
* the highest level of the surface backend interface, (that is, the
* level of paint, mask, stroke, fill, and show_glyphs). The meta
* level of paint, mask, stroke, fill, and show_text_glyphs). The meta
* surface can then be "replayed" against any target surface with:
*
* _cairo_meta_surface_replay (meta, target);
@ -157,10 +157,12 @@ _cairo_meta_surface_finish (void *abstract_surface)
free (command);
break;
case CAIRO_COMMAND_SHOW_GLYPHS:
_cairo_pattern_fini (&command->show_glyphs.source.base);
free (command->show_glyphs.glyphs);
cairo_scaled_font_destroy (command->show_glyphs.scaled_font);
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
_cairo_pattern_fini (&command->show_text_glyphs.source.base);
free (command->show_text_glyphs.utf8);
free (command->show_text_glyphs.glyphs);
free (command->show_text_glyphs.clusters);
cairo_scaled_font_destroy (command->show_text_glyphs.scaled_font);
free (command);
break;
@ -426,23 +428,34 @@ _cairo_meta_surface_fill (void *abstract_surface,
return status;
}
static cairo_bool_t
_cairo_meta_surface_has_show_text_glyphs (void *abstract_surface)
{
return TRUE;
}
static cairo_int_status_t
_cairo_meta_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
_cairo_meta_surface_show_text_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_show_glyphs_t *command;
cairo_command_show_text_glyphs_t *command;
command = malloc (sizeof (cairo_command_show_glyphs_t));
command = malloc (sizeof (cairo_command_show_text_glyphs_t));
if (command == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
command->header.type = CAIRO_COMMAND_SHOW_GLYPHS;
command->header.type = CAIRO_COMMAND_SHOW_TEXT_GLYPHS;
command->header.region = CAIRO_META_REGION_ALL;
command->op = op;
@ -450,14 +463,39 @@ _cairo_meta_surface_show_glyphs (void *abstract_surface,
if (status)
goto CLEANUP_COMMAND;
command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (command->glyphs == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_SOURCE;
}
memcpy (command->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
command->utf8 = NULL;
command->utf8_len = utf8_len;
command->glyphs = NULL;
command->num_glyphs = num_glyphs;
command->clusters = NULL;
command->num_clusters = num_clusters;
if (utf8_len) {
command->utf8 = malloc (utf8_len);
if (command->utf8 == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_ARRAYS;
}
memcpy (command->utf8, utf8, utf8_len);
}
if (num_glyphs) {
command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (glyphs[0]));
if (command->glyphs == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_ARRAYS;
}
memcpy (command->glyphs, glyphs, sizeof (glyphs[0]) * num_glyphs);
}
if (num_clusters) {
command->clusters = _cairo_malloc_ab (num_clusters, sizeof (clusters[0]));
if (command->clusters == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_ARRAYS;
}
memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters);
}
command->backward = backward;
command->scaled_font = cairo_scaled_font_reference (scaled_font);
@ -469,8 +507,11 @@ _cairo_meta_surface_show_glyphs (void *abstract_surface,
CLEANUP_SCALED_FONT:
cairo_scaled_font_destroy (command->scaled_font);
CLEANUP_ARRAYS:
free (command->utf8);
free (command->glyphs);
CLEANUP_SOURCE:
free (command->clusters);
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
@ -485,7 +526,7 @@ _cairo_meta_surface_show_glyphs (void *abstract_surface,
* surface-modifying function on the result of this function.
*
* The caller owns the return value and should call
* cairo_surface_destroy when finished with it. This function will not
* cairo_surface_destroy() when finished with it. This function will not
* return %NULL, but will return a nil surface instead.
*
* Return value: The snapshot surface.
@ -570,6 +611,9 @@ _cairo_meta_surface_get_extents (void *abstract_surface,
{
cairo_meta_surface_t *surface = abstract_surface;
if (surface->width_pixels == -1 && surface->height_pixels == -1)
return CAIRO_INT_STATUS_UNSUPPORTED;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width_pixels;
@ -618,15 +662,24 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = {
/* Here are the 5 basic drawing operations, (which are in some
* sense the only things that cairo_meta_surface should need to
* implement). */
* implement). However, we implement the more generic show_text_glyphs
* instead of show_glyphs. One or the other is eough. */
_cairo_meta_surface_paint,
_cairo_meta_surface_mask,
_cairo_meta_surface_stroke,
_cairo_meta_surface_fill,
_cairo_meta_surface_show_glyphs,
NULL,
_cairo_meta_surface_snapshot
_cairo_meta_surface_snapshot,
NULL, /* is_similar */
NULL, /* reset */
NULL, /* fill_stroke */
NULL, /* create_solid_pattern_surface */
_cairo_meta_surface_has_show_text_glyphs,
_cairo_meta_surface_show_text_glyphs
};
static cairo_path_fixed_t *
@ -635,7 +688,7 @@ _cairo_command_get_path (cairo_command_t *command)
switch (command->header.type) {
case CAIRO_COMMAND_PAINT:
case CAIRO_COMMAND_MASK:
case CAIRO_COMMAND_SHOW_GLYPHS:
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
return NULL;
case CAIRO_COMMAND_STROKE:
return &command->stroke.path;
@ -649,6 +702,78 @@ _cairo_command_get_path (cairo_command_t *command)
return NULL;
}
cairo_int_status_t
_cairo_meta_surface_get_path (cairo_surface_t *surface,
cairo_path_fixed_t *path)
{
cairo_meta_surface_t *meta;
cairo_command_t *command, **elements;
int i, num_elements;
cairo_int_status_t status;
if (surface->status)
return surface->status;
meta = (cairo_meta_surface_t *) surface;
status = CAIRO_STATUS_SUCCESS;
num_elements = meta->commands.num_elements;
elements = _cairo_array_index (&meta->commands, 0);
for (i = meta->replay_start_idx; i < num_elements; i++) {
command = elements[i];
switch (command->header.type) {
case CAIRO_COMMAND_PAINT:
case CAIRO_COMMAND_MASK:
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
status = CAIRO_INT_STATUS_UNSUPPORTED;
break;
case CAIRO_COMMAND_STROKE:
{
cairo_traps_t traps;
_cairo_traps_init (&traps);
/* XXX call cairo_stroke_to_path() when that is implemented */
status = _cairo_path_fixed_stroke_to_traps (&command->stroke.path,
&command->stroke.style,
&command->stroke.ctm,
&command->stroke.ctm_inverse,
command->stroke.tolerance,
&traps);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_traps_path (&traps, path);
_cairo_traps_fini (&traps);
break;
}
case CAIRO_COMMAND_FILL:
{
status = _cairo_path_fixed_append (path, &command->fill.path, CAIRO_DIRECTION_FORWARD);
break;
}
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
{
status = _cairo_scaled_font_glyph_path (command->show_text_glyphs.scaled_font,
command->show_text_glyphs.glyphs,
command->show_text_glyphs.num_glyphs,
path);
break;
}
default:
ASSERT_NOT_REACHED;
}
if (status)
break;
}
return _cairo_surface_set_error (surface, status);
}
static cairo_status_t
_cairo_meta_surface_replay_internal (cairo_surface_t *surface,
cairo_surface_t *target,
@ -699,7 +824,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
if (status)
break;
_cairo_path_fixed_device_transform (&path_copy, device_transform);
_cairo_path_fixed_transform (&path_copy, device_transform);
dev_path = &path_copy;
}
@ -798,13 +923,13 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
command->fill.antialias);
break;
}
case CAIRO_COMMAND_SHOW_GLYPHS:
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
{
cairo_glyph_t *glyphs = command->show_glyphs.glyphs;
cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs;
cairo_glyph_t *dev_glyphs;
int i, num_glyphs = command->show_glyphs.num_glyphs;
int i, num_glyphs = command->show_text_glyphs.num_glyphs;
/* show_glyphs is special because _cairo_surface_show_glyphs is allowed
/* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed
* to modify the glyph array that's passed in. We must always
* copy the array before handing it to the backend.
*/
@ -825,11 +950,14 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
}
status = _cairo_surface_show_glyphs (target,
command->show_glyphs.op,
&command->show_glyphs.source.base,
dev_glyphs, num_glyphs,
command->show_glyphs.scaled_font);
status = _cairo_surface_show_text_glyphs (target,
command->show_text_glyphs.op,
&command->show_text_glyphs.source.base,
command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
dev_glyphs, num_glyphs,
command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
command->show_text_glyphs.backward,
command->show_text_glyphs.scaled_font);
free (dev_glyphs);
break;
@ -887,7 +1015,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
/* Replay meta to surface. When the return status of each operation is
* one of %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED, or
* CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation
* %CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation
* will be stored in the meta surface. Any other status will abort the
* replay and return the status.
*/

View File

@ -38,6 +38,8 @@
#include "cairoint.h"
COMPILE_TIME_ASSERT (CAIRO_STATUS_LAST_STATUS < CAIRO_INT_STATUS_UNSUPPORTED);
COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127);
/**
* cairo_status_to_string:
@ -101,6 +103,16 @@ cairo_status_to_string (cairo_status_t status)
return "error creating or writing to a temporary file";
case CAIRO_STATUS_INVALID_STRIDE:
return "invalid value for stride";
case CAIRO_STATUS_FONT_TYPE_MISMATCH:
return "the font type is not appropriate for the operation";
case CAIRO_STATUS_USER_FONT_IMMUTABLE:
return "the user-font is immutable";
case CAIRO_STATUS_USER_FONT_ERROR:
return "error occurred in a user-font callback function";
case CAIRO_STATUS_NEGATIVE_COUNT:
return "negative number used where it is not allowed";
case CAIRO_STATUS_INVALID_CLUSTERS:
return "input clusters do not represent the accompanying text and glyph arrays";
}
return "<unknown error status>";

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