Merging cedar with mozilla-central.

This commit is contained in:
Mounir Lamouri 2011-05-26 08:34:54 +02:00
commit c2223f5860
311 changed files with 26129 additions and 12185 deletions

View File

@ -90,8 +90,8 @@ _TEST_FILES =\
test_aria_roles.xul \
test_aria_token_attrs.html \
test_bug420863.html \
$(warning test_childAtPoint.html temporarily disabled) \
$(warning test_childAtPoint.xul temporarily disabled) \
test_childAtPoint.html \
test_childAtPoint.xul \
test_descr.html \
test_elm_landmarks.html \
test_elm_listbox.xul \

View File

@ -25,19 +25,19 @@
testChildAtPoint(list, 1, 1, true, image.firstChild);
// ::MustPrune case (in this case childAtPoint doesn't look inside a
// button), point is inside of button.
var btn = getAccessible("btn");
testChildAtPoint(btn, 1, 1, false, btn);
testChildAtPoint(btn, 1, 1, true, btn);
// textbox), point is inside of textbox.
var txt = getAccessible("txt");
testChildAtPoint(txt, 1, 1, false, txt);
testChildAtPoint(txt, 1, 1, true, txt);
// ::MustPrune case, point is outside of button accessible but is in
// ::MustPrune case, point is outside of textbox accessible but is in
// document.
testChildAtPoint(btn, -1, 1, false, null);
testChildAtPoint(btn, -1, 1, true, null);
testChildAtPoint(txt, -1, 1, false, null);
testChildAtPoint(txt, -1, 1, true, null);
// ::MustPrune case, point is outside of root accessible.
testChildAtPoint(btn, -10000, 10000, false, null);
testChildAtPoint(btn, -10000, 10000, true, null);
testChildAtPoint(txt, -10000, 10000, false, null);
testChildAtPoint(txt, -10000, 10000, true, null);
// Not specific case, point is inside of label accessible.
var label = getAccessible("label");
@ -82,7 +82,7 @@
<span role="label">label1</span><span role="label" id="label">label2</span>
<span role="button">btn1</span><span role="button" id="btn">btn2</span>
<span role="textbox">textbox1</span><span role="textbox" id="txt">textbox2</span>
<div id="outofflow" style="width: 10px; height: 10px; position: absolute; left: 0px; top: 0px; background-color: yellow;">
</div>

View File

@ -24,8 +24,7 @@
function doTest()
{
// Initialize the tree
var view = new inTreeView();
view.mRowCount = 5;
var view = new nsTableTreeView(5);
var tree = getNode("tree");
var treeBox = tree.treeBoxObject;

View File

@ -70,6 +70,7 @@ pref("extensions.blocklist.interval", 86400);
pref("extensions.blocklist.level", 2);
pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/3/%APP_ID%/%APP_VERSION%/%PRODUCT%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/%PING_COUNT%/%TOTAL_PING_COUNT%/%DAYS_SINCE_LAST_PING%/");
pref("extensions.blocklist.detailsURL", "https://www.mozilla.com/%LOCALE%/blocklist/");
pref("extensions.blocklist.itemURL", "https://addons.mozilla.org/%LOCALE%/%APP%/blocked/%blockID%");
pref("extensions.update.autoUpdateDefault", true);

View File

@ -963,6 +963,10 @@
// if the tab is a blank one.
oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
if (newBrowser._urlbarFocused && gURLBar) {
// Explicitly close the popup if the URL bar retains focus
gURLBar.closePopup();
if (!window.fullScreen) {
gURLBar.focus();
break;

View File

@ -995,7 +995,8 @@ let UI = {
#ifdef XP_MACOSX
"preferencesCmdMac", "minimizeWindow",
#endif
"newNavigator", "newNavigatorTab", "find"
"newNavigator", "newNavigatorTab", "undo", "cut", "copy", "paste",
"selectAll", "find"
].forEach(function(key) {
let element = gWindow.document.getElementById("key_" + key);
keys[key] = element.getAttribute("key").toLocaleLowerCase().charCodeAt(0);
@ -1004,7 +1005,7 @@ let UI = {
// for key combinations with shift key, the charCode of upper case letters
// are different to the lower case ones so need to handle them differently.
["closeWindow", "tabview", "undoCloseTab", "undoCloseWindow",
"privatebrowsing"].forEach(function(key) {
"privatebrowsing", "redo"].forEach(function(key) {
let element = gWindow.document.getElementById("key_" + key);
keys[key] = element.getAttribute("key").toLocaleUpperCase().charCodeAt(0);
});
@ -1043,6 +1044,7 @@ let UI = {
case self._browserKeys.undoCloseTab:
case self._browserKeys.undoCloseWindow:
case self._browserKeys.closeWindow:
case self._browserKeys.redo:
preventDefault = false;
break;
case self._browserKeys.tabview:
@ -1056,6 +1058,11 @@ let UI = {
break;
case self._browserKeys.newNavigator:
case self._browserKeys.newNavigatorTab:
case self._browserKeys.undo:
case self._browserKeys.cut:
case self._browserKeys.copy:
case self._browserKeys.paste:
case self._browserKeys.selectAll:
preventDefault = false;
break;
#ifdef XP_UNIX

View File

@ -171,6 +171,7 @@ _BROWSER_FILES = \
browser_bug623893.js \
browser_bug624734.js \
browser_bug647886.js \
browser_bug655584.js \
browser_findbarClose.js \
browser_contextSearchTabPosition.js \
browser_ctrlTab.js \

View File

@ -0,0 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 655584 - awesomebar suggestions don't update after tab is closed
function test() {
var tab1 = gBrowser.addTab();
var tab2 = gBrowser.addTab();
// When urlbar in a new tab is focused, and a tab switch occurs,
// the urlbar popup should be closed
gBrowser.selectedTab = tab2;
gURLBar.focus(); // focus the urlbar in the tab we will switch to
gBrowser.selectedTab = tab1;
gURLBar.openPopup();
gBrowser.selectedTab = tab2;
ok(!gURLBar.popupOpen, "urlbar focused in tab to switch to, close popup");
// cleanup
gBrowser.removeCurrentTab();
gBrowser.removeCurrentTab();
}

View File

@ -54,6 +54,9 @@ function test() {
testVal("<http://sub.>mozilla.org<:666/file.ext>");
testVal("<http://>[fe80::222:19ff:fe11:8c76]</file.ext>");
testVal("<http://user:pass@>[fe80::222:19ff:fe11:8c76]<:666/file.ext>");
testVal("mailto:admin@mozilla.org");
testVal("gopher://mozilla.org/");
testVal("about:config");

View File

@ -192,7 +192,7 @@
let textNode = this.editor.rootElement.firstChild;
let value = textNode.textContent;
let matchedURL = value.match(/^((?:http|https|ftp):\/\/(?:[^\/]+@)?)([^\/:]+)/);
let matchedURL = value.match(/^((?:http|https|ftp):\/\/(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/);
if (!matchedURL)
return;

View File

@ -265,7 +265,7 @@ let PermissionDefaults = {
return this.DENY;
},
set password(aValue) {
let value = (aValue == this.ALLOW);
let value = (aValue != this.DENY);
Services.prefs.setBoolPref("signon.rememberSignons", value);
},
@ -280,7 +280,7 @@ let PermissionDefaults = {
return this.DENY;
}
if (Services.prefs.getIntPref("network.cookie.lifetimePolicy") == this.COOKIE_DENY) {
if (Services.prefs.getIntPref("network.cookie.lifetimePolicy") == this.COOKIE_SESSION) {
return this.SESSION;
}
return this.ALLOW;
@ -303,7 +303,7 @@ let PermissionDefaults = {
return this.UNKNOWN;
},
set geo(aValue) {
let value = (aValue == this.ALLOW);
let value = (aValue != this.DENY);
Services.prefs.setBoolPref("geo.enabled", value);
},
@ -316,7 +316,7 @@ let PermissionDefaults = {
return this.UNKNOWN;
},
set indexedDB(aValue) {
let value = (aValue == this.ALLOW);
let value = (aValue != this.DENY);
Services.prefs.setBoolPref("dom.indexedDB.enabled", value);
},

View File

@ -123,11 +123,11 @@ libs:: $(topsrcdir)/tools/rb/fix_macosx_stack.py
# Basic unit tests for some stuff in the unify script
check::
# build ppc/i386 binaries, and unify them
rm -f unify-test-ppc unify-test-i386 unify-test-universal
$(HOST_CC) -arch ppc $(srcdir)/unify-test.c -o unify-test-ppc
# build x64/i386 binaries, and unify them
rm -f unify-test-x64 unify-test-i386 unify-test-universal
$(HOST_CC) -arch x86_64 $(srcdir)/unify-test.c -o unify-test-x64
$(HOST_CC) -arch i386 $(srcdir)/unify-test.c -o unify-test-i386
@if ! $(srcdir)/macosx/universal/unify ./unify-test-ppc ./unify-test-i386 \
@if ! $(srcdir)/macosx/universal/unify ./unify-test-x64 ./unify-test-i386 \
./unify-test-universal; then \
echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to produce a universal binary!"; \
false; \

View File

@ -8401,6 +8401,7 @@ if test "$MOZ_TREE_CAIRO"; then
AC_DEFINE(HAVE_UINT64_T)
# Define macros for cairo-features.h
TEE_SURFACE_FEATURE="#define CAIRO_HAS_TEE_SURFACE 1"
if test "$MOZ_X11"; then
XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1"
@ -8483,6 +8484,7 @@ if test "$MOZ_TREE_CAIRO"; then
AC_SUBST(QUARTZ_FONT_FEATURE)
AC_SUBST(PNG_FUNCTIONS_FEATURE)
AC_SUBST(QT_SURFACE_FEATURE)
AC_SUBST(TEE_SURFACE_FEATURE)
MOZ_CAIRO_LIBS='$(call EXPAND_LIBNAME_PATH,mozcairo,$(DEPTH)/gfx/cairo/cairo/src)'" $CAIRO_FT_LIBS"

View File

@ -9,14 +9,12 @@ function testCancel() {
xhr.addEventListener("readystatechange", function(e) {
if (xhr.readyState == 3) // NOTE : only leaks for state == 3
xhr.abort();
else if (xhr.readyState == 4)
document.documentElement.className = "";
}, false);
xhr.open("GET", "552651.xml", true);
xhr.send();
setTimeout(function f() {
document.documentElement.className = "";
}, 1000);
}
</script>
</head>

View File

@ -1488,29 +1488,6 @@ public:
return sScriptBlockerCount == 0;
}
/**
* Get/Set the current number of removable updates. Currently only
* UPDATE_CONTENT_MODEL updates are removable, and only when firing mutation
* events. These functions should only be called by mozAutoDocUpdateRemover.
* The count is also adjusted by the normal calls to BeginUpdate/EndUpdate.
*/
static void AddRemovableScriptBlocker()
{
AddScriptBlocker();
++sRemovableScriptBlockerCount;
}
static void RemoveRemovableScriptBlocker()
{
NS_ASSERTION(sRemovableScriptBlockerCount != 0,
"Number of removable blockers should never go below zero");
--sRemovableScriptBlockerCount;
RemoveScriptBlocker();
}
static PRUint32 GetRemovableScriptBlockerLevel()
{
return sRemovableScriptBlockerCount;
}
/* Process viewport META data. This gives us information for the scale
* and zoom of a page on mobile devices. We stick the information in
* the document header and use it later on after rendering.
@ -1861,7 +1838,6 @@ private:
static PRBool sInitialized;
static PRUint32 sScriptBlockerCount;
static PRUint32 sRemovableScriptBlockerCount;
#ifdef DEBUG
static PRUint32 sDOMNodeRemovedSuppressCount;
#endif
@ -1929,33 +1905,6 @@ private:
MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class NS_STACK_CLASS nsAutoRemovableScriptBlocker {
public:
nsAutoRemovableScriptBlocker(MOZILLA_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
nsContentUtils::AddRemovableScriptBlocker();
}
~nsAutoRemovableScriptBlocker() {
nsContentUtils::RemoveRemovableScriptBlocker();
}
private:
MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class NS_STACK_CLASS mozAutoRemovableBlockerRemover
{
public:
mozAutoRemovableBlockerRemover(nsIDocument* aDocument
MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM);
~mozAutoRemovableBlockerRemover();
private:
PRUint32 mNestingLevel;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsIDocumentObserver> mObserver;
MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class NS_STACK_CLASS nsAutoScriptBlockerSuppressNodeRemoved :
public nsAutoScriptBlocker {
public:

View File

@ -514,8 +514,7 @@ public:
* Note: If there is no child at aIndex, this method will simply do nothing.
*/
virtual nsresult RemoveChildAt(PRUint32 aIndex,
PRBool aNotify,
PRBool aMutationEvent = PR_TRUE) = 0;
PRBool aNotify) = 0;
/**
* Get a property associated with this node.
@ -1295,8 +1294,7 @@ protected:
* @param aMutationEvent whether to fire a mutation event for this removal.
*/
nsresult doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, nsIContent* aKid,
nsAttrAndChildArray& aChildArray,
PRBool aMutationEvent);
nsAttrAndChildArray& aChildArray);
/**
* Most of the implementation of the nsINode InsertChildAt method.

View File

@ -52,9 +52,6 @@ public:
if (mDocument) {
mDocument->BeginUpdate(mUpdateType);
}
else if (aUpdateType == UPDATE_CONTENT_MODEL) {
nsContentUtils::AddRemovableScriptBlocker();
}
else {
nsContentUtils::AddScriptBlocker();
}
@ -65,9 +62,6 @@ public:
if (mDocument) {
mDocument->EndUpdate(mUpdateType);
}
else if (mUpdateType == UPDATE_CONTENT_MODEL) {
nsContentUtils::RemoveRemovableScriptBlocker();
}
else {
nsContentUtils::RemoveScriptBlocker();
}

View File

@ -255,7 +255,6 @@ PRUint32 nsContentUtils::sJSGCThingRootCount;
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
#endif
PRUint32 nsContentUtils::sScriptBlockerCount = 0;
PRUint32 nsContentUtils::sRemovableScriptBlockerCount = 0;
#ifdef DEBUG
PRUint32 nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
#endif
@ -6168,35 +6167,6 @@ nsContentUtils::CheckCCWrapperTraversal(nsISupports* aScriptObjectHolder,
}
#endif
mozAutoRemovableBlockerRemover::mozAutoRemovableBlockerRemover(nsIDocument* aDocument MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
{
MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
mNestingLevel = nsContentUtils::GetRemovableScriptBlockerLevel();
mDocument = aDocument;
nsISupports* sink = aDocument ? aDocument->GetCurrentContentSink() : nsnull;
mObserver = do_QueryInterface(sink);
for (PRUint32 i = 0; i < mNestingLevel; ++i) {
if (mObserver) {
mObserver->EndUpdate(mDocument, UPDATE_CONTENT_MODEL);
}
nsContentUtils::RemoveRemovableScriptBlocker();
}
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "killing mutation events");
}
mozAutoRemovableBlockerRemover::~mozAutoRemovableBlockerRemover()
{
NS_ASSERTION(nsContentUtils::GetRemovableScriptBlockerLevel() == 0,
"Should have had none");
for (PRUint32 i = 0; i < mNestingLevel; ++i) {
nsContentUtils::AddRemovableScriptBlocker();
if (mObserver) {
mObserver->BeginUpdate(mDocument, UPDATE_CONTENT_MODEL);
}
}
}
// static
PRBool
nsContentUtils::IsFocusedContent(const nsIContent* aContent)

View File

@ -610,9 +610,8 @@ nsDOMAttribute::AppendChildTo(nsIContent* aKid, PRBool aNotify)
}
nsresult
nsDOMAttribute::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
nsDOMAttribute::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on attribute child removal.");
if (aIndex != 0 || !mChild) {
return NS_OK;
}

View File

@ -94,7 +94,7 @@ public:
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,

View File

@ -3449,9 +3449,8 @@ nsDocument::AppendChildTo(nsIContent* aKid, PRBool aNotify)
}
nsresult
nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on document child removal.");
nsCOMPtr<nsIContent> oldKid = GetChildAt(aIndex);
if (!oldKid) {
return NS_OK;
@ -3463,7 +3462,7 @@ nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent
}
nsresult rv =
doRemoveChildAt(aIndex, aNotify, oldKid, mChildren, aMutationEvent);
doRemoveChildAt(aIndex, aNotify, oldKid, mChildren);
mCachedRootElement = nsnull;
return rv;
}
@ -3952,12 +3951,7 @@ nsDocument::BeginUpdate(nsUpdateType aUpdateType)
}
++mUpdateNestLevel;
if (aUpdateType == UPDATE_CONTENT_MODEL) {
nsContentUtils::AddRemovableScriptBlocker();
}
else {
nsContentUtils::AddScriptBlocker();
}
nsContentUtils::AddScriptBlocker();
NS_DOCUMENT_NOTIFY_OBSERVERS(BeginUpdate, (this, aUpdateType));
}
@ -3966,12 +3960,7 @@ nsDocument::EndUpdate(nsUpdateType aUpdateType)
{
NS_DOCUMENT_NOTIFY_OBSERVERS(EndUpdate, (this, aUpdateType));
if (aUpdateType == UPDATE_CONTENT_MODEL) {
nsContentUtils::RemoveRemovableScriptBlocker();
}
else {
nsContentUtils::RemoveScriptBlocker();
}
nsContentUtils::RemoveScriptBlocker();
--mUpdateNestLevel;

View File

@ -730,7 +730,7 @@ public:
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,

View File

@ -723,7 +723,7 @@ nsGenericDOMDataNode::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
}
nsresult
nsGenericDOMDataNode::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
nsGenericDOMDataNode::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
return NS_OK;
}

View File

@ -154,7 +154,7 @@ public:
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,

View File

@ -3663,14 +3663,13 @@ nsINode::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
}
nsresult
nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex);
NS_ASSERTION(oldKid == GetChildAt(aIndex), "Unexpected child in RemoveChildAt");
if (oldKid) {
return doRemoveChildAt(aIndex, aNotify, oldKid, mAttrsAndChildren,
aMutationEvent);
return doRemoveChildAt(aIndex, aNotify, oldKid, mAttrsAndChildren);
}
return NS_OK;
@ -3678,8 +3677,7 @@ nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutatio
nsresult
nsINode::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
nsIContent* aKid, nsAttrAndChildArray& aChildArray,
PRBool aMutationEvent)
nsIContent* aKid, nsAttrAndChildArray& aChildArray)
{
NS_PRECONDITION(aKid && aKid->GetNodeParent() == this &&
aKid == GetChildAt(aIndex) &&
@ -3991,10 +3989,10 @@ PRBool IsAllowedAsChild(nsIContent* aNewChild, PRUint16 aNewNodeType,
void
nsGenericElement::FireNodeInserted(nsIDocument* aDoc,
nsINode* aParent,
nsCOMArray<nsIContent>& aNodes)
nsTArray<nsCOMPtr<nsIContent> >& aNodes)
{
PRInt32 count = aNodes.Count();
for (PRInt32 i = 0; i < count; ++i) {
PRUint32 count = aNodes.Length();
for (PRUint32 i = 0; i < count; ++i) {
nsIContent* childContent = aNodes[i];
if (nsContentUtils::HasMutationListeners(childContent,
@ -4159,57 +4157,18 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
// Copy the children into a separate array to avoid having to deal with
// mutations to the fragment while we're inserting.
nsCOMArray<nsIContent> fragChildren;
if (!fragChildren.SetCapacity(count)) {
return NS_ERROR_OUT_OF_MEMORY;
}
PRUint32 i;
for (i = 0; i < count; i++) {
nsAutoTArray<nsCOMPtr<nsIContent>, 50> fragChildren;
fragChildren.SetCapacity(count);
for (PRUint32 i = 0; i < count; i++) {
nsIContent* child = newContent->GetChildAt(i);
NS_ASSERTION(child->GetCurrentDoc() == nsnull,
"How did we get a child with a current doc?");
fragChildren.AppendObject(child);
fragChildren.AppendElement(child);
}
// Remove the children from the fragment and flag for possible mutations.
PRBool mutated = PR_FALSE;
for (i = count; i > 0;) {
// We don't need to update i if someone mutates the DOM. The only thing
// that'd happen is that the resulting child list might be unexpected,
// but we should never crash since RemoveChildAt is out-of-bounds safe.
nsMutationGuard guard;
// Remove the children from the fragment.
for (PRUint32 i = count; i > 0;) {
newContent->RemoveChildAt(--i, PR_TRUE);
mutated = mutated || guard.Mutated(1);
}
// If we've had any unexpected mutations so far we need to recheck that
// the child can still be inserted.
if (mutated) {
for (i = 0; i < count; ++i) {
// Get the n:th child from the array.
nsIContent* childContent = fragChildren[i];
if (!HasSameOwnerDoc(childContent) ||
doc != childContent->GetOwnerDoc()) {
return NS_ERROR_DOM_WRONG_DOCUMENT_ERR;
}
nsCOMPtr<nsIDOMNode> tmpNode = do_QueryInterface(childContent);
PRUint16 tmpType = 0;
tmpNode->GetNodeType(&tmpType);
if (childContent->GetNodeParent() ||
!IsAllowedAsChild(childContent, tmpType, this, PR_FALSE,
refContent)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
}
insPos = refContent ? IndexOf(refContent) : GetChildCount();
if (insPos < 0) {
// Someone seriously messed up the childlist. We have no idea
// where to insert the remaining children, so just bail.
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
}
PRBool appending =
@ -4219,12 +4178,10 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
// Iterate through the fragment's children, and insert them in the new
// parent
for (i = 0; i < count; ++i, ++insPos) {
nsIContent* childContent = fragChildren[i];
for (PRUint32 i = 0; i < count; ++i, ++insPos) {
// XXXbz how come no reparenting here? That seems odd...
// Insert the child.
res = InsertChildAt(childContent, insPos, PR_FALSE);
res = InsertChildAt(fragChildren[i], insPos, !appending);
if (NS_FAILED(res)) {
// Make sure to notify on any children that we did succeed to insert
if (appending && i != 0) {
@ -4234,22 +4191,17 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
}
return res;
}
if (!appending) {
nsNodeUtils::ContentInserted(this, childContent, insPos);
}
}
// Notify
// Notify and fire mutation events when appending
if (appending) {
nsNodeUtils::ContentAppended(static_cast<nsIContent*>(this),
firstInsertedContent, firstInsPos);
}
// Fire mutation events. Optimize for the case when there are no listeners
if (nsContentUtils::
HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsGenericElement::FireNodeInserted(doc, this, fragChildren);
// Optimize for the case when there are no listeners
if (nsContentUtils::
HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsGenericElement::FireNodeInserted(doc, this, fragChildren);
}
}
}
else {
@ -4629,7 +4581,7 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
// Hold a script blocker while calling ParseAttribute since that can call
// out to id-observers
nsAutoRemovableScriptBlocker scriptBlocker;
nsAutoScriptBlocker scriptBlocker;
nsAttrValue attrValue;
if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {

View File

@ -329,7 +329,7 @@ public:
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
@ -596,7 +596,7 @@ public:
*/
static void FireNodeInserted(nsIDocument* aDoc,
nsINode* aParent,
nsCOMArray<nsIContent>& aNodes);
nsTArray<nsCOMPtr<nsIContent> >& aNodes);
/**
* Helper methods for implementing querySelector/querySelectorAll

View File

@ -136,7 +136,7 @@ nsStyledElementNotElementCSSInlineStyle::UnsetAttr(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRBool aNotify)
{
nsAutoRemovableScriptBlocker scriptBlocker;
nsAutoScriptBlocker scriptBlocker;
if (aAttribute == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) {
// Have to do this before clearing flag. See RemoveFromIdTable
RemoveFromIdTable();

View File

@ -782,12 +782,12 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
PRInt32 newChildCount = GetChildCount();
if (newChildCount && nsContentUtils::
HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMArray<nsIContent> childNodes;
nsAutoTArray<nsCOMPtr<nsIContent>, 50> childNodes;
NS_ASSERTION(newChildCount - oldChildCount >= 0,
"What, some unexpected dom mutation has happened?");
childNodes.SetCapacity(newChildCount - oldChildCount);
for (nsINode::ChildIterator iter(this); !iter.IsDone(); iter.Next()) {
childNodes.AppendObject(iter);
childNodes.AppendElement(iter);
}
nsGenericElement::FireNodeInserted(doc, this, childNodes);
}

View File

@ -217,8 +217,7 @@ nsHTMLFieldSetElement::InsertChildAt(nsIContent* aChild, PRUint32 aIndex,
}
nsresult
nsHTMLFieldSetElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify,
PRBool aMutationEvent /* = PR_TRUE */)
nsHTMLFieldSetElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
bool firstLegendHasChanged = false;
@ -236,7 +235,7 @@ nsHTMLFieldSetElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify,
}
}
nsresult rv = nsGenericHTMLFormElement::RemoveChildAt(aIndex, aNotify, aMutationEvent);
nsresult rv = nsGenericHTMLFormElement::RemoveChildAt(aIndex, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (firstLegendHasChanged) {

View File

@ -76,8 +76,7 @@ public:
virtual nsresult InsertChildAt(nsIContent* aChild, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify,
PRBool aMutationEvent = PR_TRUE);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
// nsIFormControl
NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_FIELDSET; }

View File

@ -75,7 +75,7 @@ public:
// nsGenericElement
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
// nsIContent
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
@ -182,10 +182,11 @@ nsHTMLOptGroupElement::InsertChildAt(nsIContent* aKid,
}
nsresult
nsHTMLOptGroupElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
nsHTMLOptGroupElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
nsSafeOptionListMutation safeMutation(GetSelect(), this, nsnull, aIndex, aNotify);
nsresult rv = nsGenericHTMLElement::RemoveChildAt(aIndex, aNotify, aMutationEvent);
nsSafeOptionListMutation safeMutation(GetSelect(), this, nsnull, aIndex,
aNotify);
nsresult rv = nsGenericHTMLElement::RemoveChildAt(aIndex, aNotify);
if (NS_FAILED(rv)) {
safeMutation.MutationFailed();
}

View File

@ -237,11 +237,10 @@ nsHTMLSelectElement::InsertChildAt(nsIContent* aKid,
}
nsresult
nsHTMLSelectElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
nsHTMLSelectElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on select child removal.");
nsSafeOptionListMutation safeMutation(this, this, nsnull, aIndex, aNotify);
nsresult rv = nsGenericHTMLFormElement::RemoveChildAt(aIndex, aNotify, aMutationEvent);
nsresult rv = nsGenericHTMLFormElement::RemoveChildAt(aIndex, aNotify);
if (NS_FAILED(rv)) {
safeMutation.MutationFailed();
}

View File

@ -280,7 +280,7 @@ public:
virtual PRBool IsHTMLFocusable(PRBool aWithMouse, PRBool *aIsFocusable, PRInt32 *aTabIndex);
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
// Overriden nsIFormControl methods
NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_SELECT; }

View File

@ -121,10 +121,9 @@ nsSVGSwitchElement::InsertChildAt(nsIContent* aKid,
}
nsresult
nsSVGSwitchElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
nsSVGSwitchElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on switch child removal.");
nsresult rv = nsSVGSwitchElementBase::RemoveChildAt(aIndex, aNotify, aMutationEvent);
nsresult rv = nsSVGSwitchElementBase::RemoveChildAt(aIndex, aNotify);
if (NS_SUCCEEDED(rv)) {
MaybeInvalidate();
}

View File

@ -73,7 +73,7 @@ public:
// nsINode
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
// nsIContent
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;

View File

@ -72,7 +72,7 @@ nsresult
nsXMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify)
{
nsAutoRemovableScriptBlocker scriptBlocker;
nsAutoScriptBlocker scriptBlocker;
PRBool isId = PR_FALSE;
if (aAttribute == GetIDAttributeName() &&
aNameSpaceID == kNameSpaceID_None) {

View File

@ -271,13 +271,12 @@ nsXTFElementWrapper::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
}
nsresult
nsXTFElementWrapper::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
nsXTFElementWrapper::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on xtf child removal.");
nsresult rv;
if (mNotificationMask & nsIXTFElement::NOTIFY_WILL_REMOVE_CHILD)
GetXTFElement()->WillRemoveChild(aIndex);
rv = nsXTFElementWrapperBase::RemoveChildAt(aIndex, aNotify, aMutationEvent);
rv = nsXTFElementWrapperBase::RemoveChildAt(aIndex, aNotify);
if (mNotificationMask & nsIXTFElement::NOTIFY_CHILD_REMOVED)
GetXTFElement()->ChildRemoved(aIndex);
return rv;

View File

@ -84,7 +84,7 @@ public:
PRBool aNullParent = PR_TRUE);
nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE);
nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
nsIAtom *GetIDAttributeName() const;
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,

View File

@ -946,9 +946,8 @@ nsXULElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
}
nsresult
nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on XUL child removal.");
nsresult rv;
nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex);
if (!oldKid) {
@ -1015,7 +1014,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEve
}
}
rv = nsStyledElement::RemoveChildAt(aIndex, aNotify, aMutationEvent);
rv = nsStyledElement::RemoveChildAt(aIndex, aNotify);
if (newCurrentIndex == -2)
controlElement->SetCurrentItem(nsnull);

View File

@ -505,7 +505,7 @@ public:
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep, PRBool aNullParent);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual PRBool GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAString& aResult) const;
virtual PRBool HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const;

View File

@ -7846,6 +7846,56 @@ nsDocShell::CheckLoadingPermissions()
//*****************************************************************************
// nsDocShell: Site Loading
//*****************************************************************************
namespace
{
// Callback used by CopyFavicon to inform the favicon service that one URI
// (mNewURI) has the same favicon URI (OnFaviconDataAvailable's aFaviconURI) as
// another.
class nsCopyFaviconCallback : public nsIFaviconDataCallback
{
public:
NS_DECL_ISUPPORTS
nsCopyFaviconCallback(nsIURI *aNewURI)
: mNewURI(aNewURI)
{
}
NS_IMETHODIMP
OnFaviconDataAvailable(nsIURI *aFaviconURI, PRUint32 aDataLen,
const PRUint8 *aData, const nsACString &aMimeType)
{
NS_ASSERTION(aDataLen == 0,
"We weren't expecting the callback to deliver data.");
nsCOMPtr<mozIAsyncFavicons> favSvc =
do_GetService("@mozilla.org/browser/favicon-service;1");
NS_ENSURE_STATE(favSvc);
return favSvc->SetAndFetchFaviconForPage(mNewURI, aFaviconURI,
PR_FALSE, nsnull);
}
private:
nsCOMPtr<nsIURI> mNewURI;
};
NS_IMPL_ISUPPORTS1(nsCopyFaviconCallback, nsIFaviconDataCallback)
// Tell the favicon service that aNewURI has the same favicon as aOldURI.
void CopyFavicon(nsIURI *aOldURI, nsIURI *aNewURI)
{
nsCOMPtr<mozIAsyncFavicons> favSvc =
do_GetService("@mozilla.org/browser/favicon-service;1");
if (favSvc) {
nsCOMPtr<nsIFaviconDataCallback> callback =
new nsCopyFaviconCallback(aNewURI);
favSvc->GetFaviconURLForPage(aOldURI, callback);
}
}
} // anonymous namespace
class InternalLoadEvent : public nsRunnable
{
public:
@ -8450,6 +8500,10 @@ nsDocShell::InternalLoad(nsIURI * aURI,
}
}
// Inform the favicon service that the favicon for oldURI also
// applies to aURI.
CopyFavicon(oldURI, aURI);
return NS_OK;
}
}
@ -9439,43 +9493,6 @@ nsDocShell::SetReferrerURI(nsIURI * aURI)
// nsDocShell: Session History
//*****************************************************************************
namespace
{
// Callback used in nsDocShell::AddState. When we change URIs with
// push/replaceState, we use this callback to ensure that Places associates
// a favicon with the new URI.
class nsAddStateFaviconCallback : public nsIFaviconDataCallback
{
public:
NS_DECL_ISUPPORTS
nsAddStateFaviconCallback(nsIURI *aNewURI)
: mNewURI(aNewURI)
{
}
NS_IMETHODIMP
OnFaviconDataAvailable(nsIURI *aFaviconURI, PRUint32 aDataLen,
const PRUint8 *aData, const nsACString &aMimeType)
{
NS_ASSERTION(aDataLen == 0,
"We weren't expecting the callback to deliver data.");
nsCOMPtr<mozIAsyncFavicons> favSvc =
do_GetService("@mozilla.org/browser/favicon-service;1");
NS_ENSURE_STATE(favSvc);
return favSvc->SetAndFetchFaviconForPage(mNewURI, aFaviconURI,
PR_FALSE, nsnull);
}
private:
nsCOMPtr<nsIURI> mNewURI;
};
NS_IMPL_ISUPPORTS1(nsAddStateFaviconCallback, nsIFaviconDataCallback)
} // anonymous namespace
NS_IMETHODIMP
nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
const nsAString& aURL, PRBool aReplace, JSContext* aCx)
@ -9766,13 +9783,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
// Inform the favicon service that our old favicon applies to this new
// URI.
nsCOMPtr<mozIAsyncFavicons> favSvc =
do_GetService("@mozilla.org/browser/favicon-service;1");
if (favSvc) {
nsCOMPtr<nsIFaviconDataCallback> callback =
new nsAddStateFaviconCallback(newURI);
favSvc->GetFaviconURLForPage(oldURI, callback);
}
CopyFavicon(oldURI, newURI);
}
else {
FireDummyOnLocationChange();

View File

@ -51,6 +51,8 @@ _BROWSER_TEST_FILES = \
browser_bug388121-1.js \
browser_bug388121-2.js \
browser_bug441169.js \
browser_bug420605.js \
file_bug420605.html \
browser_bug503832.js \
browser_loadDisallowInherit.js \
file_bug503832.html \

View File

@ -0,0 +1,123 @@
/* Test for Bug 420605
* https://bugzilla.mozilla.org/show_bug.cgi?id=420605
*/
function test() {
waitForExplicitFinish();
var pageurl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html";
var fragmenturl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html#firefox";
var historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService);
/* Queries nsINavHistoryService and returns a single history entry
* for a given URI */
function getNavHistoryEntry(aURI) {
var options = historyService.getNewQueryOptions();
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
options.maxResults = 1;
var query = historyService.getNewQuery();
query.uri = aURI;
var result = historyService.executeQuery(query, options);
result.root.containerOpen = true;
if (!result.root.childCount) {
return null;
}
return result.root.getChild(0);
}
// We'll save the favicon URL of the orignal page here and check that the
// page with a hash has the same favicon.
var originalFavicon;
// Control flow in this test is a bit complicated.
//
// When the page loads, onPageLoad (the DOMContentLoaded handler) and
// historyObserver::onPageChanged are both called, in some order. Once
// they've both run, we click a fragment link in the content page
// (clickLinkIfReady), which should trigger another onPageChanged event,
// this time for the fragment's URL.
var _clickLinkTimes = 0;
function clickLinkIfReady() {
_clickLinkTimes++;
if (_clickLinkTimes == 2) {
EventUtils.sendMouseEvent({type:'click'}, 'firefox-link',
gBrowser.selectedBrowser.contentWindow);
}
}
/* Global history observer that triggers for the two test URLs above. */
var historyObserver = {
onBeginUpdateBatch: function() {},
onEndUpdateBatch: function() {},
onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
aTransitionType, _added) {},
onTitleChanged: function(aURI, aPageTitle) {},
onBeforeDeleteURI: function(aURI) {},
onDeleteURI: function(aURI) {},
onClearHistory: function() {},
onPageChanged: function(aURI, aWhat, aValue) {
if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
return;
}
aURI = aURI.spec;
switch (aURI) {
case pageurl:
ok(aValue, "Favicon value is not null for page without fragment.");
originalFavicon = aValue;
// Now that the favicon has loaded, click on fragment link.
// This should trigger the |case fragmenturl| below.
clickLinkIfReady();
return;
case fragmenturl:
// If the fragment URL's favicon isn't set, this branch won't
// be called and the test will time out.
is(aValue, originalFavicon, "New favicon should be same as original favicon.");
// Let's explicitly check that we can get the favicon
// from nsINavHistoryService now.
let info = getNavHistoryEntry(makeURI(aURI));
ok(info, "There must be a history entry for the fragment.");
ok(info.icon, "The history entry must have an associated favicon.");
historyService.removeObserver(historyObserver, false);
gBrowser.removeCurrentTab();
finish();
}
},
onPageExpired: function(aURI, aVisitTime, aWholeEntry) {},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsINavHistoryObserver) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
historyService.addObserver(historyObserver, false);
function onPageLoad() {
gBrowser.selectedBrowser
.removeEventListener("DOMContentLoaded", arguments.callee, true);
clickLinkIfReady();
}
// Make sure neither of the test pages haven't been loaded before.
var info = getNavHistoryEntry(makeURI(pageurl));
ok(!info, "The test page must not have been visited already.");
info = getNavHistoryEntry(makeURI(fragmenturl));
ok(!info, "The fragment test page must not have been visited already.");
// Now open the test page in a new tab.
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener(
"DOMContentLoaded", onPageLoad, true);
content.location = pageurl;
}

View File

@ -0,0 +1,31 @@
<head>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="/>
<title>Page Title for Bug 420605</title>
</head>
<body>
<h1>Fragment links</h1>
<p>This page has a bunch of fragment links to sections below:</p>
<ul>
<li><a id="firefox-link" href="#firefox">Firefox</a></li>
<li><a id="thunderbird-link" href="#thunderbird">Thunderbird</a></li>
<li><a id="seamonkey-link" href="#seamonkey">Seamonkey</a></li>
</ul>
<p>And here are the sections:</p>
<h2 id="firefox">Firefox</h2>
<p>Firefox is a browser.</p>
<h2 id="thunderbird">Thunderbird</h2>
<p>Thunderbird is an email client</p>
<h2 id="seamonkey">Seamonkey</h2>
<p>Seamonkey is the all-in-one application.</p>
</body>
</html>

View File

@ -5807,7 +5807,8 @@ nsHTMLEditRules::GetNodesForOperation(nsCOMArray<nsIDOMRange>& inArrayOfRanges,
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ASSERTION(rangeCount == rangeItemArray.Length(), "How did that happen?");
NS_ASSERTION(static_cast<PRUint32>(rangeCount) == rangeItemArray.Length(),
"How did that happen?");
// first register ranges for special editor gravity
for (i = 0; i < rangeCount; i++)

View File

@ -1700,7 +1700,27 @@ nsPlaintextEditor::SelectEntireDocument(nsISelection *aSelection)
return aSelection->Collapse(rootElement, 0);
}
return nsEditor::SelectEntireDocument(aSelection);
nsresult rv = nsEditor::SelectEntireDocument(aSelection);
NS_ENSURE_SUCCESS(rv, rv);
// Don't select the trailing BR node if we have one
PRInt32 selOffset;
nsCOMPtr<nsIDOMNode> selNode;
rv = GetEndNodeAndOffset(aSelection, getter_AddRefs(selNode), &selOffset);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> childNode = GetChildAt(selNode, selOffset - 1);
if (childNode && nsTextEditUtils::IsMozBR(childNode)) {
nsCOMPtr<nsIDOMNode> parentNode;
PRInt32 parentOffset;
rv = GetNodeLocation(childNode, address_of(parentNode), &parentOffset);
NS_ENSURE_SUCCESS(rv, rv);
return aSelection->Extend(parentNode, parentOffset);
}
return NS_OK;
}
already_AddRefed<nsPIDOMEventTarget>

View File

@ -70,20 +70,25 @@ CSRCS = \
cairo-arc.c \
cairo-array.c \
cairo-atomic.c \
cairo-base64-stream.c \
cairo-bentley-ottmann.c \
cairo-bentley-ottmann-rectilinear.c \
cairo-bentley-ottmann-rectangular.c \
cairo-base64-stream.c \
cairo-botor-scan-converter.c \
cairo-boxes.c \
cairo-cache.c \
cairo-clip.c \
cairo-color.c \
cairo-composite-rectangles.c \
cairo-debug.c \
cairo-deflate-stream.c \
cairo-device.c \
cairo-fixed.c \
cairo-font-face.c \
cairo-font-face-twin.c \
cairo-font-face-twin-data.c \
cairo-font-options.c \
cairo-freed-pool.c \
cairo-freelist.c \
cairo-gstate.c \
cairo-hash.c \
@ -94,6 +99,7 @@ CSRCS = \
cairo-matrix.c \
cairo-misc.c \
cairo-mutex.c \
cairo-observer.c \
cairo-output-stream.c \
cairo-paginated-surface.c \
cairo-path.c \
@ -107,6 +113,7 @@ CSRCS = \
cairo-polygon.c \
cairo-recording-surface.c \
cairo-rectangle.c \
cairo-rectangular-scan-converter.c \
cairo-region.c \
cairo-scaled-font.c \
cairo-scaled-font-subsets.c \
@ -117,6 +124,9 @@ CSRCS = \
cairo-surface.c \
cairo-surface-clipper.c \
cairo-surface-fallback.c \
cairo-surface-offset.c \
cairo-surface-snapshot.c \
cairo-surface-subsurface.c \
cairo-surface-wrapper.c \
cairo-tee-surface.c \
cairo-tor-scan-converter.c \
@ -130,7 +140,7 @@ CSRCS = \
EXPORTS_NAMESPACES = cairo
EXPORTS_cairo = cairo.h cairo-version.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
EXPORTS_cairo = cairo.h cairo-version.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h cairo-tee.h
# cairo-type1-subset.c should be here, but it's only supported on freetype platforms
@ -153,6 +163,7 @@ PDF_EXPORTS = cairo-pdf.h
PS_EXPORTS = cairo-ps.h
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
DEFINES += -DDISABLE_SOME_FLOATING_POINT
CSRCS += cairo-win32-surface.c
ifndef WINCE
@ -269,3 +280,4 @@ endif
cairo-features.h: $(srcdir)/cairo-features.h.in $(GLOBAL_DEPS)
$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) ./$@
cat cairo-dwrite-font.i | gzip | python -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)"

View File

@ -11,7 +11,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -37,6 +37,8 @@
#include "cairoint.h"
CAIRO_BEGIN_DECLS
cairo_private cairo_surface_t *
_cairo_analysis_surface_create (cairo_surface_t *target);
@ -71,4 +73,6 @@ _cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
cairo_private cairo_surface_t *
_cairo_null_surface_create (cairo_content_t content);
CAIRO_END_DECLS
#endif /* CAIRO_ANALYSIS_SURFACE_H */

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -37,8 +37,10 @@
#include "cairoint.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-error-private.h"
#include "cairo-paginated-private.h"
#include "cairo-recording-surface-private.h"
#include "cairo-surface-subsurface-private.h"
#include "cairo-region-private.h"
typedef struct {
@ -99,10 +101,11 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
cairo_bool_t old_has_ctm;
cairo_matrix_t old_ctm, p2d;
cairo_status_t status;
cairo_surface_t *source;
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
surface_pattern = (const cairo_surface_pattern_t *) pattern;
assert (_cairo_surface_is_recording (surface_pattern->surface));
assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING);
old_ctm = surface->ctm;
old_has_ctm = surface->has_ctm;
@ -114,8 +117,13 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
surface->has_ctm = ! _cairo_matrix_is_identity (&surface->ctm);
status = _cairo_recording_surface_replay_and_create_regions (surface_pattern->surface,
&surface->base);
source = surface_pattern->surface;
if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
source = sub->target;
}
status = _cairo_recording_surface_replay_and_create_regions (source, &surface->base);
surface->ctm = old_ctm;
surface->has_ctm = old_has_ctm;
@ -396,9 +404,9 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
cairo_clip_t *clip)
@ -716,7 +724,9 @@ _cairo_analysis_surface_create (cairo_surface_t *target)
/* I believe the content type here is truly arbitrary. I'm quite
* sure nothing will ever use this value. */
_cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_analysis_surface_backend,
NULL, /* device */
CAIRO_CONTENT_COLOR_ALPHA);
cairo_matrix_init_identity (&surface->ctm);
@ -831,9 +841,9 @@ typedef cairo_int_status_t
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
cairo_clip_t *clip);
@ -906,7 +916,10 @@ _cairo_null_surface_create (cairo_content_t content)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
_cairo_surface_init (surface, &cairo_null_surface_backend, content);
_cairo_surface_init (surface,
&cairo_null_surface_backend,
NULL, /* device */
content);
return surface;
}

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -36,6 +36,7 @@
*/
#include "cairoint.h"
#include "cairo-error-private.h"
/**
* _cairo_array_init:
@ -260,7 +261,7 @@ _cairo_array_append (cairo_array_t *array,
}
/**
* _cairo_array_append:
* _cairo_array_append_multiple:
* @array: a #cairo_array_t
*
* Append one or more items onto the array by growing the array by

View File

@ -1,6 +1,7 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2007 Chris Wilson
* Copyright © 2010 Andrea Canciani
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -12,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -32,6 +33,7 @@
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
* Andrea Canciani <ranma42@gmail.com>
*/
#ifndef CAIRO_ATOMIC_PRIVATE_H
@ -57,12 +59,29 @@ CAIRO_BEGIN_DECLS
typedef int cairo_atomic_int_t;
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
static cairo_always_inline cairo_atomic_int_t
_cairo_atomic_int_get (cairo_atomic_int_t *x)
{
__sync_synchronize ();
return *x;
}
static cairo_always_inline void *
_cairo_atomic_ptr_get (void **x)
{
__sync_synchronize ();
return *x;
}
#else
# define _cairo_atomic_int_get(x) (*x)
# define _cairo_atomic_int_set(x, value) ((*x) = value)
# define _cairo_atomic_ptr_get(x) (*x)
#endif
# define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
# define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_bool_compare_and_swap (x, oldv, newv)
# define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
#if SIZEOF_VOID_P==SIZEOF_INT
typedef int cairo_atomic_intptr_t;
@ -75,7 +94,10 @@ typedef long long cairo_atomic_intptr_t;
#endif
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
(void*)__sync_val_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
__sync_bool_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
# define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \
_cairo_atomic_intptr_to_voidptr (__sync_val_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv))
#endif
@ -87,11 +109,10 @@ typedef long long cairo_atomic_intptr_t;
typedef AO_t cairo_atomic_int_t;
# define _cairo_atomic_int_get(x) (AO_load_full (x))
# define _cairo_atomic_int_set(x, value) (AO_store_full (x))
# define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
# define _cairo_atomic_int_dec_and_test(x) (AO_fetch_and_sub1_full(x) == 1)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) ((cairo_atomic_int_t) AO_compare_and_swap_full(x, oldv, newv) ? oldv : *x)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) AO_compare_and_swap_full(x, oldv, newv)
#if SIZEOF_VOID_P==SIZEOF_INT
typedef unsigned int cairo_atomic_intptr_t;
@ -103,45 +124,129 @@ typedef unsigned long long cairo_atomic_intptr_t;
#error No matching integer pointer type
#endif
# define _cairo_atomic_ptr_get(x) _cairo_atomic_intptr_to_voidptr (AO_load_full (x))
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
(void*) (cairo_atomic_intptr_t) _cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
_cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
#endif
#if HAVE_OS_ATOMIC_OPS
#include <libkern/OSAtomic.h>
#define HAS_ATOMIC_OPS 1
typedef int32_t cairo_atomic_int_t;
# define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x))
# define _cairo_atomic_int_inc(x) ((void) OSAtomicIncrement32Barrier (x))
# define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x)
#if SIZEOF_VOID_P==4
typedef int32_t cairo_atomic_intptr_t;
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
OSAtomicCompareAndSwap32Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
#elif SIZEOF_VOID_P==8
typedef int64_t cairo_atomic_intptr_t;
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
OSAtomicCompareAndSwap64Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
#else
#error No matching integer pointer type
#endif
# define _cairo_atomic_ptr_get(x) (OSMemoryBarrier(), *(x))
#endif
#ifndef HAS_ATOMIC_OPS
typedef int cairo_atomic_int_t;
#if SIZEOF_VOID_P==SIZEOF_INT
typedef unsigned int cairo_atomic_intptr_t;
#elif SIZEOF_VOID_P==SIZEOF_LONG
typedef unsigned long cairo_atomic_intptr_t;
#elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
typedef unsigned long long cairo_atomic_intptr_t;
#else
#error No matching integer pointer type
#endif
typedef cairo_atomic_intptr_t cairo_atomic_int_t;
cairo_private void
_cairo_atomic_int_inc (int *x);
_cairo_atomic_int_inc (cairo_atomic_int_t *x);
cairo_private cairo_bool_t
_cairo_atomic_int_dec_and_test (int *x);
_cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x);
cairo_private int
_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
cairo_private cairo_atomic_int_t
_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv);
cairo_private void *
_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv);
_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv);
#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_impl (x, oldv, newv)
#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_impl (x, oldv, newv)
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
# include "cairo-compiler-private.h"
cairo_private int
_cairo_atomic_int_get (int *x);
cairo_private void
_cairo_atomic_int_set (int *x, int value);
cairo_private cairo_atomic_int_t
_cairo_atomic_int_get (cairo_atomic_int_t *x);
# define _cairo_atomic_ptr_get(x) (void *) _cairo_atomic_int_get((cairo_atomic_int_t *) x)
#else
# define _cairo_atomic_int_get(x) (*x)
# define _cairo_atomic_ptr_get(x) (*x)
#endif
#else
# define _cairo_atomic_int_get(x) (*x)
# define _cairo_atomic_int_set(x, value) ((*x) = value)
/* Workaround GCC complaining about casts */
static cairo_always_inline void *
_cairo_atomic_intptr_to_voidptr (cairo_atomic_intptr_t x)
{
return (void *) x;
}
static cairo_always_inline cairo_atomic_int_t
_cairo_atomic_int_cmpxchg_return_old_fallback(cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv)
{
cairo_atomic_int_t curr;
do {
curr = _cairo_atomic_int_get (x);
} while (curr == oldv && !_cairo_atomic_int_cmpxchg (x, oldv, newv));
return curr;
}
static cairo_always_inline void *
_cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv)
{
void *curr;
do {
curr = _cairo_atomic_ptr_get (x);
} while (curr == oldv && !_cairo_atomic_ptr_cmpxchg (x, oldv, newv));
return curr;
}
#endif
#ifndef _cairo_atomic_int_cmpxchg_return_old
#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_fallback (x, oldv, newv)
#endif
#ifndef _cairo_atomic_ptr_cmpxchg_return_old
#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_fallback (x, oldv, newv)
#endif
#ifndef _cairo_atomic_int_cmpxchg
#define _cairo_atomic_int_cmpxchg(x, oldv, newv) (_cairo_atomic_int_cmpxchg_return_old (x, oldv, newv) == oldv)
#endif
#ifndef _cairo_atomic_ptr_cmpxchg
#define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) (_cairo_atomic_ptr_cmpxchg_return_old (x, oldv, newv) == oldv)
#endif
#define _cairo_atomic_uint_get(x) _cairo_atomic_int_get(x)

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -42,7 +42,7 @@ COMPILE_TIME_ASSERT(sizeof(void*) == sizeof(int) ||
sizeof(void*) == sizeof(long long));
#else
void
_cairo_atomic_int_inc (int *x)
_cairo_atomic_int_inc (cairo_atomic_intptr_t *x)
{
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
*x += 1;
@ -50,7 +50,7 @@ _cairo_atomic_int_inc (int *x)
}
cairo_bool_t
_cairo_atomic_int_dec_and_test (int *x)
_cairo_atomic_int_dec_and_test (cairo_atomic_intptr_t *x)
{
cairo_bool_t ret;
@ -61,10 +61,10 @@ _cairo_atomic_int_dec_and_test (int *x)
return ret;
}
int
_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
cairo_atomic_intptr_t
_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_intptr_t *x, cairo_atomic_intptr_t oldv, cairo_atomic_intptr_t newv)
{
int ret;
cairo_atomic_intptr_t ret;
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
ret = *x;
@ -76,7 +76,7 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
}
void *
_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv)
_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv)
{
void *ret;
@ -88,13 +88,12 @@ _cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv)
return ret;
}
#endif
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
int
_cairo_atomic_int_get (int *x)
cairo_atomic_intptr_t
_cairo_atomic_int_get (cairo_atomic_intptr_t *x)
{
int ret;
cairo_atomic_intptr_t ret;
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
ret = *x;
@ -102,12 +101,6 @@ _cairo_atomic_int_get (int *x)
return ret;
}
void
_cairo_atomic_int_set (int *x, int value)
{
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
*x = value;
CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
}
#endif
#endif

View File

@ -14,7 +14,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -37,6 +37,7 @@
*/
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-output-stream-private.h"
typedef struct _cairo_base64_stream {

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -35,6 +35,7 @@
*/
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-output-stream-private.h"
typedef struct _cairo_base85_stream {

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -38,7 +38,9 @@
/* Provide definitions for standalone compilation */
#include "cairoint.h"
#include "cairo-boxes-private.h"
#include "cairo-combsort-private.h"
#include "cairo-error-private.h"
typedef struct _cairo_bo_edge cairo_bo_edge_t;
typedef struct _cairo_bo_trap cairo_bo_trap_t;
@ -215,20 +217,33 @@ edges_collinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
static cairo_status_t
_cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
int32_t bot,
cairo_traps_t *traps)
cairo_bool_t do_traps,
void *container)
{
cairo_bo_trap_t *trap = &left->deferred_trap;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
/* Only emit (trivial) non-degenerate trapezoids with positive height. */
if (likely (trap->top < bot)) {
_cairo_traps_add_trap (traps,
trap->top, bot,
&left->edge.line, &trap->right->edge.line);
if (do_traps) {
_cairo_traps_add_trap (container,
trap->top, bot,
&left->edge.line, &trap->right->edge.line);
status = _cairo_traps_status ((cairo_traps_t *) container);
} else {
cairo_box_t box;
box.p1.x = left->edge.line.p1.x;
box.p1.y = trap->top;
box.p2.x = trap->right->edge.line.p1.x;
box.p2.y = bot;
status = _cairo_boxes_add (container, &box);
}
}
trap->right = NULL;
return _cairo_traps_status (traps);
return status;
}
/* Start a new trapezoid at the given top y coordinate, whose edges
@ -240,7 +255,8 @@ static inline cairo_status_t
_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *left,
cairo_bo_edge_t *right,
int top,
cairo_traps_t *traps)
cairo_bool_t do_traps,
void *container)
{
cairo_status_t status;
@ -255,7 +271,7 @@ _cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *left,
return CAIRO_STATUS_SUCCESS;
}
status = _cairo_bo_edge_end_trap (left, top, traps);
status = _cairo_bo_edge_end_trap (left, top, do_traps, container);
if (unlikely (status))
return status;
}
@ -272,7 +288,8 @@ static inline cairo_status_t
_active_edges_to_traps (cairo_bo_edge_t *left,
int32_t top,
cairo_fill_rule_t fill_rule,
cairo_traps_t *traps)
cairo_bool_t do_traps,
void *container)
{
cairo_bo_edge_t *right;
cairo_status_t status;
@ -303,7 +320,7 @@ _active_edges_to_traps (cairo_bo_edge_t *left,
right = left->next;
while (right != NULL) {
if (right->deferred_trap.right != NULL) {
status = _cairo_bo_edge_end_trap (right, top, traps);
status = _cairo_bo_edge_end_trap (right, top, do_traps, container);
if (unlikely (status))
return status;
}
@ -321,8 +338,8 @@ _active_edges_to_traps (cairo_bo_edge_t *left,
right = right->next;
}
status = _cairo_bo_edge_start_or_continue_trap (left, right,
top, traps);
status = _cairo_bo_edge_start_or_continue_trap (left, right, top,
do_traps, container);
if (unlikely (status))
return status;
@ -337,7 +354,7 @@ _active_edges_to_traps (cairo_bo_edge_t *left,
right = left->next;
while (right != NULL) {
if (right->deferred_trap.right != NULL) {
status = _cairo_bo_edge_end_trap (right, top, traps);
status = _cairo_bo_edge_end_trap (right, top, do_traps, container);
if (unlikely (status))
return status;
}
@ -358,8 +375,8 @@ _active_edges_to_traps (cairo_bo_edge_t *left,
right = right->next;
}
status = _cairo_bo_edge_start_or_continue_trap (left, right,
top, traps);
status = _cairo_bo_edge_start_or_continue_trap (left, right, top,
do_traps, container);
if (unlikely (status))
return status;
@ -376,7 +393,8 @@ static cairo_status_t
_cairo_bentley_ottmann_tessellate_rectilinear (cairo_bo_event_t **start_events,
int num_events,
cairo_fill_rule_t fill_rule,
cairo_traps_t *traps)
cairo_bool_t do_traps,
void *container)
{
cairo_bo_sweep_line_t sweep_line;
cairo_bo_event_t *event;
@ -388,7 +406,7 @@ _cairo_bentley_ottmann_tessellate_rectilinear (cairo_bo_event_t **start_events
if (event->point.y != sweep_line.current_y) {
status = _active_edges_to_traps (sweep_line.head,
sweep_line.current_y,
fill_rule, traps);
fill_rule, do_traps, container);
if (unlikely (status))
return status;
@ -406,7 +424,7 @@ _cairo_bentley_ottmann_tessellate_rectilinear (cairo_bo_event_t **start_events
if (event->edge->deferred_trap.right != NULL) {
status = _cairo_bo_edge_end_trap (event->edge,
sweep_line.current_y,
traps);
do_traps, container);
if (unlikely (status))
return status;
}
@ -476,7 +494,8 @@ _cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t *traps,
}
status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
fill_rule, traps);
fill_rule,
TRUE, traps);
if (events != stack_events)
free (events);
@ -485,6 +504,72 @@ _cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t *traps,
return status;
}
cairo_status_t
_cairo_bentley_ottmann_tessellate_rectilinear_polygon_to_boxes (const cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule,
cairo_boxes_t *boxes)
{
cairo_status_t status;
cairo_bo_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_event_t)];
cairo_bo_event_t *events;
cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
cairo_bo_event_t **event_ptrs;
cairo_bo_edge_t stack_edges[ARRAY_LENGTH (stack_events)];
cairo_bo_edge_t *edges;
int num_events;
int i, j;
if (unlikely (polygon->num_edges == 0))
return CAIRO_STATUS_SUCCESS;
num_events = 2 * polygon->num_edges;
events = stack_events;
event_ptrs = stack_event_ptrs;
edges = stack_edges;
if (num_events > ARRAY_LENGTH (stack_events)) {
events = _cairo_malloc_ab_plus_c (num_events,
sizeof (cairo_bo_event_t) +
sizeof (cairo_bo_edge_t) +
sizeof (cairo_bo_event_t *),
sizeof (cairo_bo_event_t *));
if (unlikely (events == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
event_ptrs = (cairo_bo_event_t **) (events + num_events);
edges = (cairo_bo_edge_t *) (event_ptrs + num_events + 1);
}
for (i = j = 0; i < polygon->num_edges; i++) {
edges[i].edge = polygon->edges[i];
edges[i].deferred_trap.right = NULL;
edges[i].prev = NULL;
edges[i].next = NULL;
event_ptrs[j] = &events[j];
events[j].type = CAIRO_BO_EVENT_TYPE_START;
events[j].point.y = polygon->edges[i].top;
events[j].point.x = polygon->edges[i].line.p1.x;
events[j].edge = &edges[i];
j++;
event_ptrs[j] = &events[j];
events[j].type = CAIRO_BO_EVENT_TYPE_STOP;
events[j].point.y = polygon->edges[i].bottom;
events[j].point.x = polygon->edges[i].line.p1.x;
events[j].edge = &edges[i];
j++;
}
status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
fill_rule,
FALSE, boxes);
if (events != stack_events)
free (events);
return status;
}
cairo_status_t
_cairo_bentley_ottmann_tessellate_rectilinear_traps (cairo_traps_t *traps,
cairo_fill_rule_t fill_rule)
@ -572,7 +657,7 @@ _cairo_bentley_ottmann_tessellate_rectilinear_traps (cairo_traps_t *traps,
_cairo_traps_clear (traps);
status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
fill_rule,
traps);
TRUE, traps);
traps->is_rectilinear = TRUE;
if (events != stack_events)

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -38,6 +38,7 @@
/* Provide definitions for standalone compilation */
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-freelist-private.h"
#include "cairo-combsort-private.h"
@ -129,21 +130,25 @@ static void
dump_traps (cairo_traps_t *traps, const char *filename)
{
FILE *file;
cairo_box_t extents;
int n;
if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
return;
#if 0
if (traps->has_limits) {
printf ("%s: limits=(%d, %d, %d, %d)\n",
filename,
traps->limits.p1.x, traps->limits.p1.y,
traps->limits.p2.x, traps->limits.p2.y);
}
#endif
_cairo_traps_extents (traps, &extents);
printf ("%s: extents=(%d, %d, %d, %d)\n",
filename,
traps->extents.p1.x, traps->extents.p1.y,
traps->extents.p2.x, traps->extents.p2.y);
extents.p1.x, extents.p1.y,
extents.p2.x, extents.p2.y);
file = fopen (filename, "a");
if (file != NULL) {

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef CAIRO_BOXES_H
#define CAIRO_BOXES_H
#include "cairo-types-private.h"
#include "cairo-compiler-private.h"
struct _cairo_boxes_t {
cairo_status_t status;
cairo_box_t limit;
const cairo_box_t *limits;
int num_limits;
int num_boxes;
unsigned int is_pixel_aligned : 1;
struct _cairo_boxes_chunk {
struct _cairo_boxes_chunk *next;
cairo_box_t *base;
int count;
int size;
} chunks, *tail;
cairo_box_t boxes_embedded[32];
};
cairo_private void
_cairo_boxes_init (cairo_boxes_t *boxes);
cairo_private void
_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
cairo_box_t *array,
int num_boxes);
cairo_private void
_cairo_boxes_limit (cairo_boxes_t *boxes,
const cairo_box_t *limits,
int num_limits);
cairo_private cairo_status_t
_cairo_boxes_add (cairo_boxes_t *boxes,
const cairo_box_t *box);
cairo_private void
_cairo_boxes_extents (const cairo_boxes_t *boxes,
cairo_rectangle_int_t *extents);
cairo_private void
_cairo_boxes_clear (cairo_boxes_t *boxes);
cairo_private void
_cairo_boxes_fini (cairo_boxes_t *boxes);
#endif /* CAIRO_BOXES_H */

View File

@ -0,0 +1,300 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-boxes-private.h"
#include "cairo-error-private.h"
void
_cairo_boxes_init (cairo_boxes_t *boxes)
{
boxes->status = CAIRO_STATUS_SUCCESS;
boxes->num_limits = 0;
boxes->num_boxes = 0;
boxes->tail = &boxes->chunks;
boxes->chunks.next = NULL;
boxes->chunks.base = boxes->boxes_embedded;
boxes->chunks.size = ARRAY_LENGTH (boxes->boxes_embedded);
boxes->chunks.count = 0;
boxes->is_pixel_aligned = TRUE;
}
void
_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
cairo_box_t *array,
int num_boxes)
{
int n;
boxes->status = CAIRO_STATUS_SUCCESS;
boxes->num_limits = 0;
boxes->num_boxes = num_boxes;
boxes->tail = &boxes->chunks;
boxes->chunks.next = NULL;
boxes->chunks.base = array;
boxes->chunks.size = num_boxes;
boxes->chunks.count = num_boxes;
for (n = 0; n < num_boxes; n++) {
if (! _cairo_fixed_is_integer (array[n].p1.x) ||
! _cairo_fixed_is_integer (array[n].p1.y) ||
! _cairo_fixed_is_integer (array[n].p2.x) ||
! _cairo_fixed_is_integer (array[n].p2.y))
{
break;
}
}
boxes->is_pixel_aligned = n == num_boxes;
}
void
_cairo_boxes_limit (cairo_boxes_t *boxes,
const cairo_box_t *limits,
int num_limits)
{
int n;
boxes->limits = limits;
boxes->num_limits = num_limits;
if (boxes->num_limits) {
boxes->limit = limits[0];
for (n = 1; n < num_limits; n++) {
if (limits[n].p1.x < boxes->limit.p1.x)
boxes->limit.p1.x = limits[n].p1.x;
if (limits[n].p1.y < boxes->limit.p1.y)
boxes->limit.p1.y = limits[n].p1.y;
if (limits[n].p2.x > boxes->limit.p2.x)
boxes->limit.p2.x = limits[n].p2.x;
if (limits[n].p2.y > boxes->limit.p2.y)
boxes->limit.p2.y = limits[n].p2.y;
}
}
}
static void
_cairo_boxes_add_internal (cairo_boxes_t *boxes,
const cairo_box_t *box)
{
struct _cairo_boxes_chunk *chunk;
if (unlikely (boxes->status))
return;
chunk = boxes->tail;
if (unlikely (chunk->count == chunk->size)) {
int size;
size = chunk->size * 2;
chunk->next = _cairo_malloc_ab_plus_c (size,
sizeof (cairo_box_t),
sizeof (struct _cairo_boxes_chunk));
if (unlikely (chunk->next == NULL)) {
boxes->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
return;
}
chunk = chunk->next;
boxes->tail = chunk;
chunk->next = NULL;
chunk->count = 0;
chunk->size = size;
chunk->base = (cairo_box_t *) (chunk + 1);
}
chunk->base[chunk->count++] = *box;
boxes->num_boxes++;
if (boxes->is_pixel_aligned) {
boxes->is_pixel_aligned =
_cairo_fixed_is_integer (box->p1.x) &&
_cairo_fixed_is_integer (box->p1.y) &&
_cairo_fixed_is_integer (box->p2.x) &&
_cairo_fixed_is_integer (box->p2.y);
}
}
cairo_status_t
_cairo_boxes_add (cairo_boxes_t *boxes,
const cairo_box_t *box)
{
if (box->p1.y == box->p2.y)
return CAIRO_STATUS_SUCCESS;
if (box->p1.x == box->p2.x)
return CAIRO_STATUS_SUCCESS;
if (boxes->num_limits) {
cairo_point_t p1, p2;
cairo_bool_t reversed = FALSE;
int n;
/* support counter-clockwise winding for rectangular tessellation */
if (box->p1.x < box->p2.x) {
p1.x = box->p1.x;
p2.x = box->p2.x;
} else {
p2.x = box->p1.x;
p1.x = box->p2.x;
reversed = ! reversed;
}
if (p1.x >= boxes->limit.p2.x || p2.x <= boxes->limit.p1.x)
return CAIRO_STATUS_SUCCESS;
if (box->p1.y < box->p2.y) {
p1.y = box->p1.y;
p2.y = box->p2.y;
} else {
p2.y = box->p1.y;
p1.y = box->p2.y;
reversed = ! reversed;
}
if (p1.y >= boxes->limit.p2.y || p2.y <= boxes->limit.p1.y)
return CAIRO_STATUS_SUCCESS;
for (n = 0; n < boxes->num_limits; n++) {
const cairo_box_t *limits = &boxes->limits[n];
cairo_box_t _box;
cairo_point_t _p1, _p2;
if (p1.x >= limits->p2.x || p2.x <= limits->p1.x)
continue;
if (p1.y >= limits->p2.y || p2.y <= limits->p1.y)
continue;
/* Otherwise, clip the box to the limits. */
_p1 = p1;
if (_p1.x < limits->p1.x)
_p1.x = limits->p1.x;
if (_p1.y < limits->p1.y)
_p1.y = limits->p1.y;
_p2 = p2;
if (_p2.x > limits->p2.x)
_p2.x = limits->p2.x;
if (_p2.y > limits->p2.y)
_p2.y = limits->p2.y;
if (_p2.y <= _p1.y || _p2.x <= _p1.x)
continue;
_box.p1.y = _p1.y;
_box.p2.y = _p2.y;
if (reversed) {
_box.p1.x = _p2.x;
_box.p2.x = _p1.x;
} else {
_box.p1.x = _p1.x;
_box.p2.x = _p2.x;
}
_cairo_boxes_add_internal (boxes, &_box);
}
} else {
_cairo_boxes_add_internal (boxes, box);
}
return boxes->status;
}
void
_cairo_boxes_extents (const cairo_boxes_t *boxes,
cairo_rectangle_int_t *extents)
{
const struct _cairo_boxes_chunk *chunk;
cairo_box_t box;
int i;
box.p1.y = box.p1.x = INT_MAX;
box.p2.y = box.p2.x = INT_MIN;
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
const cairo_box_t *b = chunk->base;
for (i = 0; i < chunk->count; i++) {
if (b[i].p1.x < box.p1.x)
box.p1.x = b[i].p1.x;
if (b[i].p1.y < box.p1.y)
box.p1.y = b[i].p1.y;
if (b[i].p2.x > box.p2.x)
box.p2.x = b[i].p2.x;
if (b[i].p2.y > box.p2.y)
box.p2.y = b[i].p2.y;
}
}
_cairo_box_round_to_rectangle (&box, extents);
}
void
_cairo_boxes_clear (cairo_boxes_t *boxes)
{
struct _cairo_boxes_chunk *chunk, *next;
for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) {
next = chunk->next;
free (chunk);
}
boxes->tail = &boxes->chunks;
boxes->chunks.next = 0;
boxes->chunks.count = 0;
boxes->num_boxes = 0;
boxes->is_pixel_aligned = TRUE;
}
void
_cairo_boxes_fini (cairo_boxes_t *boxes)
{
struct _cairo_boxes_chunk *chunk, *next;
for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) {
next = chunk->next;
free (chunk);
}
}

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -37,6 +37,7 @@
*/
#include "cairoint.h"
#include "cairo-error-private.h"
static void
_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
@ -174,9 +175,7 @@ _cairo_cache_thaw (cairo_cache_t *cache)
{
assert (cache->freeze_count > 0);
cache->freeze_count--;
if (cache->freeze_count == 0)
if (--cache->freeze_count == 0)
_cairo_cache_shrink_to_accommodate (cache, 0);
}
@ -240,9 +239,6 @@ static void
_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
unsigned long additional)
{
if (cache->freeze_count)
return;
while (cache->size + additional > cache->max_size) {
if (! _cairo_cache_remove_random (cache))
return;
@ -267,7 +263,8 @@ _cairo_cache_insert (cairo_cache_t *cache,
{
cairo_status_t status;
_cairo_cache_shrink_to_accommodate (cache, entry->size);
if (entry->size && ! cache->freeze_count)
_cairo_cache_shrink_to_accommodate (cache, entry->size);
status = _cairo_hash_table_insert (cache->hash_table,
(cairo_hash_entry_t *) entry);

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -41,6 +41,7 @@
#define _BSD_SOURCE /* for snprintf(), strdup() */
#include "cairoint.h"
#include "cairo-error-private.h"
#if CAIRO_HAS_FONT_SUBSET
@ -117,6 +118,7 @@ typedef struct _cairo_cff_font {
cairo_array_t local_sub_index;
int num_glyphs;
cairo_bool_t is_cid;
int units_per_em;
/* CID Font Data */
int *fdselect;
@ -1772,6 +1774,9 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font->y_max = (int16_t) be16_to_cpu (head.y_max);
font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
font->descent = (int16_t) be16_to_cpu (hhea.descender);
font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
if (font->units_per_em == 0)
font->units_per_em = 1000;
font->font_name = NULL;
status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
@ -1955,20 +1960,20 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
cff_subset->font_name = NULL;
}
cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
if (unlikely (cff_subset->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
cff_subset->widths[i] = font->widths[i];
cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em;
cff_subset->x_min = font->x_min;
cff_subset->y_min = font->y_min;
cff_subset->x_max = font->x_max;
cff_subset->y_max = font->y_max;
cff_subset->ascent = font->ascent;
cff_subset->descent = font->descent;
cff_subset->x_min = (double)font->x_min/font->units_per_em;
cff_subset->y_min = (double)font->y_min/font->units_per_em;
cff_subset->x_max = (double)font->x_max/font->units_per_em;
cff_subset->y_max = (double)font->y_max/font->units_per_em;
cff_subset->ascent = (double)font->ascent/font->units_per_em;
cff_subset->descent = (double)font->descent/font->units_per_em;
cff_subset->data = malloc (length);
if (unlikely (cff_subset->data == NULL)) {
@ -2212,21 +2217,21 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
goto fail2;
}
cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
if (unlikely (cff_subset->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
cff_subset->widths[i] = type2_subset.widths[i];
cff_subset->widths[i] = (double)type2_subset.widths[i]/1000;
cff_subset->x_min = type2_subset.x_min;
cff_subset->y_min = type2_subset.y_min;
cff_subset->x_max = type2_subset.x_max;
cff_subset->y_max = type2_subset.y_max;
cff_subset->ascent = type2_subset.y_max;
cff_subset->descent = type2_subset.y_min;
cff_subset->x_min = (double)type2_subset.x_min/1000;
cff_subset->y_min = (double)type2_subset.y_min/1000;
cff_subset->x_max = (double)type2_subset.x_max/1000;
cff_subset->y_max = (double)type2_subset.y_max/1000;
cff_subset->ascent = (double)type2_subset.y_max/1000;
cff_subset->descent = (double)type2_subset.y_min/1000;
cff_subset->data = malloc (length);
if (unlikely (cff_subset->data == NULL)) {

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -76,10 +76,6 @@ struct _cairo_clip {
cairo_private void
_cairo_clip_init (cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_clip_init_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rect);
cairo_private_no_warn cairo_clip_t *
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
@ -91,6 +87,10 @@ _cairo_clip_init_copy_transformed (cairo_clip_t *clip,
cairo_private void
_cairo_clip_reset (cairo_clip_t *clip);
cairo_private cairo_bool_t
_cairo_clip_equal (const cairo_clip_t *clip_a,
const cairo_clip_t *clip_b);
#define _cairo_clip_fini(clip) _cairo_clip_reset (clip)
cairo_private cairo_status_t
@ -112,12 +112,12 @@ cairo_private const cairo_rectangle_int_t *
_cairo_clip_get_extents (const cairo_clip_t *clip);
cairo_private cairo_surface_t *
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst);
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst, int *tx, int *ty);
cairo_private cairo_status_t
_cairo_clip_combine_with_surface (cairo_clip_t *clip,
cairo_surface_t *dst,
const cairo_rectangle_int_t *extents);
int dst_x, int dst_y);
cairo_private cairo_int_status_t
_cairo_clip_get_region (cairo_clip_t *clip,
@ -128,6 +128,20 @@ _cairo_clip_get_boxes (cairo_clip_t *clip,
cairo_box_t **boxes,
int *count);
cairo_private cairo_status_t
_cairo_clip_to_boxes (cairo_clip_t **clip,
cairo_composite_rectangles_t *extents,
cairo_box_t **boxes,
int *num_boxes);
cairo_private cairo_bool_t
_cairo_clip_contains_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rect);
cairo_private cairo_bool_t
_cairo_clip_contains_extents (cairo_clip_t *clip,
const cairo_composite_rectangles_t *extents);
cairo_private void
_cairo_clip_drop_cache (cairo_clip_t *clip);

View File

@ -15,7 +15,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -41,95 +41,16 @@
#include "cairoint.h"
#include "cairo-clip-private.h"
#include "cairo-error-private.h"
#include "cairo-freed-pool-private.h"
#include "cairo-gstate-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-region-private.h"
/* Keep a stash of recently freed clip_paths, since we need to
* reallocate them frequently.
*/
#define MAX_FREED_POOL_SIZE 4
typedef struct {
void *pool[MAX_FREED_POOL_SIZE];
int top;
} freed_pool_t;
#if HAS_FREED_POOL
static freed_pool_t clip_path_pool;
static void *
_atomic_fetch (void **slot)
{
return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL);
}
static cairo_bool_t
_atomic_store (void **slot, void *ptr)
{
return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr) == NULL;
}
static void *
_freed_pool_get (freed_pool_t *pool)
{
void *ptr;
int i;
i = pool->top - 1;
if (i < 0)
i = 0;
ptr = _atomic_fetch (&pool->pool[i]);
if (ptr != NULL) {
pool->top = i;
return ptr;
}
/* either empty or contended */
for (i = ARRAY_LENGTH (pool->pool); i--;) {
ptr = _atomic_fetch (&pool->pool[i]);
if (ptr != NULL) {
pool->top = i;
return ptr;
}
}
/* empty */
pool->top = 0;
return NULL;
}
static void
_freed_pool_put (freed_pool_t *pool, void *ptr)
{
int i = pool->top;
if (_atomic_store (&pool->pool[i], ptr)) {
pool->top = i + 1;
return;
}
/* either full or contended */
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
if (_atomic_store (&pool->pool[i], ptr)) {
pool->top = i + 1;
return;
}
}
/* full */
pool->top = ARRAY_LENGTH (pool->pool);
free (ptr);
}
static void
_freed_pool_reset (freed_pool_t *pool)
{
int i;
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
free (pool->pool[i]);
pool->pool[i] = NULL;
}
}
#endif
static cairo_clip_path_t *
_cairo_clip_path_create (cairo_clip_t *clip)
@ -158,9 +79,6 @@ _cairo_clip_path_create (cairo_clip_t *clip)
static cairo_clip_path_t *
_cairo_clip_path_reference (cairo_clip_path_t *clip_path)
{
if (clip_path == NULL)
return NULL;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
_cairo_reference_count_inc (&clip_path->ref_count);
@ -247,47 +165,40 @@ _cairo_clip_intersect_rectangle (cairo_clip_t *clip,
status = _cairo_path_fixed_close_path (&clip_path->path);
assert (status == CAIRO_STATUS_SUCCESS);
clip_path->extents = *rect;
clip_path->fill_rule = CAIRO_FILL_RULE_WINDING;
clip_path->tolerance = 1;
clip_path->antialias = CAIRO_ANTIALIAS_NONE;
clip_path->antialias = CAIRO_ANTIALIAS_DEFAULT;
clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
clip_path->extents = *rect;
if (clip_path->prev != NULL) {
if (! _cairo_rectangle_intersect (&clip_path->extents,
&clip_path->prev->extents))
{
_cairo_clip_set_all_clipped (clip);
}
}
/* could preallocate the region if it proves worthwhile */
return CAIRO_STATUS_SUCCESS;
}
/* XXX consider accepting a matrix, no users yet. */
cairo_status_t
_cairo_clip_init_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rect)
{
_cairo_clip_init (clip);
if (rect == NULL)
return CAIRO_STATUS_SUCCESS;
if (rect->width == 0 || rect->height == 0) {
_cairo_clip_set_all_clipped (clip);
return CAIRO_STATUS_SUCCESS;
}
return _cairo_clip_intersect_rectangle (clip, rect);
}
cairo_clip_t *
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
{
if (other != NULL) {
clip->all_clipped = other->all_clipped;
clip->path = _cairo_clip_path_reference (other->path);
/* this guy is here because of the weird return semantics of _cairo_clip_init_copy */
if (!other->path)
return NULL;
if (other->path == NULL) {
clip->path = NULL;
if (! clip->all_clipped)
clip = NULL;
} else {
clip->path = _cairo_clip_path_reference (other->path);
}
} else {
_cairo_clip_init (clip);
clip = NULL;
}
return clip;
@ -318,9 +229,8 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
if (clip->path != NULL) {
if (clip->path->fill_rule == fill_rule &&
(path->is_rectilinear ||
(tolerance == clip->path->tolerance &&
antialias == clip->path->antialias)) &&
(path->is_rectilinear || tolerance == clip->path->tolerance) &&
antialias == clip->path->antialias &&
_cairo_path_fixed_equal (&clip->path->path, path))
{
return CAIRO_STATUS_SUCCESS;
@ -372,6 +282,38 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
}
cairo_bool_t
_cairo_clip_equal (const cairo_clip_t *clip_a,
const cairo_clip_t *clip_b)
{
const cairo_clip_path_t *clip_path_a, *clip_path_b;
clip_path_a = clip_a->path;
clip_path_b = clip_b->path;
while (clip_path_a && clip_path_b) {
if (clip_path_a == clip_path_b)
return TRUE;
if (clip_path_a->fill_rule != clip_path_b->fill_rule)
return FALSE;
if (clip_path_a->tolerance != clip_path_b->tolerance)
return FALSE;
if (clip_path_a->antialias != clip_path_b->antialias)
return FALSE;
if (! _cairo_path_fixed_equal (&clip_path_a->path, &clip_path_b->path))
return FALSE;
clip_path_a = clip_path_a->prev;
clip_path_b = clip_path_b->prev;
}
return clip_path_a == clip_path_b; /* ie both NULL */
}
cairo_status_t
_cairo_clip_clip (cairo_clip_t *clip,
const cairo_path_fixed_t *path,
@ -409,7 +351,7 @@ _cairo_clip_rectangle (cairo_clip_t *clip,
if (clip->path != NULL) {
if (rectangle->x <= clip->path->extents.x &&
rectangle->y <= clip->path->extents.y &&
rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
rectangle->y + rectangle->height >= clip->path->extents.y + clip->path->extents.height)
{
return CAIRO_STATUS_SUCCESS;
@ -443,6 +385,7 @@ _cairo_clip_path_reapply_clip_path_transform (cairo_clip_t *clip,
status = _cairo_path_fixed_init_copy (&clip_path->path,
&other_path->path);
if (unlikely (status)) {
clip->path = clip->path->prev;
_cairo_clip_path_destroy (clip_path);
return status;
}
@ -485,6 +428,7 @@ _cairo_clip_path_reapply_clip_path_translate (cairo_clip_t *clip,
status = _cairo_path_fixed_init_copy (&clip_path->path,
&other_path->path);
if (unlikely (status)) {
clip->path = clip->path->prev;
_cairo_clip_path_destroy (clip_path);
return status;
}
@ -500,6 +444,13 @@ _cairo_clip_path_reapply_clip_path_translate (cairo_clip_t *clip,
clip_path->flags = other_path->flags;
if (other_path->region != NULL) {
clip_path->region = cairo_region_copy (other_path->region);
status = clip_path->region->status;
if (unlikely (status)) {
clip->path = clip->path->prev;
_cairo_clip_path_destroy (clip_path);
return status;
}
cairo_region_translate (clip_path->region, tx, ty);
}
clip_path->surface = cairo_surface_reference (other_path->surface);
@ -997,104 +948,73 @@ _cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_combine_region (cairo_surface_t *surface,
const cairo_region_t *region,
const cairo_rectangle_int_t *extents)
{
cairo_region_t clear_region;
cairo_status_t status;
_cairo_region_init_rectangle (&clear_region, extents);
status = cairo_region_subtract (&clear_region, region);
if (unlikely (status))
return status;
if (! cairo_region_is_empty (&clear_region)) {
cairo_region_translate (&clear_region, -extents->x, -extents->y);
status = _cairo_surface_fill_region (surface,
CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
&clear_region);
}
_cairo_region_fini (&clear_region);
return status;
}
static cairo_surface_t *
_cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
cairo_surface_t *target)
cairo_surface_t *target,
int *tx, int *ty)
{
cairo_surface_t *surface;
cairo_pattern_union_t pattern;
cairo_status_t status;
const cairo_rectangle_int_t *clip_extents = &clip_path->extents;
cairo_clip_path_t *prev;
cairo_bool_t need_translate;
cairo_surface_t *surface;
cairo_clip_path_t *prev;
cairo_status_t status;
while (clip_path->prev != NULL &&
clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
clip_path->path.maybe_fill_region)
{
clip_path = clip_path->prev;
}
clip_extents = &clip_path->extents;
if (clip_path->surface != NULL &&
clip_path->surface->backend == target->backend)
{
return cairo_surface_reference (clip_path->surface);
*tx = clip_extents->x;
*ty = clip_extents->y;
return clip_path->surface;
}
surface = _cairo_surface_create_similar_solid (target,
CAIRO_CONTENT_ALPHA,
clip_extents->width,
clip_extents->height,
CAIRO_COLOR_TRANSPARENT,
FALSE);
surface = _cairo_surface_create_similar_scratch (target,
CAIRO_CONTENT_ALPHA,
clip_extents->width,
clip_extents->height);
if (surface == NULL) {
if (clip_path->surface != NULL &&
clip_path->surface->backend == &_cairo_image_surface_backend)
{
return cairo_surface_reference (clip_path->surface);
}
surface =
_cairo_image_surface_create_with_content (CAIRO_CONTENT_ALPHA,
clip_extents->width,
clip_extents->height);
surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
clip_extents->width,
clip_extents->height);
}
if (unlikely (surface->status))
return surface;
_cairo_pattern_init_solid (&pattern.solid,
CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
status = _cairo_clip_path_to_region (clip_path);
if (unlikely (_cairo_status_is_error (status)))
goto BAIL;
need_translate = clip_extents->x | clip_extents->y;
if (status == CAIRO_STATUS_SUCCESS) {
if (need_translate) {
cairo_region_translate (clip_path->region,
-clip_extents->x, -clip_extents->y);
}
status = _cairo_surface_fill_region (surface,
CAIRO_OPERATOR_SOURCE,
CAIRO_COLOR_WHITE,
clip_path->region);
if (need_translate) {
cairo_region_translate (clip_path->region,
clip_extents->x, clip_extents->y);
}
if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
clip_path->path.maybe_fill_region)
{
status = _cairo_surface_paint (surface,
CAIRO_OPERATOR_SOURCE,
&_cairo_pattern_white.base,
NULL);
if (unlikely (status))
goto BAIL;
}
else
{
status = _cairo_surface_paint (surface,
CAIRO_OPERATOR_CLEAR,
&_cairo_pattern_clear.base,
NULL);
if (unlikely (status))
goto BAIL;
goto DONE;
} else {
if (need_translate) {
_cairo_path_fixed_translate (&clip_path->path,
_cairo_fixed_from_int (-clip_extents->x),
_cairo_fixed_from_int (-clip_extents->y));
}
status = _cairo_surface_fill (surface,
CAIRO_OPERATOR_OVER,
&pattern.base,
CAIRO_OPERATOR_ADD,
&_cairo_pattern_white.base,
&clip_path->path,
clip_path->fill_rule,
clip_path->tolerance,
@ -1111,19 +1031,16 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
}
prev = clip_path->prev;
NEXT_PATH:
if (prev != NULL) {
status = _cairo_clip_path_to_region (prev);
if (unlikely (_cairo_status_is_error (status)))
goto BAIL;
if (status == CAIRO_STATUS_SUCCESS) {
status = _combine_region (surface, prev->region, clip_extents);
if (unlikely (status))
goto BAIL;
} else if (prev->flags & CAIRO_CLIP_PATH_IS_BOX) {
while (prev != NULL) {
if (prev->flags & CAIRO_CLIP_PATH_IS_BOX &&
prev->path.maybe_fill_region)
{
/* a simple box only affects the extents */
} else if (prev->path.is_rectilinear) {
}
else if (prev->path.is_rectilinear ||
prev->surface == NULL ||
prev->surface->backend != target->backend)
{
if (need_translate) {
_cairo_path_fixed_translate (&prev->path,
_cairo_fixed_from_int (-clip_extents->x),
@ -1131,7 +1048,7 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
}
status = _cairo_surface_fill (surface,
CAIRO_OPERATOR_IN,
&pattern.base,
&_cairo_pattern_white.base,
&prev->path,
prev->fill_rule,
prev->tolerance,
@ -1145,19 +1062,23 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
if (unlikely (status))
goto BAIL;
prev = prev->prev;
goto NEXT_PATH;
} else {
}
else
{
cairo_surface_pattern_t pattern;
cairo_surface_t *prev_surface;
int prev_tx, prev_ty;
prev_surface = _cairo_clip_path_get_surface (prev, target);
_cairo_pattern_init_for_surface (&pattern.surface, prev_surface);
cairo_surface_destroy (prev_surface);
prev_surface = _cairo_clip_path_get_surface (prev, target, &prev_tx, &prev_ty);
status = prev_surface->status;
if (unlikely (status))
goto BAIL;
_cairo_pattern_init_for_surface (&pattern, prev_surface);
pattern.base.filter = CAIRO_FILTER_NEAREST;
cairo_matrix_init_translate (&pattern.base.matrix,
-prev->extents.x + clip_extents->x,
-prev->extents.y + clip_extents->y);
clip_extents->x - prev_tx,
clip_extents->y - prev_ty);
status = _cairo_surface_paint (surface,
CAIRO_OPERATOR_IN,
&pattern.base,
@ -1166,18 +1087,75 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
if (unlikely (status))
goto BAIL;
break;
}
prev = prev->prev;
}
DONE:
*tx = clip_extents->x;
*ty = clip_extents->y;
cairo_surface_destroy (clip_path->surface);
return clip_path->surface = cairo_surface_reference (surface);
return clip_path->surface = surface;
BAIL:
cairo_surface_destroy (surface);
return _cairo_surface_create_in_error (status);
}
cairo_bool_t
_cairo_clip_contains_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rect)
{
cairo_clip_path_t *clip_path;
if (clip == NULL)
return FALSE;
clip_path = clip->path;
if (clip_path->extents.x > rect->x ||
clip_path->extents.y > rect->y ||
clip_path->extents.x + clip_path->extents.width < rect->x + rect->width ||
clip_path->extents.y + clip_path->extents.height < rect->y + rect->height)
{
return FALSE;
}
do {
cairo_box_t box;
if ((clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) == 0)
return FALSE;
if (! _cairo_path_fixed_is_box (&clip_path->path, &box))
return FALSE;
if (box.p1.x > _cairo_fixed_from_int (rect->x) ||
box.p1.y > _cairo_fixed_from_int (rect->y) ||
box.p2.x < _cairo_fixed_from_int (rect->x + rect->width) ||
box.p2.y < _cairo_fixed_from_int (rect->y + rect->height))
{
return FALSE;
}
} while ((clip_path = clip_path->prev) != NULL);
return TRUE;
}
cairo_bool_t
_cairo_clip_contains_extents (cairo_clip_t *clip,
const cairo_composite_rectangles_t *extents)
{
const cairo_rectangle_int_t *rect;
if (clip == NULL)
return FALSE;
rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
return _cairo_clip_contains_rectangle (clip, rect);
}
void
_cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
{
@ -1202,72 +1180,48 @@ _cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
clip_path = clip->path;
do {
fprintf (stream, "path: has region? %s, has surface? %s: ",
fprintf (stream, "path: has region? %s, has surface? %s, aa=%d, tolerance=%f, rule=%d: ",
clip_path->region == NULL ? "no" : "yes",
clip_path->surface == NULL ? "no" : "yes");
clip_path->surface == NULL ? "no" : "yes",
clip_path->antialias,
clip_path->tolerance,
clip_path->fill_rule);
_cairo_debug_print_path (stream, &clip_path->path);
fprintf (stream, "\n");
} while ((clip_path = clip_path->prev) != NULL);
}
cairo_surface_t *
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target)
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target, int *tx, int *ty)
{
/* XXX is_clear -> all_clipped */
assert (clip->path != NULL);
return _cairo_clip_path_get_surface (clip->path, target);
return _cairo_clip_path_get_surface (clip->path, target, tx, ty);
}
cairo_status_t
_cairo_clip_combine_with_surface (cairo_clip_t *clip,
cairo_surface_t *dst,
const cairo_rectangle_int_t *extents)
int dst_x, int dst_y)
{
cairo_pattern_union_t pattern;
cairo_clip_path_t *clip_path = clip->path;
cairo_bool_t need_translate;
cairo_status_t status;
assert (clip_path != NULL);
if (clip_path->surface != NULL &&
clip_path->surface->backend == dst->backend)
{
_cairo_pattern_init_for_surface (&pattern.surface,
clip_path->surface);
cairo_matrix_init_translate (&pattern.base.matrix,
extents->x - clip_path->extents.x,
extents->y - clip_path->extents.y);
status = _cairo_surface_paint (dst,
CAIRO_OPERATOR_IN,
&pattern.base,
NULL);
_cairo_pattern_fini (&pattern.base);
return status;
}
_cairo_pattern_init_solid (&pattern.solid,
CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
need_translate = extents->x | extents->y;
need_translate = dst_x | dst_y;
do {
status = _cairo_clip_path_to_region (clip_path);
if (unlikely (_cairo_status_is_error (status)))
return status;
if (status == CAIRO_STATUS_SUCCESS)
return _combine_region (dst, clip_path->region, extents);
if (clip_path->surface != NULL &&
clip_path->surface->backend == dst->backend)
{
_cairo_pattern_init_for_surface (&pattern.surface,
clip_path->surface);
cairo_surface_pattern_t pattern;
_cairo_pattern_init_for_surface (&pattern, clip_path->surface);
cairo_matrix_init_translate (&pattern.base.matrix,
extents->x - clip_path->extents.x,
extents->y - clip_path->extents.y);
dst_x - clip_path->extents.x,
dst_y - clip_path->extents.y);
pattern.base.filter = CAIRO_FILTER_NEAREST;
status = _cairo_surface_paint (dst,
CAIRO_OPERATOR_IN,
&pattern.base,
@ -1278,30 +1232,29 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
return status;
}
if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) {
cairo_region_t clip_region;
if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
clip_path->path.maybe_fill_region)
{
continue;
}
_cairo_region_init_rectangle (&clip_region, &clip_path->extents);
status = _combine_region (dst, &clip_region, extents);
} else {
if (need_translate) {
_cairo_path_fixed_translate (&clip_path->path,
_cairo_fixed_from_int (-extents->x),
_cairo_fixed_from_int (-extents->y));
}
status = _cairo_surface_fill (dst,
CAIRO_OPERATOR_IN,
&pattern.base,
&clip_path->path,
clip_path->fill_rule,
clip_path->tolerance,
clip_path->antialias,
NULL);
if (need_translate) {
_cairo_path_fixed_translate (&clip_path->path,
_cairo_fixed_from_int (extents->x),
_cairo_fixed_from_int (extents->y));
}
if (need_translate) {
_cairo_path_fixed_translate (&clip_path->path,
_cairo_fixed_from_int (-dst_x),
_cairo_fixed_from_int (-dst_y));
}
status = _cairo_surface_fill (dst,
CAIRO_OPERATOR_IN,
&_cairo_pattern_white.base,
&clip_path->path,
clip_path->fill_rule,
clip_path->tolerance,
clip_path->antialias,
NULL);
if (need_translate) {
_cairo_path_fixed_translate (&clip_path->path,
_cairo_fixed_from_int (dst_x),
_cairo_fixed_from_int (dst_y));
}
if (unlikely (status))
@ -1432,6 +1385,90 @@ _cairo_clip_get_boxes (cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
box_is_aligned (const cairo_box_t *box)
{
return
_cairo_fixed_is_integer (box->p1.x) &&
_cairo_fixed_is_integer (box->p1.y) &&
_cairo_fixed_is_integer (box->p2.x) &&
_cairo_fixed_is_integer (box->p2.y);
}
static void
intersect_with_boxes (cairo_composite_rectangles_t *extents,
cairo_box_t *boxes,
int num_boxes)
{
cairo_rectangle_int_t rect;
cairo_box_t box;
cairo_bool_t is_empty;
box.p1.x = box.p1.y = INT_MIN;
box.p2.x = box.p2.y = INT_MAX;
while (num_boxes--) {
if (boxes->p1.x < box.p1.x)
box.p1.x = boxes->p1.x;
if (boxes->p1.y < box.p1.y)
box.p1.y = boxes->p1.y;
if (boxes->p2.x > box.p2.x)
box.p2.x = boxes->p2.x;
if (boxes->p2.y > box.p2.y)
box.p2.y = boxes->p2.y;
}
_cairo_box_round_to_rectangle (&box, &rect);
is_empty = _cairo_rectangle_intersect (&extents->bounded, &rect);
is_empty = _cairo_rectangle_intersect (&extents->unbounded, &rect);
}
cairo_status_t
_cairo_clip_to_boxes (cairo_clip_t **clip,
cairo_composite_rectangles_t *extents,
cairo_box_t **boxes,
int *num_boxes)
{
cairo_status_t status;
const cairo_rectangle_int_t *rect;
rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
if (*clip == NULL)
goto EXTENTS;
status = _cairo_clip_rectangle (*clip, rect);
if (unlikely (status))
return status;
status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
switch ((int) status) {
case CAIRO_STATUS_SUCCESS:
intersect_with_boxes (extents, *boxes, *num_boxes);
if (rect->width == 0 || rect->height == 0 ||
extents->is_bounded ||
(*num_boxes == 1 && box_is_aligned (*boxes)))
{
*clip = NULL;
}
goto DONE;
case CAIRO_INT_STATUS_UNSUPPORTED:
goto EXTENTS;
default:
return status;
}
EXTENTS:
status = CAIRO_STATUS_SUCCESS;
_cairo_box_from_rectangle (&(*boxes)[0], rect);
*num_boxes = 1;
DONE:
return status;
}
static cairo_rectangle_list_t *
_cairo_rectangle_list_create_in_error (cairo_status_t status)
{

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -67,13 +67,14 @@ _cairo_stock_color (cairo_stock_t stock)
return &cairo_color_black;
case CAIRO_STOCK_TRANSPARENT:
return &cairo_color_transparent;
case CAIRO_STOCK_NUM_COLORS:
default:
ASSERT_NOT_REACHED;
/* If the user can get here somehow, give a color that indicates a
* problem. */
return &cairo_color_magenta;
}
ASSERT_NOT_REACHED;
/* If the user can get here somehow, give a color that indicates a
* problem. */
return &cairo_color_magenta;
}
void
@ -161,6 +162,7 @@ _cairo_color_get_rgba_premultiplied (cairo_color_t *color,
*alpha = color->alpha;
}
/* NB: This function works both for unmultiplied and premultiplied colors */
cairo_bool_t
_cairo_color_equal (const cairo_color_t *color_a,
const cairo_color_t *color_b)
@ -168,8 +170,42 @@ _cairo_color_equal (const cairo_color_t *color_a,
if (color_a == color_b)
return TRUE;
if (color_a->alpha_short != color_b->alpha_short)
return FALSE;
if (color_a->alpha_short == 0)
return TRUE;
return color_a->red_short == color_b->red_short &&
color_a->green_short == color_b->green_short &&
color_a->blue_short == color_b->blue_short &&
color_a->alpha_short == color_b->alpha_short;
color_a->blue_short == color_b->blue_short;
}
cairo_bool_t
_cairo_color_stop_equal (const cairo_color_stop_t *color_a,
const cairo_color_stop_t *color_b)
{
if (color_a == color_b)
return TRUE;
return color_a->alpha_short == color_b->alpha_short &&
color_a->red_short == color_b->red_short &&
color_a->green_short == color_b->green_short &&
color_a->blue_short == color_b->blue_short;
}
cairo_content_t
_cairo_color_get_content (const cairo_color_t *color)
{
if (CAIRO_COLOR_IS_OPAQUE (color))
return CAIRO_CONTENT_COLOR;
if (color->red_short == 0 &&
color->green_short == 0 &&
color->blue_short == 0)
{
return CAIRO_CONTENT_ALPHA;
}
return CAIRO_CONTENT_COLOR_ALPHA;
}

View File

@ -11,7 +11,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -44,6 +44,45 @@
#include "config.h"
#endif
/* Size in bytes of buffer to use off the stack per functions.
* Mostly used by text functions. For larger allocations, they'll
* malloc(). */
#ifndef CAIRO_STACK_BUFFER_SIZE
#define CAIRO_STACK_BUFFER_SIZE (512 * sizeof (int))
#endif
#define CAIRO_STACK_ARRAY_LENGTH(T) (CAIRO_STACK_BUFFER_SIZE / sizeof(T))
/*
* The goal of this block is to define the following macros for
* providing faster linkage to functions in the public API for calls
* from within cairo.
*
* slim_hidden_proto(f)
* slim_hidden_proto_no_warn(f)
*
* Declares `f' as a library internal function and hides the
* function from the global symbol table. This macro must be
* expanded after `f' has been declared with a prototype but before
* any calls to the function are seen by the compiler. The no_warn
* variant inhibits warnings about the return value being unused at
* call sites. The macro works by renaming `f' to an internal name
* in the symbol table and hiding that. As far as cairo internal
* calls are concerned they're calling a library internal function
* and thus don't need to bounce via the PLT.
*
* slim_hidden_def(f)
*
* Exports `f' back to the global symbol table. This macro must be
* expanded right after the function definition and only for symbols
* hidden previously with slim_hidden_proto(). The macro works by
* adding a global entry to the symbol table which points at the
* internal name of `f' created by slim_hidden_proto().
*
* Functions in the public API which aren't called by the library
* don't need to be hidden and re-exported using the slim hidden
* macros.
*/
#if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun)
# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private
# define slim_hidden_proto_no_warn(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private_no_warn
@ -134,9 +173,11 @@
#if __GNUC__ >= 3
#define cairo_pure __attribute__((pure))
#define cairo_const __attribute__((const))
#define cairo_always_inline inline __attribute__((always_inline))
#else
#define cairo_pure
#define cairo_const
#define cairo_always_inline inline
#endif
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
@ -171,6 +212,26 @@
#ifdef _MSC_VER
#undef inline
#define inline __inline
/* there are currently linkage problems that arise when trying to include intrin.h in c++:
* D:\sdks\v7.0\include\winnt.h(3674) : error C2733: second C linkage of overloaded function '_interlockedbittestandset' not allowed
* so avoid defining ffs in c++ code for now */
#ifndef __cplusplus
/* Add a definition of ffs */
#include <intrin.h>
#pragma intrinsic(_BitScanForward)
static __forceinline int
ffs (int x)
{
unsigned long i;
if (_BitScanForward(&i, x) != 0)
return i + 1;
return 0;
}
#endif
#endif
#if defined(_MSC_VER) && defined(_M_IX86)

View File

@ -0,0 +1,105 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.u>
*/
#ifndef CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H
#define CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H
#include "cairo-types-private.h"
CAIRO_BEGIN_DECLS
/* Rectangles that take part in a composite operation.
*
* The source and mask track the extents of the respective patterns in device
* space. The unbounded rectangle is essentially the clip rectangle. And the
* intersection of all is the bounded rectangle, which is the minimum extents
* the operation may require. Whether or not the operation is actually bounded
* is tracked in the is_bounded boolean.
*
*/
struct _cairo_composite_rectangles {
cairo_rectangle_int_t source;
cairo_rectangle_int_t mask;
cairo_rectangle_int_t bounded; /* dst */
cairo_rectangle_int_t unbounded; /* clip */
uint32_t is_bounded;
};
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_clip_t *clip,
cairo_bool_t *overlap);
#endif /* CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H */

View File

@ -0,0 +1,195 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-composite-rectangles-private.h"
/* A collection of routines to facilitate writing compositors. */
static inline cairo_bool_t
_cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_clip_t *clip)
{
extents->unbounded = *surface_extents;
if (clip != NULL) {
const cairo_rectangle_int_t *clip_extents;
clip_extents = _cairo_clip_get_extents (clip);
if (clip_extents == NULL)
return FALSE;
if (! _cairo_rectangle_intersect (&extents->unbounded, clip_extents))
return FALSE;
}
extents->bounded = extents->unbounded;
extents->is_bounded = _cairo_operator_bounded_by_either (op);
_cairo_pattern_get_extents (source, &extents->source);
if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) {
if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source))
return FALSE;
}
return TRUE;
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
extents->mask = extents->bounded;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents)
{
cairo_bool_t ret;
ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
return CAIRO_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
_cairo_pattern_get_extents (mask, &extents->mask);
return _cairo_composite_rectangles_intersect (extents);
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
_cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &extents->mask);
return _cairo_composite_rectangles_intersect (extents);
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
_cairo_path_fixed_approximate_fill_extents (path, &extents->mask);
return _cairo_composite_rectangles_intersect (extents);
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_clip_t *clip,
cairo_bool_t *overlap)
{
cairo_status_t status;
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs, num_glyphs,
&extents->mask,
overlap);
if (unlikely (status))
return status;
return _cairo_composite_rectangles_intersect (extents);
}

View File

@ -43,10 +43,8 @@
#include <d3d10.h>
#include <dxgi.h>
extern "C" {
#include "cairoint.h"
#include "cairo-surface-clipper-private.h"
}
#include "cairo-win32-refptr.h"
#include "cairo-d2d-private-fx.h"

View File

@ -39,10 +39,9 @@
#include "cairo-d2d-private.h"
#include "cairo-dwrite-private.h"
extern "C" {
#include "cairo-win32.h"
#include "cairo-analysis-surface-private.h"
}
#include "cairo-error-private.h"
// Required for using placement new.
#include <new>
@ -649,9 +648,9 @@ _cairo_d2d_stroke(void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
cairo_clip_t *clip);
@ -763,6 +762,16 @@ _cairo_d2d_compute_surface_mem_size(cairo_d2d_surface_t *surface)
return size;
}
static D2D1_COLOR_F
_cairo_d2d_color_from_cairo_color_stop(const cairo_color_stop_t &color)
{
return D2D1::ColorF((FLOAT)color.red,
(FLOAT)color.green,
(FLOAT)color.blue,
(FLOAT)color.alpha);
}
/**
* Gets the surface buffer texture for window surfaces whose backbuffer
* is not directly usable as a bitmap.
@ -1435,7 +1444,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
stops[i].position = (FLOAT)((repeat + source_pattern->base.stops[stop].offset) * stop_scale);
}
stops[i].color =
_cairo_d2d_color_from_cairo_color(source_pattern->base.stops[stop].color);
_cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[stop].color);
}
} else {
// Simple case, we don't need to reflect.
@ -1445,7 +1454,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
// Calculate which stop this would be in the original pattern
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i % source_pattern->base.n_stops];
stops[i].position = (FLOAT)((repeat + stop->offset) * stop_scale);
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
}
}
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_PAD) {
@ -1458,7 +1467,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
for (unsigned int i = 0; i < source_pattern->base.n_stops; i++) {
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i];
stops[i].position = (FLOAT)(global_offset + stop->offset * offset_factor);
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
}
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_NONE) {
float offset_factor = (outer_radius - inner_radius) / outer_radius;
@ -1482,7 +1491,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
for (unsigned int j = 0; j < source_pattern->base.n_stops; j++, i++) {
cairo_gradient_stop_t *stop = &source_pattern->base.stops[j];
stops[i].position = (FLOAT)(global_offset + stop->offset * offset_factor);
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
}
stops[i].position = 1.0f;
stops[i].color = D2D1::ColorF(0, 0);
@ -1514,7 +1523,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
// Cairo behavior in this situation is to draw a solid color the size of the last stop.
RefPtr<ID2D1SolidColorBrush> brush;
d2dsurf->rt->CreateSolidColorBrush(
_cairo_d2d_color_from_cairo_color(source_pattern->base.stops[source_pattern->base.n_stops - 1].color),
_cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[source_pattern->base.n_stops - 1].color),
&brush);
return brush;
}
@ -1619,7 +1628,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
stops[i].position = (FLOAT)((repeat + source_pattern->base.stops[stop].offset) * stop_scale);
}
stops[i].color =
_cairo_d2d_color_from_cairo_color(source_pattern->base.stops[stop].color);
_cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[stop].color);
}
} else {
// Simple case, we don't need to reflect.
@ -1629,7 +1638,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
// Calculate which stop this would be in the original pattern
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i % source_pattern->base.n_stops];
stops[i].position = (FLOAT)((repeat + stop->offset) * stop_scale);
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
}
}
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_PAD) {
@ -1637,7 +1646,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
for (unsigned int i = 0; i < source_pattern->base.n_stops; i++) {
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i];
stops[i].position = (FLOAT)stop->offset;
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
}
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_NONE) {
num_stops += 2;
@ -1647,7 +1656,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
for (unsigned int i = 1; i < source_pattern->base.n_stops + 1; i++) {
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i - 1];
stops[i].position = (FLOAT)stop->offset;
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
}
stops[source_pattern->base.n_stops + 1].position = 1.0f;
stops[source_pattern->base.n_stops + 1].color = D2D1::ColorF(0, 0);
@ -2309,6 +2318,16 @@ static cairo_operator_t _cairo_d2d_simplify_operator(cairo_operator_t op,
return op;
}
void
_cairo_d2d_surface_init(cairo_d2d_surface_t *newSurf, cairo_d2d_device_t *d2d_device, cairo_format_t format)
{
newSurf->format = format;
newSurf->device = d2d_device;
cairo_addref_device(&d2d_device->base);
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
}
// Implementation
static cairo_surface_t*
_cairo_d2d_create_similar(void *surface,
@ -2320,7 +2339,7 @@ _cairo_d2d_create_similar(void *surface,
cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
new (newSurf) cairo_d2d_surface_t();
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
D2D1_SIZE_U sizePixels;
@ -2425,9 +2444,7 @@ _cairo_d2d_create_similar(void *surface,
_d2d_clear_surface(newSurf);
newSurf->device = d2dsurf->device;
cairo_addref_device(&newSurf->device->base);
newSurf->device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
_cairo_d2d_surface_init(newSurf, d2dsurf->device, _cairo_format_from_content(content));
return reinterpret_cast<cairo_surface_t*>(newSurf);
@ -2501,8 +2518,8 @@ _cairo_d2d_acquire_source_image(void *abstract_surface,
return _cairo_error(CAIRO_STATUS_NO_DEVICE);
}
*image_out =
(cairo_image_surface_t*)_cairo_image_surface_create_for_data_with_content((unsigned char*)data.pData,
d2dsurf->base.content,
(cairo_image_surface_t*)cairo_image_surface_create_for_data((unsigned char*)data.pData,
d2dsurf->format,
size.width,
size.height,
data.RowPitch);
@ -2573,8 +2590,8 @@ _cairo_d2d_acquire_dest_image(void *abstract_surface,
return _cairo_error(CAIRO_STATUS_NO_DEVICE);
}
*image_out =
(cairo_image_surface_t*)_cairo_image_surface_create_for_data_with_content((unsigned char*)data.pData,
d2dsurf->base.content,
(cairo_image_surface_t*)cairo_image_surface_create_for_data((unsigned char*)data.pData,
_cairo_format_from_content(d2dsurf->base.content),
size.width,
size.height,
data.RowPitch);
@ -3178,7 +3195,7 @@ _cairo_d2d_mask(void *surface,
if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
cairo_solid_pattern_t *solidPattern =
(cairo_solid_pattern_t*)mask;
if (solidPattern->content = CAIRO_CONTENT_ALPHA) {
if (_cairo_color_get_content (&solidPattern->color) == CAIRO_CONTENT_ALPHA) {
isSolidAlphaMask = true;
solidAlphaValue = solidPattern->color.alpha;
}
@ -3321,9 +3338,9 @@ _cairo_d2d_stroke(void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
cairo_clip_t *clip)
@ -3526,7 +3543,12 @@ _cairo_d2d_fill(void *surface,
if (target_rt.get() != d2dsurf->rt.get()) {
double x1, y1, x2, y2;
_cairo_path_fixed_bounds(path, &x1, &y1, &x2, &y2);
cairo_box_t box;
_cairo_path_fixed_extents (path, &box);
x1 = _cairo_fixed_to_double (box.p1.x);
y1 = _cairo_fixed_to_double (box.p1.y);
x2 = _cairo_fixed_to_double (box.p2.x);
y2 = _cairo_fixed_to_double (box.p2.y);
cairo_rectangle_int_t bounds;
_cairo_d2d_round_out_to_int_rect(&bounds, x1, y1, x2, y2);
return _cairo_d2d_blend_temp_surface(d2dsurf, op, target_rt, clip, &bounds);
@ -4118,6 +4140,8 @@ _cairo_d2d_getextents(void *surface,
/** Helper functions. */
cairo_surface_t*
cairo_d2d_surface_create_for_hwnd(cairo_device_t *cairo_device,
HWND wnd,
@ -4127,7 +4151,7 @@ cairo_d2d_surface_create_for_hwnd(cairo_device_t *cairo_device,
cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
new (newSurf) cairo_d2d_surface_t();
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
RECT rc;
HRESULT hr;
@ -4229,9 +4253,7 @@ cairo_d2d_surface_create_for_hwnd(cairo_device_t *cairo_device,
_d2d_clear_surface(newSurf);
newSurf->device = d2d_device;
cairo_addref_device(cairo_device);
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
_cairo_d2d_surface_init(newSurf, d2d_device, _cairo_format_from_content(content));
return reinterpret_cast<cairo_surface_t*>(newSurf);
@ -4241,6 +4263,8 @@ FAIL_HWND:
return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
}
cairo_surface_t *
cairo_d2d_surface_create(cairo_device_t *device,
cairo_format_t format,
@ -4258,12 +4282,12 @@ cairo_d2d_surface_create(cairo_device_t *device,
DXGI_FORMAT dxgiformat = DXGI_FORMAT_B8G8R8A8_UNORM;
D2D1_ALPHA_MODE alpha = D2D1_ALPHA_MODE_PREMULTIPLIED;
if (format == CAIRO_FORMAT_ARGB32) {
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR_ALPHA);
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_COLOR_ALPHA);
} else if (format == CAIRO_FORMAT_RGB24) {
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR);
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_COLOR);
alpha = D2D1_ALPHA_MODE_IGNORE;
} else {
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_ALPHA);
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_ALPHA);
dxgiformat = DXGI_FORMAT_A8_UNORM;
}
@ -4343,9 +4367,7 @@ cairo_d2d_surface_create(cairo_device_t *device,
_d2d_clear_surface(newSurf);
newSurf->device = d2d_device;
cairo_addref_device(device);
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
_cairo_d2d_surface_init(newSurf, d2d_device, format);
return reinterpret_cast<cairo_surface_t*>(newSurf);
@ -4398,7 +4420,7 @@ cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo
status = CAIRO_STATUS_INVALID_CONTENT;
goto FAIL_CREATEHANDLE;
}
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
if (content == CAIRO_CONTENT_COLOR) {
alpha = D2D1_ALPHA_MODE_IGNORE;
}
@ -4407,7 +4429,7 @@ cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo
status = CAIRO_STATUS_INVALID_CONTENT;
goto FAIL_CREATEHANDLE;
}
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_ALPHA);
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_ALPHA);
} else {
status = CAIRO_STATUS_INVALID_FORMAT;
// We don't know how to support this format!
@ -4444,9 +4466,7 @@ cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo
newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
newSurf->device = d2d_device;
cairo_addref_device(device);
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
_cairo_d2d_surface_init(newSurf, d2d_device, _cairo_format_from_content(content));
return &newSurf->base;
@ -4467,10 +4487,10 @@ cairo_d2d_surface_create_for_texture(cairo_device_t *device,
D2D1_ALPHA_MODE alpha = D2D1_ALPHA_MODE_PREMULTIPLIED;
if (content == CAIRO_CONTENT_COLOR) {
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR);
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_COLOR);
alpha = D2D1_ALPHA_MODE_IGNORE;
} else {
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
}
D2D1_SIZE_U sizePixels;
@ -4527,9 +4547,7 @@ cairo_d2d_surface_create_for_texture(cairo_device_t *device,
newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
newSurf->device = d2d_device;
cairo_addref_device(device);
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
_cairo_d2d_surface_init(newSurf, d2d_device, _cairo_format_from_content(content));
return reinterpret_cast<cairo_surface_t*>(newSurf);

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -77,10 +77,14 @@ cairo_debug_reset_static_data (void)
_cairo_clip_reset_static_data ();
_cairo_image_reset_static_data ();
#if CAIRO_HAS_DRM_SURFACE
_cairo_drm_device_reset_static_data ();
#endif
_cairo_reset_static_data ();
CAIRO_MUTEX_FINALIZE ();
}
@ -106,10 +110,14 @@ _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
case CAIRO_FORMAT_A8:
width = image->width;
break;
case CAIRO_FORMAT_RGB16_565:
width = image->width*2;
break;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_ARGB32:
width = image->width*4;
break;
case CAIRO_FORMAT_INVALID:
default:
/* XXX compute width from pixman bpp */
return;
@ -221,6 +229,12 @@ _cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path)
{
cairo_status_t status;
printf ("path: extents=(%f, %f), (%f, %f)\n",
_cairo_fixed_to_double (path->extents.p1.x),
_cairo_fixed_to_double (path->extents.p1.y),
_cairo_fixed_to_double (path->extents.p2.x),
_cairo_fixed_to_double (path->extents.p2.y));
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_print_move_to,

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -35,6 +35,7 @@
*/
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-output-stream-private.h"
#include <zlib.h>

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -36,20 +36,6 @@
#ifndef CAIRO_DEPRECATED_H
#define CAIRO_DEPRECATED_H
/* The %CAIRO_FORMAT_RGB16_565 value was added in cairo 1.2.0 as part
* of fixing cairo's xlib backend to work with X servers advertising a
* 16-bit, 565 visual. But as it turned out, adding this format to
* #cairo_format_t was not necessary, and was a mistake, (cairo's xlib
* backend can work fine with 16-bit visuals in the same way it works
* with BGR visuals without any BGR formats in
* #cairo_format_t).
*
* Additionally, the support for the RGB16_565 format was never
* completely implemented. So while this format value is currently
* deprecated, it may eventually acquire complete support in the future.
*/
/* #define CAIRO_FORMAT_RGB16_565 4 */
#define CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_QUARTZ
/* Obsolete functions. These definitions exist to coerce the compiler
@ -123,7 +109,6 @@
#define cairo_matrix_copy cairo_matrix_copy_DEPRECATED_BY_cairo_matrix_t
#define cairo_matrix_get_affine cairo_matrix_get_affine_DEPRECATED_BY_cairo_matrix_t
#define cairo_set_target_surface cairo_set_target_surface_DEPRECATED_BY_cairo_create
#define cairo_set_target_glitz cairo_set_target_glitz_DEPRECATED_BY_cairo_glitz_surface_create
#define cairo_set_target_image cairo_set_target_image_DEPRECATED_BY_cairo_image_surface_create_for_data
#define cairo_set_target_pdf cairo_set_target_pdf_DEPRECATED_BY_cairo_pdf_surface_create
#define cairo_set_target_png cairo_set_target_png_DEPRECATED_BY_cairo_surface_write_to_png

View File

@ -0,0 +1,86 @@
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Intel Corporation.
*
* Contributors(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef _CAIRO_DEVICE_PRIVATE_H_
#define _CAIRO_DEVICE_PRIVATE_H_
#include "cairo-compiler-private.h"
#include "cairo-mutex-private.h"
#include "cairo-reference-count-private.h"
#include "cairo-types-private.h"
struct _cairo_device {
cairo_reference_count_t ref_count;
cairo_status_t status;
cairo_user_data_array_t user_data;
const cairo_device_backend_t *backend;
cairo_recursive_mutex_t mutex;
unsigned mutex_depth;
cairo_bool_t finished;
};
struct _cairo_device_backend {
cairo_device_type_t type;
void (*lock) (void *device);
void (*unlock) (void *device);
cairo_warn cairo_status_t (*flush) (void *device);
void (*finish) (void *device);
void (*destroy) (void *device);
};
cairo_private cairo_device_t *
_cairo_device_create_in_error (cairo_status_t status);
cairo_private void
_cairo_device_init (cairo_device_t *device,
const cairo_device_backend_t *backend);
cairo_private cairo_status_t
_cairo_device_set_error (cairo_device_t *device,
cairo_status_t error);
slim_hidden_proto_no_warn (cairo_device_reference);
slim_hidden_proto (cairo_device_acquire);
slim_hidden_proto (cairo_device_release);
slim_hidden_proto (cairo_device_flush);
slim_hidden_proto (cairo_device_finish);
slim_hidden_proto (cairo_device_destroy);
#endif /* _CAIRO_DEVICE_PRIVATE_H_ */

View File

@ -0,0 +1,533 @@
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Intel Corporation.
*
* Contributors(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-device-private.h"
#include "cairo-error-private.h"
/**
* SECTION:cairo-device
* @Title: cairo_device_t
* @Short_Description: interface to underlying rendering system
* @See_Also: #cairo_surface_t
*
* Devices are the abstraction Cairo employs for the rendering system
* used by a #cairo_surface_t. You can get the device of a surface using
* cairo_surface_get_device().
*
* Devices are created using custom functions specific to the rendering
* system you want to use. See the documentation for the surface types
* for those functions.
*
* An important function that devices fulfill is sharing access to the
* rendering system between Cairo and your application. If you want to
* access a device directly that you used to draw to with Cairo, you must
* first call cairo_device_flush() to ensure that Cairo finishes all
* operations on the device and resets it to a clean state.
*
* Cairo also provides the functions cairo_device_acquire() and
* cairo_device_release() to synchronize access to the rendering system
* in a multithreaded environment. This is done internally, but can also
* be used by applications.
*
* Putting this all together, a function that works with devices should
* look something like this:
* <informalexample><programlisting>
* void
* my_device_modifying_function (cairo_device_t *device)
* {
* cairo_status_t status;
*
* // Ensure the device is properly reset
* cairo_device_flush (device);
* // Try to acquire the device
* status = cairo_device_acquire (device);
* if (status != CAIRO_STATUS_SUCCESS) {
* printf ("Failed to acquire the device: %s\n", cairo_status_to_string (status));
* return;
* }
*
* // Do the custom operations on the device here.
* // But do not call any Cairo functions that might acquire devices.
*
* // Release the device when done.
* cairo_device_release (device);
* }
* </programlisting></informalexample>
*
* <note><para>Please refer to the documentation of each backend for
* additional usage requirements, guarantees provided, and
* interactions with existing surface API of the device functions for
* surfaces of that type.
* </para></note>
*/
static const cairo_device_t _nil_device = {
CAIRO_REFERENCE_COUNT_INVALID,
CAIRO_STATUS_NO_MEMORY,
};
static const cairo_device_t _mismatch_device = {
CAIRO_REFERENCE_COUNT_INVALID,
CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
};
static const cairo_device_t _invalid_device = {
CAIRO_REFERENCE_COUNT_INVALID,
CAIRO_STATUS_DEVICE_ERROR,
};
cairo_device_t *
_cairo_device_create_in_error (cairo_status_t status)
{
switch (status) {
case CAIRO_STATUS_NO_MEMORY:
return (cairo_device_t *) &_nil_device;
case CAIRO_STATUS_DEVICE_ERROR:
return (cairo_device_t *) &_invalid_device;
case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
return (cairo_device_t *) &_mismatch_device;
case CAIRO_STATUS_SUCCESS:
case CAIRO_STATUS_LAST_STATUS:
ASSERT_NOT_REACHED;
/* fall-through */
case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
case CAIRO_STATUS_INVALID_STATUS:
case CAIRO_STATUS_INVALID_FORMAT:
case CAIRO_STATUS_INVALID_VISUAL:
case CAIRO_STATUS_READ_ERROR:
case CAIRO_STATUS_WRITE_ERROR:
case CAIRO_STATUS_FILE_NOT_FOUND:
case CAIRO_STATUS_TEMP_FILE_ERROR:
case CAIRO_STATUS_INVALID_STRIDE:
case CAIRO_STATUS_INVALID_SIZE:
case CAIRO_STATUS_INVALID_RESTORE:
case CAIRO_STATUS_INVALID_POP_GROUP:
case CAIRO_STATUS_NO_CURRENT_POINT:
case CAIRO_STATUS_INVALID_MATRIX:
case CAIRO_STATUS_NULL_POINTER:
case CAIRO_STATUS_INVALID_STRING:
case CAIRO_STATUS_INVALID_PATH_DATA:
case CAIRO_STATUS_SURFACE_FINISHED:
case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
case CAIRO_STATUS_INVALID_DASH:
case CAIRO_STATUS_INVALID_DSC_COMMENT:
case CAIRO_STATUS_INVALID_INDEX:
case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
case CAIRO_STATUS_FONT_TYPE_MISMATCH:
case CAIRO_STATUS_USER_FONT_IMMUTABLE:
case CAIRO_STATUS_USER_FONT_ERROR:
case CAIRO_STATUS_NEGATIVE_COUNT:
case CAIRO_STATUS_INVALID_CLUSTERS:
case CAIRO_STATUS_INVALID_SLANT:
case CAIRO_STATUS_INVALID_WEIGHT:
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
case CAIRO_STATUS_INVALID_CONTENT:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_device_t *) &_nil_device;
}
}
void
_cairo_device_init (cairo_device_t *device,
const cairo_device_backend_t *backend)
{
CAIRO_REFERENCE_COUNT_INIT (&device->ref_count, 1);
device->status = CAIRO_STATUS_SUCCESS;
device->backend = backend;
CAIRO_RECURSIVE_MUTEX_INIT (device->mutex);
device->mutex_depth = 0;
device->finished = FALSE;
_cairo_user_data_array_init (&device->user_data);
}
/**
* cairo_device_reference:
* @device: a #cairo_device_t
*
* Increases the reference count on @device by one. This prevents
* @device from being destroyed until a matching call to
* cairo_device_destroy() is made.
*
* The number of references to a #cairo_device_t can be get using
* cairo_device_get_reference_count().
*
* Return value: the referenced #cairo_device_t.
*
* Since: 1.10
**/
cairo_device_t *
cairo_device_reference (cairo_device_t *device)
{
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
{
return device;
}
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
_cairo_reference_count_inc (&device->ref_count);
return device;
}
slim_hidden_def (cairo_device_reference);
/**
* cairo_device_status:
* @device: a #cairo_device_t
*
* Checks whether an error has previously occurred for this
* device.
*
* Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
* the device is in an error state.
*
* Since: 1.10
**/
cairo_status_t
cairo_device_status (cairo_device_t *device)
{
if (device == NULL)
return CAIRO_STATUS_NULL_POINTER;
return device->status;
}
/**
* cairo_device_flush:
* @device: a #cairo_device_t
*
* Finish any pending operations for the device and also restore any
* temporary modifications cairo has made to the device's state.
* This function must be called before switching from using the
* device with Cairo to operating on it directly with native APIs.
* If the device doesn't support direct access, then this function
* does nothing.
*
* This function may acquire devices.
*
* Since: 1.10
**/
void
cairo_device_flush (cairo_device_t *device)
{
cairo_status_t status;
if (device == NULL || device->status)
return;
if (device->backend->flush != NULL) {
status = device->backend->flush (device);
if (unlikely (status))
status = _cairo_device_set_error (device, status);
}
}
slim_hidden_def (cairo_device_flush);
/**
* cairo_device_finish:
* @device: the #cairo_device_t to finish
*
* This function finishes the device and drops all references to
* external resources. All surfaces, fonts and other objects created
* for this @device will be finished, too.
* Further operations on the @device will not affect the @device but
* will instead trigger a %CAIRO_STATUS_DEVICE_FINISHED error.
*
* When the last call to cairo_device_destroy() decreases the
* reference count to zero, cairo will call cairo_device_finish() if
* it hasn't been called already, before freeing the resources
* associated with the device.
*
* This function may acquire devices.
*
* Since: 1.10
**/
void
cairo_device_finish (cairo_device_t *device)
{
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
{
return;
}
if (device->finished)
return;
cairo_device_flush (device);
device->finished = TRUE;
if (device->backend->finish != NULL)
device->backend->finish (device);
}
slim_hidden_def (cairo_device_finish);
/**
* cairo_device_destroy:
* @device: a #cairo_device_t
*
* Decreases the reference count on @device by one. If the result is
* zero, then @device and all associated resources are freed. See
* cairo_device_reference().
*
* This function may acquire devices if the last reference was dropped.
*
* Since: 1.10
**/
void
cairo_device_destroy (cairo_device_t *device)
{
cairo_user_data_array_t user_data;
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
{
return;
}
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
if (! _cairo_reference_count_dec_and_test (&device->ref_count))
return;
cairo_device_finish (device);
assert (device->mutex_depth == 0);
CAIRO_MUTEX_FINI (device->mutex);
user_data = device->user_data;
device->backend->destroy (device);
_cairo_user_data_array_fini (&user_data);
}
slim_hidden_def (cairo_device_destroy);
/**
* cairo_device_get_type:
* @device: a #cairo_device_t
*
* This function returns the type of the device. See #cairo_device_type_t
* for available types.
*
* Return value: The type of @device.
*
* Since: 1.10
**/
cairo_device_type_t
cairo_device_get_type (cairo_device_t *device)
{
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
{
return (cairo_device_type_t) -1;
}
return device->backend->type;
}
/**
* cairo_device_acquire:
* @device: a #cairo_device_t
*
* Acquires the @device for the current thread. This function will block
* until no other thread has acquired the device.
*
* If the return value is %CAIRO_STATUS_SUCCESS, you successfully acquired the
* device. From now on your thread owns the device and no other thread will be
* able to acquire it until a matching call to cairo_device_release(). It is
* allowed to recursively acquire the device multiple times from the same
* thread.
*
* <note><para>You must never acquire two different devices at the same time
* unless this is explicitly allowed. Otherwise the possibility of deadlocks
* exist.
*
* As various Cairo functions can acquire devices when called, these functions
* may also cause deadlocks when you call them with an acquired device. So you
* must not have a device acquired when calling them. These functions are
* marked in the documentation.
* </para></note>
*
* Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
* the device is in an error state and could not be
* acquired. After a successful call to cairo_device_acquire(),
* a matching call to cairo_device_release() is required.
*
* Since: 1.10
**/
cairo_status_t
cairo_device_acquire (cairo_device_t *device)
{
if (device == NULL)
return CAIRO_STATUS_SUCCESS;
if (unlikely (device->status))
return device->status;
if (unlikely (device->finished))
return _cairo_device_set_error (device, CAIRO_STATUS_SURFACE_FINISHED); /* XXX */
CAIRO_MUTEX_LOCK (device->mutex);
if (device->mutex_depth++ == 0) {
if (device->backend->lock != NULL)
device->backend->lock (device);
}
return CAIRO_STATUS_SUCCESS;
}
slim_hidden_def (cairo_device_acquire);
/**
* cairo_device_release:
* @device: a #cairo_device_t
*
* Releases a @device previously acquired using cairo_device_acquire(). See
* that function for details.
*
* Since: 1.10
**/
void
cairo_device_release (cairo_device_t *device)
{
if (device == NULL)
return;
assert (device->mutex_depth > 0);
if (--device->mutex_depth == 0) {
if (device->backend->unlock != NULL)
device->backend->unlock (device);
}
CAIRO_MUTEX_UNLOCK (device->mutex);
}
slim_hidden_def (cairo_device_release);
cairo_status_t
_cairo_device_set_error (cairo_device_t *device,
cairo_status_t status)
{
if (status == CAIRO_STATUS_SUCCESS || status >= CAIRO_INT_STATUS_UNSUPPORTED)
return status;
/* Don't overwrite an existing error. This preserves the first
* error, which is the most significant. */
_cairo_status_set_error (&device->status, status);
return _cairo_error (status);
}
/**
* cairo_device_get_reference_count:
* @device: a #cairo_device_t
*
* Returns the current reference count of @device.
*
* Return value: the current reference count of @device. If the
* object is a nil object, 0 will be returned.
*
* Since: 1.10
**/
unsigned int
cairo_device_get_reference_count (cairo_device_t *device)
{
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
return 0;
return CAIRO_REFERENCE_COUNT_GET_VALUE (&device->ref_count);
}
/**
* cairo_device_get_user_data:
* @device: a #cairo_device_t
* @key: the address of the #cairo_user_data_key_t the user data was
* attached to
*
* Return user data previously attached to @device using the
* specified key. If no user data has been attached with the given
* key this function returns %NULL.
*
* Return value: the user data previously attached or %NULL.
*
* Since: 1.10
**/
void *
cairo_device_get_user_data (cairo_device_t *device,
const cairo_user_data_key_t *key)
{
return _cairo_user_data_array_get_data (&device->user_data,
key);
}
/**
* cairo_device_set_user_data:
* @device: a #cairo_device_t
* @key: the address of a #cairo_user_data_key_t to attach the user data to
* @user_data: the user data to attach to the #cairo_device_t
* @destroy: a #cairo_destroy_func_t which will be called when the
* #cairo_t is destroyed or when new user data is attached using the
* same key.
*
* Attach user data to @device. To remove user data from a surface,
* call this function with the key that was used to set it and %NULL
* for @data.
*
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
* slot could not be allocated for the user data.
*
* Since: 1.10
**/
cairo_status_t
cairo_device_set_user_data (cairo_device_t *device,
const cairo_user_data_key_t *key,
void *user_data,
cairo_destroy_func_t destroy)
{
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
return device->status;
return _cairo_user_data_array_set_data (&device->user_data,
key, user_data, destroy);
}

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -39,6 +39,7 @@
#include "cairo-directfb.h"
#include "cairo-clip-private.h"
#include "cairo-error-private.h"
#include <pixman.h>
@ -564,6 +565,7 @@ _cairo_directfb_surface_create_internal (IDirectFB *dfb,
_cairo_surface_init (&surface->base,
&_cairo_directfb_surface_backend,
NULL, /* device */
content);
surface->pixman_format = _directfb_to_pixman_format (format);
surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
@ -762,14 +764,14 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
pixman_image_composite (PIXMAN_OP_SRC,
image_src->pixman_image,
NULL,
pixman_image,
src_x, src_y,
0, 0,
0, 0,
width, height);
pixman_image_composite32 (PIXMAN_OP_SRC,
image_src->pixman_image,
NULL,
pixman_image,
src_x, src_y,
0, 0,
0, 0,
width, height);
pixman_image_unref (pixman_image);
@ -1814,7 +1816,7 @@ _cairo_directfb_surface_show_glyphs (void *abstract_dst,
static cairo_bool_t
_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_content_t content)
_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b)
{
cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
@ -1955,6 +1957,7 @@ cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface)
_cairo_surface_init (&surface->base,
&_cairo_directfb_surface_backend,
NULL, /* device */
_directfb_format_to_content (format));
return &surface->base;

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -39,56 +39,41 @@
CAIRO_BEGIN_DECLS
typedef struct _cairo_drm_device cairo_drm_device_t;
struct udev_device;
cairo_public cairo_drm_device_t *
cairo_public cairo_device_t *
cairo_drm_device_get (struct udev_device *device);
cairo_public cairo_drm_device_t *
cairo_public cairo_device_t *
cairo_drm_device_get_for_fd (int fd);
cairo_public cairo_drm_device_t *
cairo_public cairo_device_t *
cairo_drm_device_default (void);
cairo_public cairo_drm_device_t *
cairo_drm_device_reference (cairo_drm_device_t *device);
cairo_public cairo_status_t
cairo_drm_device_status (cairo_drm_device_t *device);
cairo_public int
cairo_drm_device_get_fd (cairo_drm_device_t *device);
cairo_drm_device_get_fd (cairo_device_t *device);
cairo_public void
cairo_drm_device_throttle (cairo_drm_device_t *device);
cairo_public void
cairo_drm_device_destroy (cairo_drm_device_t *device);
cairo_drm_device_throttle (cairo_device_t *device);
cairo_public cairo_surface_t *
cairo_drm_surface_create (cairo_drm_device_t *device,
cairo_content_t content,
cairo_drm_surface_create (cairo_device_t *device,
cairo_format_t format,
int width, int height);
cairo_public cairo_surface_t *
cairo_drm_surface_create_for_name (cairo_drm_device_t *device,
cairo_drm_surface_create_for_name (cairo_device_t *device,
unsigned int name,
cairo_format_t format,
int width, int height, int stride);
cairo_public cairo_surface_t *
cairo_drm_surface_create_from_cacheable_image (cairo_drm_device_t *device,
cairo_drm_surface_create_from_cacheable_image (cairo_device_t *device,
cairo_surface_t *surface);
cairo_public cairo_status_t
cairo_drm_surface_enable_scan_out (cairo_surface_t *surface);
cairo_public cairo_drm_device_t *
cairo_drm_surface_get_device (cairo_surface_t *abstract_surface);
cairo_public unsigned int
cairo_drm_surface_get_handle (cairo_surface_t *surface);
@ -120,7 +105,7 @@ cairo_drm_surface_get_stride (cairo_surface_t *surface);
* will also disassociate the mapping.)
*/
cairo_public cairo_surface_t *
cairo_drm_surface_map (cairo_surface_t *surface);
cairo_drm_surface_map_to_image (cairo_surface_t *surface);
cairo_public void
cairo_drm_surface_unmap (cairo_surface_t *drm_surface,

View File

@ -34,13 +34,12 @@
* Bas Schouten <bschouten@mozilla.com>
*/
extern "C" {
#include "cairoint.h"
#include "cairo-win32-private.h"
#include "cairo-surface-private.h"
#include "cairo-clip-private.h"
}
#include "cairo-d2d-private.h"
#include "cairo-dwrite-private.h"
#include <float.h>

View File

@ -0,0 +1,60 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef _CAIRO_ERROR_PRIVATE_H_
#define _CAIRO_ERROR_PRIVATE_H_
#include "cairo.h"
#include "cairo-compiler-private.h"
CAIRO_BEGIN_DECLS
#define _cairo_status_is_error(status) \
(status != CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS)
cairo_private cairo_status_t
_cairo_error (cairo_status_t status);
/* hide compiler warnings when discarding the return value */
#define _cairo_error_throw(status) do { \
cairo_status_t status__ = _cairo_error (status); \
(void) status__; \
} while (0)
CAIRO_END_DECLS
#endif /* _CAIRO_ERROR_PRIVATE_H_ */

View File

@ -89,6 +89,8 @@
@QUARTZ_FONT_FEATURE@
@TEE_SURFACE_FEATURE@
@PNG_FUNCTIONS_FEATURE@
@FC_FONT_FEATURE@

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -53,7 +53,7 @@
#define CAIRO_FIXED_ONE_FLOAT ((float)(1 << CAIRO_FIXED_FRAC_BITS))
#define CAIRO_FIXED_EPSILON ((cairo_fixed_t)(1))
#define CAIRO_FIXED_FRAC_MASK (((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS))
#define CAIRO_FIXED_FRAC_MASK ((cairo_fixed_t)(((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS)))
#define CAIRO_FIXED_WHOLE_MASK (~CAIRO_FIXED_FRAC_MASK)
static inline cairo_fixed_t
@ -136,6 +136,16 @@ _cairo_fixed_from_26_6 (uint32_t i)
#endif
}
static inline cairo_fixed_t
_cairo_fixed_from_16_16 (uint32_t i)
{
#if CAIRO_FIXED_FRAC_BITS > 16
return i << (CAIRO_FIXED_FRAC_BITS - 16);
#else
return i >> (16 - CAIRO_FIXED_FRAC_BITS);
#endif
}
static inline double
_cairo_fixed_to_double (cairo_fixed_t f)
{
@ -154,12 +164,48 @@ _cairo_fixed_is_integer (cairo_fixed_t f)
return (f & CAIRO_FIXED_FRAC_MASK) == 0;
}
static inline cairo_fixed_t
_cairo_fixed_floor (cairo_fixed_t f)
{
return f & ~CAIRO_FIXED_FRAC_MASK;
}
static inline cairo_fixed_t
_cairo_fixed_round (cairo_fixed_t f)
{
return _cairo_fixed_floor (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
}
static inline cairo_fixed_t
_cairo_fixed_round_down (cairo_fixed_t f)
{
return _cairo_fixed_floor (f + CAIRO_FIXED_FRAC_MASK/2);
}
static inline int
_cairo_fixed_integer_part (cairo_fixed_t f)
{
return f >> CAIRO_FIXED_FRAC_BITS;
}
static inline int
_cairo_fixed_integer_round (cairo_fixed_t f)
{
return _cairo_fixed_integer_part (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
}
static inline int
_cairo_fixed_integer_round_down (cairo_fixed_t f)
{
return _cairo_fixed_integer_part (f + CAIRO_FIXED_FRAC_MASK/2);
}
static inline int
_cairo_fixed_fractional_part (cairo_fixed_t f)
{
return f & CAIRO_FIXED_FRAC_MASK;
}
static inline int
_cairo_fixed_integer_floor (cairo_fixed_t f)
{
@ -225,12 +271,18 @@ _cairo_fixed_16_16_from_double (double d)
}
static inline int
_cairo_fixed_16_16_floor (cairo_fixed_t f)
_cairo_fixed_16_16_floor (cairo_fixed_16_16_t f)
{
if (f >= 0)
return f >> 16;
return f >> 16;
else
return -((-f - 1) >> 16) - 1;
return -((-f - 1) >> 16) - 1;
}
static inline double
_cairo_fixed_16_16_to_double (cairo_fixed_16_16_t f)
{
return ((double) f) / (double) (1 << 16);
}
#if CAIRO_FIXED_BITS == 32

View File

@ -13,7 +13,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -35,6 +35,7 @@
*/
#include "cairoint.h"
#include "cairo-error-private.h"
#include <math.h>

View File

@ -14,7 +14,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -39,6 +39,24 @@
*/
#include "cairoint.h"
#include "cairo-error-private.h"
/**
* SECTION:cairo-font-face
* @Title: cairo_font_face_t
* @Short_Description: Base class for font faces
* @See_Also: #cairo_scaled_font_t
*
* #cairo_font_face_t represents a particular font at a particular weight,
* slant, and other characteristic but no size, transformation, or size.
*
* Font faces are created using <firstterm>font-backend</firstterm>-specific
* constructors, typically of the form
* cairo_<emphasis>backend</emphasis>_font_face_create(), or implicitly
* using the <firstterm>toy</firstterm> text API by way of
* cairo_select_font_face(). The resulting face can be accessed using
* cairo_get_font_face().
*/
/* #cairo_font_face_t */

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -35,12 +35,27 @@
*/
#include "cairoint.h"
#include "cairo-error-private.h"
/**
* SECTION:cairo-font-options
* @Title: cairo_font_options_t
* @Short_Description: How a font should be rendered
* @See_Also: #cairo_scaled_font_t
*
* The font options specify how fonts should be rendered. Most of the
* time the font options implied by a surface are just right and do not
* need any changes, but for pixel-based targets tweaking font options
* may result in superior output on a particular display.
*/
static const cairo_font_options_t _cairo_font_options_nil = {
CAIRO_ANTIALIAS_DEFAULT,
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_LCD_FILTER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT
CAIRO_HINT_METRICS_DEFAULT,
CAIRO_ROUND_GLYPH_POS_DEFAULT
};
/**
@ -54,8 +69,10 @@ _cairo_font_options_init_default (cairo_font_options_t *options)
{
options->antialias = CAIRO_ANTIALIAS_DEFAULT;
options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
options->round_glyph_positions = CAIRO_ROUND_GLYPH_POS_DEFAULT;
}
void
@ -64,8 +81,10 @@ _cairo_font_options_init_copy (cairo_font_options_t *options,
{
options->antialias = other->antialias;
options->subpixel_order = other->subpixel_order;
options->lcd_filter = other->lcd_filter;
options->hint_style = other->hint_style;
options->hint_metrics = other->hint_metrics;
options->round_glyph_positions = other->round_glyph_positions;
}
/**
@ -189,10 +208,14 @@ cairo_font_options_merge (cairo_font_options_t *options,
options->antialias = other->antialias;
if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
options->subpixel_order = other->subpixel_order;
if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
options->lcd_filter = other->lcd_filter;
if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
options->hint_style = other->hint_style;
if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
options->hint_metrics = other->hint_metrics;
if (other->round_glyph_positions != CAIRO_ROUND_GLYPH_POS_DEFAULT)
options->round_glyph_positions = other->round_glyph_positions;
}
slim_hidden_def (cairo_font_options_merge);
@ -221,8 +244,10 @@ cairo_font_options_equal (const cairo_font_options_t *options,
return (options->antialias == other->antialias &&
options->subpixel_order == other->subpixel_order &&
options->lcd_filter == other->lcd_filter &&
options->hint_style == other->hint_style &&
options->hint_metrics == other->hint_metrics);
options->hint_metrics == other->hint_metrics &&
options->round_glyph_positions == other->round_glyph_positions);
}
slim_hidden_def (cairo_font_options_equal);
@ -246,7 +271,8 @@ cairo_font_options_hash (const cairo_font_options_t *options)
return ((options->antialias) |
(options->subpixel_order << 4) |
(options->hint_style << 8) |
(options->lcd_filter << 8) |
(options->hint_style << 12) |
(options->hint_metrics << 16));
}
slim_hidden_def (cairo_font_options_hash);
@ -327,6 +353,87 @@ cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
return options->subpixel_order;
}
/**
* _cairo_font_options_set_lcd_filter:
* @options: a #cairo_font_options_t
* @lcd_filter: the new LCD filter
*
* Sets the LCD filter for the font options object. The LCD filter
* specifies how pixels are filtered when rendered with an antialiasing
* mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
* #cairo_lcd_filter_t for full details.
*
* Since: 1.8
**/
void
_cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
cairo_lcd_filter_t lcd_filter)
{
if (cairo_font_options_status (options))
return;
options->lcd_filter = lcd_filter;
}
/**
* _cairo_font_options_get_lcd_filter:
* @options: a #cairo_font_options_t
*
* Gets the LCD filter for the font options object.
* See the documentation for #cairo_lcd_filter_t for full details.
*
* Return value: the LCD filter for the font options object
*
* Since: 1.8
**/
cairo_lcd_filter_t
_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
{
if (cairo_font_options_status ((cairo_font_options_t *) options))
return CAIRO_LCD_FILTER_DEFAULT;
return options->lcd_filter;
}
/**
* _cairo_font_options_set_round_glyph_positions:
* @options: a #cairo_font_options_t
* @round: the new rounding value
*
* Sets the rounding options for the font options object. If rounding is set, a
* glyph's position will be rounded to integer values.
*
* Since: 1.12
**/
void
_cairo_font_options_set_round_glyph_positions (cairo_font_options_t *options,
cairo_round_glyph_positions_t round)
{
if (cairo_font_options_status (options))
return;
options->round_glyph_positions = round;
}
/**
* _cairo_font_options_get_round_glyph_positions:
* @options: a #cairo_font_options_t
*
* Gets the glyph position rounding option for the font options object.
*
* Return value: The round glyph posistions flag for the font options object.
*
* Since: 1.12
**/
cairo_round_glyph_positions_t
_cairo_font_options_get_round_glyph_positions (const cairo_font_options_t *options)
{
if (cairo_font_options_status ((cairo_font_options_t *) options))
return CAIRO_ROUND_GLYPH_POS_DEFAULT;
return options->round_glyph_positions;
}
/**
* cairo_font_options_set_hint_style:
* @options: a #cairo_font_options_t

View File

@ -0,0 +1,78 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2000 Keith Packard
* Copyright © 2005 Red Hat, Inc
* Copyright © 2010 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
* Keith Packard <keithp@keithp.com>
* Carl Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef _CAIRO_FONTCONFIG_PRIVATE_H
#define _CAIRO_FONTCONFIG_PRIVATE_H
#include "cairo.h"
#if CAIRO_HAS_FC_FONT
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
#endif
/* sub-pixel order */
#ifndef FC_RGBA_UNKNOWN
#define FC_RGBA_UNKNOWN 0
#define FC_RGBA_RGB 1
#define FC_RGBA_BGR 2
#define FC_RGBA_VRGB 3
#define FC_RGBA_VBGR 4
#define FC_RGBA_NONE 5
#endif
/* hinting style */
#ifndef FC_HINT_NONE
#define FC_HINT_NONE 0
#define FC_HINT_SLIGHT 1
#define FC_HINT_MEDIUM 2
#define FC_HINT_FULL 3
#endif
/* LCD filter */
#ifndef FC_LCD_NONE
#define FC_LCD_NONE 0
#define FC_LCD_DEFAULT 1
#define FC_LCD_LIGHT 2
#define FC_LCD_LEGACY 3
#endif
#endif /* _CAIRO_FONTCONFIG_PRIVATE_H */

View File

@ -0,0 +1,129 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Chris Wilson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef CAIRO_FREED_POOL_H
#define CAIRO_FREED_POOL_H
#include "cairoint.h"
#include "cairo-atomic-private.h"
#if HAS_ATOMIC_OPS
/* Keep a stash of recently freed clip_paths, since we need to
* reallocate them frequently.
*/
#define MAX_FREED_POOL_SIZE 4
typedef struct {
void *pool[MAX_FREED_POOL_SIZE];
int top;
} freed_pool_t;
static cairo_always_inline void *
_atomic_fetch (void **slot)
{
void *ptr;
do {
ptr = _cairo_atomic_ptr_get (slot);
} while (! _cairo_atomic_ptr_cmpxchg (slot, ptr, NULL));
return ptr;
}
static cairo_always_inline cairo_bool_t
_atomic_store (void **slot, void *ptr)
{
return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr);
}
cairo_private void *
_freed_pool_get_search (freed_pool_t *pool);
static inline void *
_freed_pool_get (freed_pool_t *pool)
{
void *ptr;
int i;
i = pool->top - 1;
if (i < 0)
i = 0;
ptr = _atomic_fetch (&pool->pool[i]);
if (likely (ptr != NULL)) {
pool->top = i;
return ptr;
}
/* either empty or contended */
return _freed_pool_get_search (pool);
}
cairo_private void
_freed_pool_put_search (freed_pool_t *pool, void *ptr);
static inline void
_freed_pool_put (freed_pool_t *pool, void *ptr)
{
int i;
i = pool->top;
if (likely (i < ARRAY_LENGTH (pool->pool) &&
_atomic_store (&pool->pool[i], ptr)))
{
pool->top = i + 1;
return;
}
/* either full or contended */
_freed_pool_put_search (pool, ptr);
}
cairo_private void
_freed_pool_reset (freed_pool_t *pool);
#define HAS_FREED_POOL 1
#else
typedef int freed_pool_t;
#define _freed_pool_get(pool) NULL
#define _freed_pool_put(pool, ptr) free(ptr)
#define _freed_pool_reset(ptr)
#endif
#endif /* CAIRO_FREED_POOL_PRIVATE_H */

View File

@ -0,0 +1,93 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Chris Wilson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.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/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-freed-pool-private.h"
#if HAS_FREED_POOL
void *
_freed_pool_get_search (freed_pool_t *pool)
{
void *ptr;
int i;
for (i = ARRAY_LENGTH (pool->pool); i--;) {
ptr = _atomic_fetch (&pool->pool[i]);
if (ptr != NULL) {
pool->top = i;
return ptr;
}
}
/* empty */
pool->top = 0;
return NULL;
}
void
_freed_pool_put_search (freed_pool_t *pool, void *ptr)
{
int i;
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
if (_atomic_store (&pool->pool[i], ptr)) {
pool->top = i + 1;
return;
}
}
/* full */
pool->top = i;
free (ptr);
}
void
_freed_pool_reset (freed_pool_t *pool)
{
int i;
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
free (pool->pool[i]);
pool->pool[i] = NULL;
}
pool->top = 0;
}
#endif

View File

@ -24,6 +24,7 @@
#include "cairo-types-private.h"
#include "cairo-compiler-private.h"
#include "cairo-freelist-type-private.h"
/* for stand-alone compilation*/
#ifndef VG
@ -34,32 +35,6 @@
#define NULL (void *) 0
#endif
typedef struct _cairo_freelist_node cairo_freelist_node_t;
struct _cairo_freelist_node {
cairo_freelist_node_t *next;
};
typedef struct _cairo_freelist {
cairo_freelist_node_t *first_free_node;
unsigned nodesize;
} cairo_freelist_t;
typedef struct _cairo_freelist_pool cairo_freelist_pool_t;
struct _cairo_freelist_pool {
cairo_freelist_pool_t *next;
unsigned size, rem;
uint8_t *data;
};
typedef struct _cairo_freepool {
cairo_freelist_node_t *first_free_node;
cairo_freelist_pool_t *pools;
unsigned nodesize;
cairo_freelist_pool_t embedded_pool;
uint8_t embedded_data[1000];
} cairo_freepool_t;
/* Initialise a freelist that will be responsible for allocating
* nodes of size nodesize. */
cairo_private void
@ -96,6 +71,20 @@ _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize);
cairo_private void
_cairo_freepool_fini (cairo_freepool_t *freepool);
static inline void
_cairo_freepool_reset (cairo_freepool_t *freepool)
{
while (freepool->pools != &freepool->embedded_pool) {
cairo_freelist_pool_t *pool = freepool->pools;
freepool->pools = pool->next;
pool->next = freepool->freepools;
freepool->freepools = pool;
}
freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
freepool->embedded_pool.data = freepool->embedded_data;
}
cairo_private void *
_cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool);

View File

@ -0,0 +1,54 @@
/*
* Copyright © 2010 Joonas Pihlaja
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef CAIRO_FREELIST_TYPE_H
#define CAIRO_FREELIST_TYPE_H
#include "cairo-types-private.h"
#include "cairo-compiler-private.h"
typedef struct _cairo_freelist_node cairo_freelist_node_t;
struct _cairo_freelist_node {
cairo_freelist_node_t *next;
};
typedef struct _cairo_freelist {
cairo_freelist_node_t *first_free_node;
unsigned nodesize;
} cairo_freelist_t;
typedef struct _cairo_freelist_pool cairo_freelist_pool_t;
struct _cairo_freelist_pool {
cairo_freelist_pool_t *next;
unsigned size, rem;
uint8_t *data;
};
typedef struct _cairo_freepool {
cairo_freelist_node_t *first_free_node;
cairo_freelist_pool_t *pools;
cairo_freelist_pool_t *freepools;
unsigned nodesize;
cairo_freelist_pool_t embedded_pool;
uint8_t embedded_data[1000];
} cairo_freepool_t;
#endif /* CAIRO_FREELIST_TYPE_H */

View File

@ -22,6 +22,7 @@
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-freelist-private.h"
void
@ -83,12 +84,12 @@ _cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
}
}
void
_cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize)
{
freepool->first_free_node = NULL;
freepool->pools = &freepool->embedded_pool;
freepool->freepools = NULL;
freepool->nodesize = nodesize;
freepool->embedded_pool.next = NULL;
@ -96,19 +97,28 @@ _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize)
freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
freepool->embedded_pool.data = freepool->embedded_data;
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data,
sizeof (freepool->embedded_data)));
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data, sizeof (freepool->embedded_data)));
}
void
_cairo_freepool_fini (cairo_freepool_t *freepool)
{
cairo_freelist_pool_t *pool = freepool->pools;
cairo_freelist_pool_t *pool;
pool = freepool->pools;
while (pool != &freepool->embedded_pool) {
cairo_freelist_pool_t *next = pool->next;
free (pool);
pool = next;
}
pool = freepool->freepools;
while (pool != NULL) {
cairo_freelist_pool_t *next = pool->next;
free (pool);
pool = next;
}
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool, sizeof (freepool)));
}
@ -118,23 +128,31 @@ _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool)
cairo_freelist_pool_t *pool;
int poolsize;
if (freepool->pools != &freepool->embedded_pool)
poolsize = 2 * freepool->pools->size;
else
poolsize = (128 * freepool->nodesize + 8191) & -8192;
pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
if (unlikely (pool == NULL))
return pool;
if (freepool->freepools != NULL) {
pool = freepool->freepools;
freepool->freepools = pool->next;
poolsize = pool->size;
} else {
if (freepool->pools != &freepool->embedded_pool)
poolsize = 2 * freepool->pools->size;
else
poolsize = (128 * freepool->nodesize + 8191) & -8192;
pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
if (unlikely (pool == NULL))
return pool;
pool->size = poolsize;
}
pool->next = freepool->pools;
freepool->pools = pool;
pool->size = poolsize;
pool->rem = poolsize - freepool->nodesize;
pool->data = (uint8_t *) (pool + 1) + freepool->nodesize;
VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, poolsize));
VG (VALGRIND_MAKE_MEM_UNDEFINED (pool->data, freepool->nodesize));
VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, pool->rem));
return pool + 1;
}

View File

@ -14,7 +14,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -41,14 +41,12 @@
#define _BSD_SOURCE /* for strdup() */
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-ft-private.h"
#include <float.h>
#if CAIRO_HAS_FC_FONT
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
#endif
#include "cairo-fontconfig-private.h"
#include <ft2build.h>
#include FT_FREETYPE_H
@ -59,6 +57,30 @@
#include FT_SYNTHESIS_H
#endif
#if HAVE_FT_LIBRARY_SETLCDFILTER
#include FT_LCD_FILTER_H
#endif
/* Fontconfig version older than 2.6 didn't have these options */
#ifndef FC_LCD_FILTER
#define FC_LCD_FILTER "lcdfilter"
#endif
/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
#ifndef FC_LCD_NONE
#define FC_LCD_NONE 0
#define FC_LCD_DEFAULT 1
#define FC_LCD_LIGHT 2
#define FC_LCD_LEGACY 3
#endif
/* FreeType version older than 2.3.5(?) didn't have these options */
#ifndef FT_LCD_FILTER_NONE
#define FT_LCD_FILTER_NONE 0
#define FT_LCD_FILTER_DEFAULT 1
#define FT_LCD_FILTER_LIGHT 2
#define FT_LCD_FILTER_LEGACY 16
#endif
#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
@ -67,11 +89,35 @@
/* This is the max number of FT_face objects we keep open at once
*/
#define MAX_OPEN_FACES 10
/* This is the maximum font size we allow to be passed to FT_Set_Char_Size
*/
#define MAX_FONT_SIZE 1000
/**
* SECTION:cairo-ft
* @Title: FreeType Fonts
* @Short_Description: Font support for FreeType
* @See_Also: #cairo_font_face_t
*
* The FreeType font backend is primarily used to render text on GNU/Linux
* systems, but can be used on other platforms too.
*/
/**
* CAIRO_HAS_FT_FONT:
*
* Defined if the FreeType font backend is available.
* This macro can be used to conditionally compile backend-specific code.
*/
/**
* CAIRO_HAS_FC_FONT:
*
* Defined if the Fontconfig-specific functions of the FreeType font backend
* are available.
* This macro can be used to conditionally compile backend-specific code.
*/
/*
* The simple 2x2 matrix is converted into separate scale and shape
* factors so that hinting works right
@ -180,6 +226,7 @@ typedef struct _cairo_ft_unscaled_font_map {
static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
static void
_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
cairo_ft_unscaled_font_t *unscaled)
@ -779,23 +826,279 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
return CAIRO_STATUS_SUCCESS;
}
/* Empirically-derived subpixel filtering values thanks to Keith
* Packard and libXft. */
static const int filters[3][3] = {
/* red */
#if 0
{ 65538*4/7,65538*2/7,65538*1/7 },
/* green */
{ 65536*1/4, 65536*2/4, 65537*1/4 },
/* blue */
{ 65538*1/7,65538*2/7,65538*4/7 },
#endif
{ 65538*9/13,65538*3/13,65538*1/13 },
/* green */
{ 65538*1/6, 65538*4/6, 65538*1/6 },
/* blue */
{ 65538*1/13,65538*3/13,65538*9/13 },
};
/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
* into a different format. For example, we want to convert a
* FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
* ARGB or ABGR bitmap.
*
* this function prepares a target descriptor for this operation.
*
* input :: target bitmap descriptor. The function will set its
* 'width', 'rows' and 'pitch' fields, and only these
*
* slot :: the glyph slot containing the source bitmap. this
* function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
*
* mode :: the requested final rendering mode. supported values are
* MONO, NORMAL (i.e. gray), LCD and LCD_V
*
* the function returns the size in bytes of the corresponding buffer,
* it's up to the caller to allocate the corresponding memory block
* before calling _fill_xrender_bitmap
*
* it also returns -1 in case of error (e.g. incompatible arguments,
* like trying to convert a gray bitmap into a monochrome one)
*/
static int
_compute_xrender_bitmap_size(FT_Bitmap *target,
FT_GlyphSlot slot,
FT_Render_Mode mode)
{
FT_Bitmap *ftbit;
int width, height, pitch;
if (slot->format != FT_GLYPH_FORMAT_BITMAP)
return -1;
/* compute the size of the final bitmap */
ftbit = &slot->bitmap;
width = ftbit->width;
height = ftbit->rows;
pitch = (width + 3) & ~3;
switch (ftbit->pixel_mode) {
case FT_PIXEL_MODE_MONO:
if (mode == FT_RENDER_MODE_MONO) {
pitch = (((width + 31) & ~31) >> 3);
break;
}
/* fall-through */
case FT_PIXEL_MODE_GRAY:
if (mode == FT_RENDER_MODE_LCD ||
mode == FT_RENDER_MODE_LCD_V)
{
/* each pixel is replicated into a 32-bit ARGB value */
pitch = width * 4;
}
break;
case FT_PIXEL_MODE_LCD:
if (mode != FT_RENDER_MODE_LCD)
return -1;
/* horz pixel triplets are packed into 32-bit ARGB values */
width /= 3;
pitch = width * 4;
break;
case FT_PIXEL_MODE_LCD_V:
if (mode != FT_RENDER_MODE_LCD_V)
return -1;
/* vert pixel triplets are packed into 32-bit ARGB values */
height /= 3;
pitch = width * 4;
break;
default: /* unsupported source format */
return -1;
}
target->width = width;
target->rows = height;
target->pitch = pitch;
target->buffer = NULL;
return pitch * height;
}
/* this functions converts the glyph bitmap found in a FT_GlyphSlot
* into a different format (see _compute_xrender_bitmap_size)
*
* you should call this function after _compute_xrender_bitmap_size
*
* target :: target bitmap descriptor. Note that its 'buffer' pointer
* must point to memory allocated by the caller
*
* slot :: the glyph slot containing the source bitmap
*
* mode :: the requested final rendering mode
*
* bgr :: boolean, set if BGR or VBGR pixel ordering is needed
*/
static void
_fill_xrender_bitmap(FT_Bitmap *target,
FT_GlyphSlot slot,
FT_Render_Mode mode,
int bgr)
{
FT_Bitmap *ftbit = &slot->bitmap;
unsigned char *srcLine = ftbit->buffer;
unsigned char *dstLine = target->buffer;
int src_pitch = ftbit->pitch;
int width = target->width;
int height = target->rows;
int pitch = target->pitch;
int subpixel;
int h;
subpixel = (mode == FT_RENDER_MODE_LCD ||
mode == FT_RENDER_MODE_LCD_V);
if (src_pitch < 0)
srcLine -= src_pitch * (ftbit->rows - 1);
target->pixel_mode = ftbit->pixel_mode;
switch (ftbit->pixel_mode) {
case FT_PIXEL_MODE_MONO:
if (subpixel) {
/* convert mono to ARGB32 values */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
for (x = 0; x < width; x++) {
if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
((unsigned int *) dstLine)[x] = 0xffffffffU;
}
}
target->pixel_mode = FT_PIXEL_MODE_LCD;
} else if (mode == FT_RENDER_MODE_NORMAL) {
/* convert mono to 8-bit gray */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
for (x = 0; x < width; x++) {
if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
dstLine[x] = 0xff;
}
}
target->pixel_mode = FT_PIXEL_MODE_GRAY;
} else {
/* copy mono to mono */
int bytes = (width + 7) >> 3;
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
memcpy (dstLine, srcLine, bytes);
}
break;
case FT_PIXEL_MODE_GRAY:
if (subpixel) {
/* convert gray to ARGB32 values */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
unsigned int *dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++) {
unsigned int pix = srcLine[x];
pix |= (pix << 8);
pix |= (pix << 16);
dst[x] = pix;
}
}
target->pixel_mode = FT_PIXEL_MODE_LCD;
} else {
/* copy gray into gray */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
memcpy (dstLine, srcLine, width);
}
break;
case FT_PIXEL_MODE_LCD:
if (!bgr) {
/* convert horizontal RGB into ARGB32 */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
unsigned char *src = srcLine;
unsigned int *dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++, src += 3) {
unsigned int pix;
pix = ((unsigned int)src[0] << 16) |
((unsigned int)src[1] << 8) |
((unsigned int)src[2] ) |
((unsigned int)src[1] << 24) ;
dst[x] = pix;
}
}
} else {
/* convert horizontal BGR into ARGB32 */
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
int x;
unsigned char *src = srcLine;
unsigned int *dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++, src += 3) {
unsigned int pix;
pix = ((unsigned int)src[2] << 16) |
((unsigned int)src[1] << 8) |
((unsigned int)src[0] ) |
((unsigned int)src[1] << 24) ;
dst[x] = pix;
}
}
}
break;
default: /* FT_PIXEL_MODE_LCD_V */
/* convert vertical RGB into ARGB32 */
if (!bgr) {
for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
int x;
unsigned char* src = srcLine;
unsigned int* dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++, src += 1) {
unsigned int pix;
pix = ((unsigned int)src[0] << 16) |
((unsigned int)src[src_pitch] << 8) |
((unsigned int)src[src_pitch*2] ) |
((unsigned int)src[src_pitch] << 24) ;
dst[x] = pix;
}
}
} else {
for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
int x;
unsigned char *src = srcLine;
unsigned int *dst = (unsigned int *) dstLine;
for (x = 0; x < width; x++, src += 1) {
unsigned int pix;
pix = ((unsigned int)src[src_pitch * 2] << 16) |
((unsigned int)src[src_pitch] << 8) |
((unsigned int)src[0] ) |
((unsigned int)src[src_pitch] << 24) ;
dst[x] = pix;
}
}
}
}
}
/* Fills in val->image with an image surface created from @bitmap
*/
@ -808,6 +1111,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
int width, height, stride;
unsigned char *data;
int format = CAIRO_FORMAT_A8;
cairo_image_surface_t *image;
width = bitmap->width;
height = bitmap->rows;
@ -864,11 +1168,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
case FT_PIXEL_MODE_GRAY:
switch (font_options->antialias) {
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY:
case CAIRO_ANTIALIAS_NONE:
default:
if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
stride = bitmap->pitch;
if (own_buffer) {
data = bitmap->buffer;
@ -879,104 +1179,18 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
memcpy (data, bitmap->buffer, stride * height);
}
format = CAIRO_FORMAT_A8;
break;
case CAIRO_ANTIALIAS_SUBPIXEL: {
int x, y;
unsigned char *in_line, *out_line, *in;
unsigned int *out;
unsigned int red, green, blue;
int rf, gf, bf;
int s;
int o, os;
unsigned char *data_rgba;
unsigned int width_rgba, stride_rgba;
int vmul = 1;
int hmul = 1;
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
default:
width /= 3;
hmul = 3;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
case CAIRO_SUBPIXEL_ORDER_VBGR:
vmul = 3;
height /= 3;
break;
}
/*
* Filter the glyph to soften the color fringes
*/
width_rgba = width;
stride = bitmap->pitch;
stride_rgba = (width_rgba * 4 + 3) & ~3;
data_rgba = calloc (stride_rgba, height);
if (unlikely (data_rgba == NULL)) {
if (own_buffer)
free (bitmap->buffer);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
format = CAIRO_FORMAT_A8;
} else {
/* if we get there, the data from the source bitmap
* really comes from _fill_xrender_bitmap, and is
* made of 32-bit ARGB or ABGR values */
assert (own_buffer != 0);
assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
os = 1;
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_VRGB:
os = stride;
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
default:
rf = 0;
gf = 1;
bf = 2;
break;
case CAIRO_SUBPIXEL_ORDER_VBGR:
os = stride;
case CAIRO_SUBPIXEL_ORDER_BGR:
bf = 0;
gf = 1;
rf = 2;
break;
}
in_line = bitmap->buffer;
out_line = data_rgba;
for (y = 0; y < height; y++)
{
in = in_line;
out = (unsigned int *) out_line;
in_line += stride * vmul;
out_line += stride_rgba;
for (x = 0; x < width * hmul; x += hmul)
{
red = green = blue = 0;
o = 0;
for (s = 0; s < 3; s++)
{
red += filters[rf][s]*in[x+o];
green += filters[gf][s]*in[x+o];
blue += filters[bf][s]*in[x+o];
o += os;
}
red = red / 65536;
green = green / 65536;
blue = blue / 65536;
*out++ = (green << 24) | (red << 16) | (green << 8) | blue;
}
}
/* Images here are stored in native format. The
* backend must convert to its own format as needed
*/
if (own_buffer)
free (bitmap->buffer);
data = data_rgba;
stride = stride_rgba;
format = CAIRO_FORMAT_ARGB32;
break;
}
data = bitmap->buffer;
stride = bitmap->pitch;
format = CAIRO_FORMAT_ARGB32;
}
break;
case FT_PIXEL_MODE_GRAY2:
@ -988,18 +1202,22 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
*surface = (cairo_image_surface_t *)
/* XXX */
*surface = image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (data,
format,
width, height, stride);
if ((*surface)->base.status) {
if (image->base.status) {
free (data);
return (*surface)->base.status;
}
_cairo_image_surface_assume_ownership_of_data ((*surface));
if (format == CAIRO_FORMAT_ARGB32)
pixman_image_set_component_alpha (image->pixman_image, TRUE);
_cairo_debug_check_image_surface_is_defined (&(*surface)->base);
_cairo_image_surface_assume_ownership_of_data (image);
_cairo_debug_check_image_surface_is_defined (&image->base);
return CAIRO_STATUS_SUCCESS;
}
@ -1024,16 +1242,59 @@ _render_glyph_outline (FT_Face face,
cairo_font_options_t *font_options,
cairo_image_surface_t **surface)
{
int rgba = FC_RGBA_UNKNOWN;
int lcd_filter = FT_LCD_FILTER_LEGACY;
FT_GlyphSlot glyphslot = face->glyph;
FT_Outline *outline = &glyphslot->outline;
FT_Bitmap bitmap;
FT_BBox cbox;
FT_Matrix matrix;
int hmul = 1;
int vmul = 1;
unsigned int width, height, stride;
cairo_bool_t subpixel = FALSE;
unsigned int width, height;
cairo_status_t status;
FT_Error fterror;
FT_Library library = glyphslot->library;
FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
switch (font_options->antialias) {
case CAIRO_ANTIALIAS_NONE:
render_mode = FT_RENDER_MODE_MONO;
break;
case CAIRO_ANTIALIAS_SUBPIXEL:
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
render_mode = FT_RENDER_MODE_LCD;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
case CAIRO_SUBPIXEL_ORDER_VBGR:
render_mode = FT_RENDER_MODE_LCD_V;
break;
}
switch (font_options->lcd_filter) {
case CAIRO_LCD_FILTER_NONE:
lcd_filter = FT_LCD_FILTER_NONE;
break;
case CAIRO_LCD_FILTER_DEFAULT:
case CAIRO_LCD_FILTER_INTRA_PIXEL:
lcd_filter = FT_LCD_FILTER_LEGACY;
break;
case CAIRO_LCD_FILTER_FIR3:
lcd_filter = FT_LCD_FILTER_LIGHT;
break;
case CAIRO_LCD_FILTER_FIR5:
lcd_filter = FT_LCD_FILTER_DEFAULT;
break;
}
break;
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY:
render_mode = FT_RENDER_MODE_NORMAL;
}
FT_Outline_Get_CBox (outline, &cbox);
@ -1044,20 +1305,21 @@ _render_glyph_outline (FT_Face face,
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
stride = (width * hmul + 3) & ~3;
if (width * height == 0) {
cairo_format_t format;
/* Looks like fb handles zero-sized images just fine */
switch (font_options->antialias) {
case CAIRO_ANTIALIAS_NONE:
switch (render_mode) {
case FT_RENDER_MODE_MONO:
format = CAIRO_FORMAT_A1;
break;
case CAIRO_ANTIALIAS_SUBPIXEL:
case FT_RENDER_MODE_LCD:
case FT_RENDER_MODE_LCD_V:
format= CAIRO_FORMAT_ARGB32;
break;
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY:
case FT_RENDER_MODE_LIGHT:
case FT_RENDER_MODE_NORMAL:
case FT_RENDER_MODE_MAX:
default:
format = CAIRO_FORMAT_A8;
break;
@ -1067,75 +1329,74 @@ _render_glyph_outline (FT_Face face,
cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
if ((*surface)->base.status)
return (*surface)->base.status;
} else {
} else {
matrix.xx = matrix.yy = 0x10000L;
matrix.xy = matrix.yx = 0;
int bitmap_size;
switch (font_options->antialias) {
case CAIRO_ANTIALIAS_NONE:
bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
bitmap.num_grays = 1;
stride = ((width + 31) & -32) >> 3;
break;
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY:
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
bitmap.num_grays = 256;
stride = (width + 3) & -4;
break;
case CAIRO_ANTIALIAS_SUBPIXEL:
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
default:
matrix.xx *= 3;
hmul = 3;
subpixel = TRUE;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
case CAIRO_SUBPIXEL_ORDER_VBGR:
matrix.yy *= 3;
vmul = 3;
subpixel = TRUE;
break;
switch (render_mode) {
case FT_RENDER_MODE_LCD:
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
rgba = FC_RGBA_BGR;
} else {
rgba = FC_RGBA_RGB;
}
case FT_RENDER_MODE_LCD_V:
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
rgba = FC_RGBA_VBGR;
} else {
rgba = FC_RGBA_VRGB;
}
break;
case FT_RENDER_MODE_MONO:
case FT_RENDER_MODE_LIGHT:
case FT_RENDER_MODE_NORMAL:
case FT_RENDER_MODE_MAX:
default:
break;
}
FT_Outline_Transform (outline, &matrix);
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
bitmap.num_grays = 256;
stride = (width * hmul + 3) & -4;
}
#if HAVE_FT_LIBRARY_SETLCDFILTER
FT_Library_SetLcdFilter (library, lcd_filter);
#endif
bitmap.pitch = stride;
bitmap.width = width * hmul;
bitmap.rows = height * vmul;
bitmap.buffer = calloc (stride, bitmap.rows);
if (unlikely (bitmap.buffer == NULL))
fterror = FT_Render_Glyph (face->glyph, render_mode);
#if HAVE_FT_LIBRARY_SETLCDFILTER
FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
#endif
if (fterror != 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
bitmap_size = _compute_xrender_bitmap_size (&bitmap,
face->glyph,
render_mode);
if (bitmap_size < 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
bitmap.buffer = calloc (1, bitmap_size);
if (bitmap.buffer == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
free (bitmap.buffer);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
(rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
/* Note:
* _get_bitmap_surface will free bitmap.buffer if there is an error
*/
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
if (unlikely (status))
return status;
}
/*
* Note: the font's coordinate system is upside down from ours, so the
* Y coordinate of the control box needs to be negated. Moreover, device
* offsets are position of glyph origin relative to top left while xMin
* and yMax are offsets of top left relative to origin. Another negation.
*/
cairo_surface_set_device_offset (&(*surface)->base,
floor (-(double) cbox.xMin / 64.0),
floor (+(double) cbox.yMax / 64.0));
/* Note: the font's coordinate system is upside down from ours, so the
* Y coordinate of the control box needs to be negated. Moreover, device
* offsets are position of glyph origin relative to top left while xMin
* and yMax are offsets of top left relative to origin. Another negation.
*/
cairo_surface_set_device_offset (&(*surface)->base,
(double)-glyphslot->bitmap_left,
(double)+glyphslot->bitmap_top);
}
return CAIRO_STATUS_SUCCESS;
}
@ -1207,8 +1468,8 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
original_to_transformed = *shape;
cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
orig_width = cairo_image_surface_get_width (&(*surface)->base);
orig_height = cairo_image_surface_get_height (&(*surface)->base);
orig_width = (*surface)->width;
orig_height = (*surface)->height;
cairo_matrix_translate (&original_to_transformed,
-origin_x, -origin_y);
@ -1246,9 +1507,8 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
original_to_transformed.x0 -= x_min;
original_to_transformed.y0 -= y_min;
/* Create the transformed bitmap
*/
width = x_max - x_min;
/* Create the transformed bitmap */
width = x_max - x_min;
height = y_max - y_min;
transformed_to_original = original_to_transformed;
@ -1256,30 +1516,19 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
if (unlikely (status))
return status;
/* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
width = (width + 3) & ~3;
image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
if (unlikely (image->status))
return image->status;
/* Initialize it to empty
*/
status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
0, 0,
width, height);
if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
}
/* Draw the original bitmap transformed into the new bitmap
*/
_cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
status = _cairo_surface_paint (image, CAIRO_OPERATOR_OVER,
&pattern.base, NULL);
status = _cairo_surface_paint (image,
CAIRO_OPERATOR_SOURCE,
&pattern.base,
NULL);
_cairo_pattern_fini (&pattern.base);
@ -1355,6 +1604,7 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
if (antialias) {
cairo_subpixel_order_t subpixel_order;
int lcd_filter;
/* disable hinting if requested */
if (FcPatternGetBool (pattern,
@ -1390,6 +1640,25 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
}
if (FcPatternGetInteger (pattern,
FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
{
switch (lcd_filter) {
case FC_LCD_NONE:
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
break;
case FC_LCD_DEFAULT:
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
break;
case FC_LCD_LIGHT:
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
break;
case FC_LCD_LEGACY:
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
break;
}
}
#ifdef FC_HINT_STYLE
if (FcPatternGetInteger (pattern,
FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
@ -1491,6 +1760,12 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
options->base.hint_style = CAIRO_HINT_STYLE_NONE;
if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
options->base.lcd_filter = other->base.lcd_filter;
if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
load_flags |= FT_LOAD_NO_HINTING;
@ -1514,11 +1789,11 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
load_target |= FT_LOAD_TARGET_LCD;
load_target = FT_LOAD_TARGET_LCD;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
case CAIRO_SUBPIXEL_ORDER_VBGR:
load_target |= FT_LOAD_TARGET_LCD_V;
load_target = FT_LOAD_TARGET_LCD_V;
break;
}
}
@ -2517,6 +2792,34 @@ _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
}
}
if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
{
if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
{
int lcd_filter;
switch (options->lcd_filter) {
case CAIRO_LCD_FILTER_NONE:
lcd_filter = FT_LCD_FILTER_NONE;
break;
case CAIRO_LCD_FILTER_DEFAULT:
case CAIRO_LCD_FILTER_INTRA_PIXEL:
lcd_filter = FT_LCD_FILTER_LEGACY;
break;
case CAIRO_LCD_FILTER_FIR3:
lcd_filter = FT_LCD_FILTER_LIGHT;
break;
default:
case CAIRO_LCD_FILTER_FIR5:
lcd_filter = FT_LCD_FILTER_DEFAULT;
break;
}
if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
}
if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
{
if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
@ -2638,13 +2941,11 @@ _cairo_ft_resolve_pattern (FcPattern *pattern,
}
status = _cairo_ft_unscaled_font_create_for_pattern (resolved, &unscaled);
if (unlikely (status)) {
if (unlikely (status || unscaled == NULL)) {
font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
goto FREE_RESOLVED;
}
assert (unscaled != NULL);
_get_pattern_ft_options (resolved, &ft_options);
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
_cairo_unscaled_font_destroy (&unscaled->base);

View File

@ -12,7 +12,7 @@
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*

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