mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge commit for bug 399397
This commit is contained in:
commit
5e4e630789
2
.hgtags
2
.hgtags
@ -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
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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 $@
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1 +1 @@
|
||||
MOZ_APP_DISPLAYNAME="GranParadiso"
|
||||
MOZ_APP_DISPLAYNAME="Shiretoko"
|
||||
|
@ -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"
|
||||
|
@ -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/
|
||||
|
||||
|
@ -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/">
|
||||
|
@ -1,3 +1,3 @@
|
||||
brandShortName=Gran Paradiso
|
||||
brandFullName=Gran Paradiso
|
||||
brandShortName=Shiretoko
|
||||
brandFullName=Shiretoko
|
||||
vendorShortName=mozilla.org
|
||||
|
@ -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)
|
||||
|
@ -1 +1 @@
|
||||
3.1a1pre
|
||||
3.1a2pre
|
||||
|
@ -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
|
||||
|
@ -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
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
1.9.1a1pre
|
||||
1.9.1a2pre
|
||||
|
@ -196,6 +196,7 @@ FixMath.h
|
||||
float.h
|
||||
Folders.h
|
||||
fontconfig/fontconfig.h
|
||||
fontconfig/fcfreetype.h
|
||||
Font.h
|
||||
Fonts.h
|
||||
fp.h
|
||||
|
14
configure.in
14
configure.in
@ -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 ========================================================
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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")
|
||||
|
378
content/base/src/nsNodeIterator.cpp
Normal file
378
content/base/src/nsNodeIterator.cpp
Normal 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);
|
||||
}
|
103
content/base/src/nsNodeIterator.h
Normal file
103
content/base/src/nsNodeIterator.h
Normal 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
|
122
content/base/src/nsTraversal.cpp
Normal file
122
content/base/src/nsTraversal.cpp
Normal 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;
|
||||
}
|
78
content/base/src/nsTraversal.h
Normal file
78
content/base/src/nsTraversal.h
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
1413
content/base/test/file_bug416317.xhtml
Normal file
1413
content/base/test/file_bug416317.xhtml
Normal file
File diff suppressed because it is too large
Load Diff
117
content/base/test/test_NodeIterator_basics_filters.xhtml
Normal file
117
content/base/test/test_NodeIterator_basics_filters.xhtml
Normal 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>
|
205
content/base/test/test_NodeIterator_mutations_1.xhtml
Normal file
205
content/base/test/test_NodeIterator_mutations_1.xhtml
Normal 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>
|
113
content/base/test/test_NodeIterator_mutations_2.html
Normal file
113
content/base/test/test_NodeIterator_mutations_2.html
Normal 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>
|
32
content/base/test/test_bug416317-1.html
Normal file
32
content/base/test/test_bug416317-1.html
Normal 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>
|
||||
|
32
content/base/test/test_bug416317-2.html
Normal file
32
content/base/test/test_bug416317-2.html
Normal 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>
|
||||
|
@ -63,7 +63,6 @@ REQUIRES = \
|
||||
xpconnect \
|
||||
caps \
|
||||
imglib2 \
|
||||
cairo \
|
||||
thebes \
|
||||
view \
|
||||
$(NULL)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,7 @@ XPIDLSRCS = \
|
||||
nsIDOMDOMConfiguration.idl \
|
||||
nsIDOMNSEditableElement.idl \
|
||||
nsIDOMNSElement.idl \
|
||||
nsIDOMNodeSelector.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
53
dom/public/idl/core/nsIDOMNodeSelector.idl
Normal file
53
dom/public/idl/core/nsIDOMNodeSelector.idl
Normal 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);
|
||||
};
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -36,7 +36,7 @@
|
||||
#ifndef CAIRO_BEOS_H
|
||||
#define CAIRO_BEOS_H
|
||||
|
||||
#include <cairo.h>
|
||||
#include "cairo.h"
|
||||
|
||||
#if CAIRO_HAS_BEOS_SURFACE
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -47,7 +47,7 @@
|
||||
#ifndef CAIRO_DIRECTFB_H
|
||||
#define CAIRO_DIRECTFB_H
|
||||
|
||||
#include <cairo.h>
|
||||
#include "cairo.h"
|
||||
|
||||
#ifdef CAIRO_HAS_DIRECTFB_SURFACE
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ();
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -37,7 +37,7 @@
|
||||
#ifndef CAIRO_FT_H
|
||||
#define CAIRO_FT_H
|
||||
|
||||
#include <cairo.h>
|
||||
#include "cairo.h"
|
||||
|
||||
#if CAIRO_HAS_FT_FONT
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
#ifndef CAIRO_GLITZ_H
|
||||
#define CAIRO_GLITZ_H
|
||||
|
||||
#include <cairo.h>
|
||||
#include "cairo.h"
|
||||
|
||||
#if CAIRO_HAS_GLITZ_SURFACE
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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, ®ion->rgn))
|
||||
if (! pixman_image_set_clip_region32 (surface->pixman_image, ®ion->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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user