mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 04:27:41 +00:00
Merge m-c to fx-team.
This commit is contained in:
commit
93007c3658
@ -723,6 +723,15 @@ public:
|
||||
*/
|
||||
bool HasNumericValue() const;
|
||||
|
||||
/**
|
||||
* Return true if the accessible state change is processed by handling proper
|
||||
* DOM UI event, if otherwise then false. For example, HTMLCheckboxAccessible
|
||||
* process nsIDocumentObserver::ContentStateChanged instead
|
||||
* 'CheckboxStateChange' event.
|
||||
*/
|
||||
bool NeedsDOMUIEvent() const
|
||||
{ return !(mStateFlags & eIgnoreDOMUIEvent); }
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
@ -789,6 +798,7 @@ protected:
|
||||
eSharedNode = 1 << 2, // accessible shares DOM node from another accessible
|
||||
eNotNodeMapEntry = 1 << 3, // accessible shouldn't be in document node map
|
||||
eHasNumericValue = 1 << 4, // accessible has a numeric value
|
||||
eIgnoreDOMUIEvent = 1 << 5, // don't process DOM UI events for a11y events
|
||||
|
||||
eLastStateFlag = eHasNumericValue
|
||||
};
|
||||
|
@ -1158,7 +1158,13 @@ DocAccessible::ContentStateChanged(nsIDocument* aDocument,
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccSelChangeEvent(widget, accessible, selChangeType);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(accessible, states::CHECKED,
|
||||
aContent->AsElement()->State().HasState(NS_EVENT_STATE_CHECKED));
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
if (aStateMask.HasState(NS_EVENT_STATE_INVALID)) {
|
||||
|
@ -21,7 +21,9 @@ public:
|
||||
ProgressMeterAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
LeafAccessible(aContent, aDoc)
|
||||
{
|
||||
mStateFlags |= eHasNumericValue;
|
||||
// Ignore 'ValueChange' DOM event in lieu of @value attribute change
|
||||
// notifications.
|
||||
mStateFlags |= eHasNumericValue | eIgnoreDOMUIEvent;
|
||||
mType = eProgressType;
|
||||
}
|
||||
|
||||
|
@ -310,16 +310,13 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
|
||||
if (eventType.EqualsLiteral("RadioStateChange")) {
|
||||
uint64_t state = accessible->State();
|
||||
|
||||
// radiogroup in prefWindow is exposed as a list,
|
||||
// and panebutton is exposed as XULListitem in A11y.
|
||||
// XULListitemAccessible::GetStateInternal uses STATE_SELECTED in this case,
|
||||
// so we need to check states::SELECTED also.
|
||||
bool isEnabled = (state & (states::CHECKED | states::SELECTED)) != 0;
|
||||
|
||||
nsRefPtr<AccEvent> accEvent =
|
||||
new AccStateChangeEvent(accessible, states::CHECKED, isEnabled);
|
||||
nsEventShell::FireEvent(accEvent);
|
||||
if (accessible->NeedsDOMUIEvent()) {
|
||||
nsRefPtr<AccEvent> accEvent =
|
||||
new AccStateChangeEvent(accessible, states::CHECKED, isEnabled);
|
||||
nsEventShell::FireEvent(accEvent);
|
||||
}
|
||||
|
||||
if (isEnabled) {
|
||||
FocusMgr()->ActiveItemChanged(accessible);
|
||||
@ -333,14 +330,14 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
}
|
||||
|
||||
if (eventType.EqualsLiteral("CheckboxStateChange")) {
|
||||
uint64_t state = accessible->State();
|
||||
if (accessible->NeedsDOMUIEvent()) {
|
||||
uint64_t state = accessible->State();
|
||||
bool isEnabled = !!(state & states::CHECKED);
|
||||
|
||||
bool isEnabled = !!(state & states::CHECKED);
|
||||
|
||||
nsRefPtr<AccEvent> accEvent =
|
||||
new AccStateChangeEvent(accessible, states::CHECKED, isEnabled);
|
||||
|
||||
nsEventShell::FireEvent(accEvent);
|
||||
nsRefPtr<AccEvent> accEvent =
|
||||
new AccStateChangeEvent(accessible, states::CHECKED, isEnabled);
|
||||
nsEventShell::FireEvent(accEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -455,14 +452,10 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
||||
logging::ActiveItemChangeCausedBy("DOMMenuBarInactive", accessible);
|
||||
#endif
|
||||
}
|
||||
else if (eventType.EqualsLiteral("ValueChange")) {
|
||||
|
||||
//We don't process 'ValueChange' events for progress meters since we listen
|
||||
//@value attribute change for them.
|
||||
if (!accessible->IsProgress()) {
|
||||
targetDocument->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
accessible);
|
||||
}
|
||||
else if (accessible->NeedsDOMUIEvent() &&
|
||||
eventType.EqualsLiteral("ValueChange")) {
|
||||
targetDocument->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
accessible);
|
||||
}
|
||||
#ifdef DEBUG_DRAGDROPSTART
|
||||
else if (eventType.EqualsLiteral("mouseover")) {
|
||||
|
@ -39,12 +39,6 @@ using namespace mozilla::a11y;
|
||||
// HTMLCheckboxAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HTMLCheckboxAccessible::
|
||||
HTMLCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
LeafAccessible(aContent, aDoc)
|
||||
{
|
||||
}
|
||||
|
||||
role
|
||||
HTMLCheckboxAccessible::NativeRole()
|
||||
{
|
||||
@ -119,12 +113,6 @@ HTMLCheckboxAccessible::IsWidget() const
|
||||
// HTMLRadioButtonAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HTMLRadioButtonAccessible::
|
||||
HTMLRadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
RadioButtonAccessible(aContent, aDoc)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t
|
||||
HTMLRadioButtonAccessible::NativeState()
|
||||
{
|
||||
|
@ -26,7 +26,13 @@ class HTMLCheckboxAccessible : public LeafAccessible
|
||||
public:
|
||||
enum { eAction_Click = 0 };
|
||||
|
||||
HTMLCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
|
||||
HTMLCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
LeafAccessible(aContent, aDoc)
|
||||
{
|
||||
// Ignore "CheckboxStateChange" DOM event in lieu of document observer
|
||||
// state change notification.
|
||||
mStateFlags |= eIgnoreDOMUIEvent;
|
||||
}
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName);
|
||||
@ -51,7 +57,13 @@ class HTMLRadioButtonAccessible : public RadioButtonAccessible
|
||||
{
|
||||
|
||||
public:
|
||||
HTMLRadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc);
|
||||
HTMLRadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
RadioButtonAccessible(aContent, aDoc)
|
||||
{
|
||||
// Ignore "RadioStateChange" DOM event in lieu of document observer
|
||||
// state change notification.
|
||||
mStateFlags |= eIgnoreDOMUIEvent;
|
||||
}
|
||||
|
||||
// Accessible
|
||||
virtual uint64_t NativeState();
|
||||
|
@ -72,6 +72,26 @@
|
||||
};
|
||||
}
|
||||
|
||||
function changeCheckInput(aID, aIsChecked)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
|
||||
this.eventSeq = [
|
||||
new stateChangeChecker(STATE_CHECKED, false, aIsChecked, this.DOMNode)
|
||||
];
|
||||
|
||||
this.invoke = function changeCheckInput_invoke()
|
||||
{
|
||||
this.DOMNode.checked = aIsChecked;
|
||||
}
|
||||
|
||||
this.getID = function changeCheckInput_getID()
|
||||
{
|
||||
return "change checked state to '" + aIsChecked + "' for " +
|
||||
prettyName(aID);
|
||||
}
|
||||
}
|
||||
|
||||
function stateChangeOnFileInput(aID, aAttr, aValue,
|
||||
aState, aIsExtraState, aIsEnabled)
|
||||
{
|
||||
@ -154,6 +174,12 @@
|
||||
// invalid state change
|
||||
gQueue.push(new invalidInput("email"));
|
||||
|
||||
// checked state change
|
||||
gQueue.push(new changeCheckInput("checkbox", true));
|
||||
gQueue.push(new changeCheckInput("checkbox", false));
|
||||
gQueue.push(new changeCheckInput("radio", true));
|
||||
gQueue.push(new changeCheckInput("radio", false));
|
||||
|
||||
// file input inherited state changes
|
||||
gQueue.push(new stateChangeOnFileInput("file", "aria-busy", "true",
|
||||
STATE_BUSY, false, true));
|
||||
@ -180,17 +206,22 @@
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=564471"
|
||||
title="Make state change events async">
|
||||
Mozilla Bug 564471
|
||||
</a><br>
|
||||
Bug 564471
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=555728"
|
||||
title="Fire a11y event based on HTML5 constraint validation">
|
||||
Mozilla Bug 555728
|
||||
Bug 555728
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
|
||||
title="File input control should be propogate states to descendants">
|
||||
Mozilla Bug 699017
|
||||
Bug 699017
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=788389"
|
||||
title="Fire statechange event whenever checked state is changed not depending on focused state">
|
||||
Bug 788389
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
@ -204,6 +235,9 @@
|
||||
|
||||
<input id="email" type='email'>
|
||||
|
||||
<input id="checkbox" type="checkbox">
|
||||
<input id="radio" type="radio">
|
||||
|
||||
<input id="file" type="file">
|
||||
|
||||
<div id="div"></div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "f02326672a650ce8f549562e22468fb0e0a5dcf8",
|
||||
"revision": "7669b3265def0eed0473acd938897704007afaf3",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
[
|
||||
{
|
||||
"size": 117247732,
|
||||
"digest": "16e74278e4e9b0d710df77d68af1677c91823dccfc611ab00ee617298a63787f9f9892bd1a41eccb8d45fb18d61bfda0dbd1de88f1861c14b4b44da3b94a4eca",
|
||||
"size": 114839868,
|
||||
"digest": "4754612c52330f4d25a250eb52adbf245950e3411a46f45836950b96fdff99e37e3563667d9a0069a7097f3900af3710d9e94010a26bf2e7e1a27c97f37ef447",
|
||||
"algorithm": "sha512",
|
||||
"filename": "backup-leo.tar.xz"
|
||||
},
|
||||
|
@ -10,16 +10,18 @@ relativesrcdir = @relativesrcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
# Disabled for intermittent failures (bug 880739)
|
||||
# browser_context_menu_tests.js \
|
||||
# browser_context_menu_tests_01.html \
|
||||
# browser_context_menu_tests_02.html \
|
||||
# browser_context_menu_tests_03.html \
|
||||
|
||||
MOCHITEST_METRO_FILES = \
|
||||
head.js \
|
||||
browser_urlbar.js \
|
||||
browser_bookmarks.js \
|
||||
browser_canonizeURL.js \
|
||||
browser_circular_progress_indicator.js \
|
||||
browser_context_menu_tests.js \
|
||||
browser_context_menu_tests_01.html \
|
||||
browser_context_menu_tests_02.html \
|
||||
browser_context_menu_tests_03.html \
|
||||
browser_context_ui.js \
|
||||
browser_downloads.js \
|
||||
browser_findbar.js \
|
||||
|
@ -862,23 +862,6 @@ public:
|
||||
*/
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const = 0;
|
||||
|
||||
/**
|
||||
* Checks if a node has the same ownerDocument as this one. Note that this
|
||||
* actually compares nodeinfo managers because nodes always have one, even
|
||||
* when they don't have an ownerDocument. If this function returns true
|
||||
* it doesn't mean that the nodes actually have an ownerDocument.
|
||||
*
|
||||
* @param aOther Other node to check
|
||||
* @return Whether the owner documents of this node and of aOther are the
|
||||
* same.
|
||||
*/
|
||||
bool HasSameOwnerDoc(nsINode *aOther)
|
||||
{
|
||||
// We compare nodeinfo managers because nodes always have one, even when
|
||||
// they don't have an ownerDocument.
|
||||
return mNodeInfo->NodeInfoManager() == aOther->mNodeInfo->NodeInfoManager();
|
||||
}
|
||||
|
||||
// This class can be extended by subclasses that wish to store more
|
||||
// information in the slots.
|
||||
class nsSlots
|
||||
|
@ -900,7 +900,7 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
bool aCompileEventHandlers)
|
||||
{
|
||||
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
||||
NS_PRECONDITION(HasSameOwnerDoc(NODE_FROM(aParent, aDocument)),
|
||||
NS_PRECONDITION((NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc()),
|
||||
"Must have the same owner document");
|
||||
NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
|
||||
"aDocument must be current doc of aParent");
|
||||
|
@ -283,7 +283,7 @@ nsDOMAttributeMap::SetNamedItemInternal(Attr& aAttr,
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
if (!mContent->HasSameOwnerDoc(&aAttr)) {
|
||||
if (mContent->OwnerDoc() != aAttr.OwnerDoc()) {
|
||||
nsCOMPtr<nsINode> adoptedNode =
|
||||
mContent->OwnerDoc()->AdoptNode(aAttr, aError);
|
||||
if (aError.Failed()) {
|
||||
|
@ -440,7 +440,7 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
bool aCompileEventHandlers)
|
||||
{
|
||||
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
||||
NS_PRECONDITION(HasSameOwnerDoc(NODE_FROM(aParent, aDocument)),
|
||||
NS_PRECONDITION(NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc(),
|
||||
"Must have the same owner document");
|
||||
NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
|
||||
"aDocument must be current doc of aParent");
|
||||
|
@ -631,6 +631,7 @@ GK_ATOM(odd, "odd")
|
||||
GK_ATOM(OFF, "OFF")
|
||||
GK_ATOM(ol, "ol")
|
||||
GK_ATOM(omitXmlDeclaration, "omit-xml-declaration")
|
||||
GK_ATOM(ona2dpstatuschanged, "ona2dpstatuschanged")
|
||||
GK_ATOM(onabort, "onabort")
|
||||
GK_ATOM(onadapteradded, "onadapteradded")
|
||||
GK_ATOM(onafterprint, "onafterprint")
|
||||
@ -713,6 +714,7 @@ GK_ATOM(onget, "onget")
|
||||
GK_ATOM(onhashchange, "onhashchange")
|
||||
GK_ATOM(onheadphoneschange, "onheadphoneschange")
|
||||
GK_ATOM(onheld, "onheld")
|
||||
GK_ATOM(onhfpstatuschanged, "onhfpstatuschanged")
|
||||
GK_ATOM(onholding, "onholding")
|
||||
GK_ATOM(oniccinfochange, "oniccinfochange")
|
||||
GK_ATOM(onicccardlockerror, "onicccardlockerror")
|
||||
@ -756,6 +758,7 @@ GK_ATOM(onoverflowchanged, "onoverflowchanged")
|
||||
GK_ATOM(onpagehide, "onpagehide")
|
||||
GK_ATOM(onpageshow, "onpageshow")
|
||||
GK_ATOM(onpaint, "onpaint")
|
||||
GK_ATOM(onpairedstatuschanged, "onpairedstatuschanged")
|
||||
GK_ATOM(onpaste, "onpaste")
|
||||
GK_ATOM(onpopuphidden, "onpopuphidden")
|
||||
GK_ATOM(onpopuphiding, "onpopuphiding")
|
||||
@ -769,6 +772,7 @@ GK_ATOM(onreset, "onreset")
|
||||
GK_ATOM(onresuming, "onresuming")
|
||||
GK_ATOM(onMozBeforeResize, "onMozBeforeResize")
|
||||
GK_ATOM(onresize, "onresize")
|
||||
GK_ATOM(onscostatuschanged, "onscostatuschanged")
|
||||
GK_ATOM(onscroll, "onscroll")
|
||||
GK_ATOM(onselect, "onselect")
|
||||
GK_ATOM(onsending, "onsending")
|
||||
|
@ -1318,7 +1318,7 @@ AdoptNodeIntoOwnerDoc(nsINode *aParent, nsINode *aNode)
|
||||
NS_ASSERTION(aParent->OwnerDoc() == doc,
|
||||
"ownerDoc chainged while adopting");
|
||||
NS_ASSERTION(adoptedNode == node, "Uh, adopt node changed nodes?");
|
||||
NS_ASSERTION(aParent->HasSameOwnerDoc(aNode),
|
||||
NS_ASSERTION(aParent->OwnerDoc() == aNode->OwnerDoc(),
|
||||
"ownerDocument changed again after adopting!");
|
||||
|
||||
return NS_OK;
|
||||
@ -1340,7 +1340,7 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
|
||||
|
||||
if (!HasSameOwnerDoc(aKid)) {
|
||||
if (OwnerDoc() != aKid->OwnerDoc()) {
|
||||
rv = AdoptNodeIntoOwnerDoc(this, aKid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -1953,7 +1953,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
||||
// DocumentType nodes are the only nodes that can have a null
|
||||
// ownerDocument according to the DOM spec, and we need to allow
|
||||
// inserting them w/o calling AdoptNode().
|
||||
if (!HasSameOwnerDoc(newContent)) {
|
||||
if (OwnerDoc() != newContent->OwnerDoc()) {
|
||||
aError = AdoptNodeIntoOwnerDoc(this, aNewChild);
|
||||
if (aError.Failed()) {
|
||||
return nullptr;
|
||||
|
@ -476,52 +476,43 @@ nsColorPickerShownCallback::Done(const nsAString& aColor)
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsColorPickerShownCallback, nsIColorPickerShownCallback)
|
||||
|
||||
HTMLInputElement::AsyncClickHandler::AsyncClickHandler(HTMLInputElement* aInput)
|
||||
: mInput(aInput)
|
||||
bool
|
||||
HTMLInputElement::IsPopupBlocked() const
|
||||
{
|
||||
nsPIDOMWindow* win = aInput->OwnerDoc()->GetWindow();
|
||||
if (win) {
|
||||
mPopupControlState = win->GetPopupControlState();
|
||||
nsCOMPtr<nsPIDOMWindow> win = OwnerDoc()->GetWindow();
|
||||
MOZ_ASSERT(win, "window should not be null");
|
||||
if (!win) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::AsyncClickHandler::Run()
|
||||
{
|
||||
if (mInput->GetType() == NS_FORM_INPUT_FILE) {
|
||||
return InitFilePicker();
|
||||
} else if (mInput->GetType() == NS_FORM_INPUT_COLOR) {
|
||||
return InitColorPicker();
|
||||
// Check if page is allowed to open the popup
|
||||
if (win->GetPopupControlState() <= openControlled) {
|
||||
return false;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIPopupWindowManager> pm = do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID);
|
||||
if (!pm) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t permission;
|
||||
pm->TestPermission(OwnerDoc()->NodePrincipal(), &permission);
|
||||
return permission == nsIPopupWindowManager::DENY_POPUP;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLInputElement::AsyncClickHandler::InitColorPicker()
|
||||
HTMLInputElement::InitColorPicker()
|
||||
{
|
||||
// Get parent nsPIDOMWindow object.
|
||||
nsCOMPtr<nsIDocument> doc = mInput->OwnerDoc();
|
||||
nsCOMPtr<nsIDocument> doc = OwnerDoc();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = doc->GetWindow();
|
||||
if (!win) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Check if page is allowed to open the popup
|
||||
if (mPopupControlState > openControlled) {
|
||||
nsCOMPtr<nsIPopupWindowManager> pm =
|
||||
do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID);
|
||||
|
||||
if (!pm) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t permission;
|
||||
pm->TestPermission(doc->NodePrincipal(), &permission);
|
||||
if (permission == nsIPopupWindowManager::DENY_POPUP) {
|
||||
nsGlobalWindow::FirePopupBlockedEvent(doc, win, nullptr, EmptyString(), EmptyString());
|
||||
return NS_OK;
|
||||
}
|
||||
if (IsPopupBlocked()) {
|
||||
nsGlobalWindow::FirePopupBlockedEvent(doc, win, nullptr, EmptyString(), EmptyString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get Loc title
|
||||
@ -535,42 +526,30 @@ HTMLInputElement::AsyncClickHandler::InitColorPicker()
|
||||
}
|
||||
|
||||
nsAutoString initialValue;
|
||||
mInput->GetValueInternal(initialValue);
|
||||
GetValueInternal(initialValue);
|
||||
nsresult rv = colorPicker->Init(win, title, initialValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIColorPickerShownCallback> callback =
|
||||
new nsColorPickerShownCallback(mInput, colorPicker);
|
||||
new nsColorPickerShownCallback(this, colorPicker);
|
||||
|
||||
return colorPicker->Open(callback);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLInputElement::AsyncClickHandler::InitFilePicker()
|
||||
HTMLInputElement::InitFilePicker()
|
||||
{
|
||||
// Get parent nsPIDOMWindow object.
|
||||
nsCOMPtr<nsIDocument> doc = mInput->OwnerDoc();
|
||||
nsCOMPtr<nsIDocument> doc = OwnerDoc();
|
||||
|
||||
nsPIDOMWindow* win = doc->GetWindow();
|
||||
nsCOMPtr<nsPIDOMWindow> win = doc->GetWindow();
|
||||
if (!win) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Check if page is allowed to open the popup
|
||||
if (mPopupControlState > openControlled) {
|
||||
nsCOMPtr<nsIPopupWindowManager> pm =
|
||||
do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID);
|
||||
|
||||
if (!pm) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t permission;
|
||||
pm->TestPermission(doc->NodePrincipal(), &permission);
|
||||
if (permission == nsIPopupWindowManager::DENY_POPUP) {
|
||||
nsGlobalWindow::FirePopupBlockedEvent(doc, win, nullptr, EmptyString(), EmptyString());
|
||||
return NS_OK;
|
||||
}
|
||||
if (IsPopupBlocked()) {
|
||||
nsGlobalWindow::FirePopupBlockedEvent(doc, win, nullptr, EmptyString(), EmptyString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get Loc title
|
||||
@ -582,7 +561,7 @@ HTMLInputElement::AsyncClickHandler::InitFilePicker()
|
||||
if (!filePicker)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
bool multi = mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
|
||||
bool multi = HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
|
||||
|
||||
nsresult rv = filePicker->Init(win, title,
|
||||
multi
|
||||
@ -590,8 +569,8 @@ HTMLInputElement::AsyncClickHandler::InitFilePicker()
|
||||
: static_cast<int16_t>(nsIFilePicker::modeOpen));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) {
|
||||
mInput->SetFilePickerFiltersFromAccept(filePicker);
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) {
|
||||
SetFilePickerFiltersFromAccept(filePicker);
|
||||
} else {
|
||||
filePicker->AppendFilters(nsIFilePicker::filterAll);
|
||||
}
|
||||
@ -599,10 +578,10 @@ HTMLInputElement::AsyncClickHandler::InitFilePicker()
|
||||
// Set default directry and filename
|
||||
nsAutoString defaultName;
|
||||
|
||||
const nsCOMArray<nsIDOMFile>& oldFiles = mInput->GetFilesInternal();
|
||||
const nsCOMArray<nsIDOMFile>& oldFiles = GetFilesInternal();
|
||||
|
||||
nsCOMPtr<nsIFilePickerShownCallback> callback =
|
||||
new HTMLInputElement::nsFilePickerShownCallback(mInput, filePicker, multi);
|
||||
new HTMLInputElement::nsFilePickerShownCallback(this, filePicker, multi);
|
||||
|
||||
if (oldFiles.Count()) {
|
||||
nsString path;
|
||||
@ -2596,13 +2575,6 @@ HTMLInputElement::SelectAll(nsPresContext* aPresContext)
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::FireAsyncClickHandler()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event = new AsyncClickHandler(this);
|
||||
return NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLInputElement::NeedToInitializeEditorForEvent(nsEventChainPreVisitor& aVisitor) const
|
||||
{
|
||||
@ -2906,8 +2878,8 @@ HTMLInputElement::ShouldPreventDOMActivateDispatch(EventTarget* aOriginalTarget)
|
||||
nsGkAtoms::button, eCaseMatters);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::MaybeFireAsyncClickHandler(nsEventChainPostVisitor& aVisitor)
|
||||
nsresult
|
||||
HTMLInputElement::MaybeInitPickers(nsEventChainPostVisitor& aVisitor)
|
||||
{
|
||||
// Open a file picker when we receive a click on a <input type='file'>, or
|
||||
// open a color picker when we receive a click on a <input type='color'>.
|
||||
@ -2915,12 +2887,17 @@ HTMLInputElement::MaybeFireAsyncClickHandler(nsEventChainPostVisitor& aVisitor)
|
||||
// - preventDefault() has not been called (or something similar);
|
||||
// - it's the left mouse button.
|
||||
// We do not prevent non-trusted click because authors can already use
|
||||
// .click(). However, the file picker will follow the rules of popup-blocking.
|
||||
if ((mType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_COLOR) &&
|
||||
NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
|
||||
// .click(). However, the pickers will follow the rules of popup-blocking.
|
||||
if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) &&
|
||||
!aVisitor.mEvent->mFlags.mDefaultPrevented) {
|
||||
FireAsyncClickHandler();
|
||||
if (mType == NS_FORM_INPUT_FILE) {
|
||||
return InitFilePicker();
|
||||
}
|
||||
if (mType == NS_FORM_INPUT_COLOR) {
|
||||
return InitColorPicker();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -2928,9 +2905,8 @@ HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
{
|
||||
if (!aVisitor.mPresContext) {
|
||||
// Hack alert! In order to open file picker even in case the element isn't
|
||||
// in document, fire click handler even without PresContext.
|
||||
MaybeFireAsyncClickHandler(aVisitor);
|
||||
return NS_OK;
|
||||
// in document, try to init picker even without PresContext.
|
||||
return MaybeInitPickers(aVisitor);
|
||||
}
|
||||
|
||||
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
|
||||
@ -3333,9 +3309,7 @@ HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
PostHandleEventForRangeThumb(aVisitor);
|
||||
}
|
||||
|
||||
MaybeFireAsyncClickHandler(aVisitor);
|
||||
|
||||
return rv;
|
||||
return MaybeInitPickers(aVisitor);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -222,9 +222,6 @@ public:
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
|
||||
|
||||
void MaybeFireAsyncClickHandler(nsEventChainPostVisitor& aVisitor);
|
||||
NS_IMETHOD FireAsyncClickHandler();
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLInputElement,
|
||||
nsGenericHTMLFormElementWithState)
|
||||
|
||||
@ -1083,6 +1080,25 @@ protected:
|
||||
*/
|
||||
bool ShouldPreventDOMActivateDispatch(EventTarget* aOriginalTarget);
|
||||
|
||||
/**
|
||||
* Some input type (color and file) let user choose a value using a picker:
|
||||
* this function checks if it is needed, and if so, open the corresponding
|
||||
* picker (color picker or file picker).
|
||||
*/
|
||||
nsresult MaybeInitPickers(nsEventChainPostVisitor& aVisitor);
|
||||
|
||||
nsresult InitFilePicker();
|
||||
nsresult InitColorPicker();
|
||||
|
||||
/**
|
||||
* Use this function before trying to open a picker.
|
||||
* It checks if the page is allowed to open a new pop-up.
|
||||
* If it returns true, you should not create the picker.
|
||||
*
|
||||
* @return true if popup should be blocked, false otherwise
|
||||
*/
|
||||
bool IsPopupBlocked() const;
|
||||
|
||||
nsCOMPtr<nsIControllers> mControllers;
|
||||
|
||||
/*
|
||||
@ -1230,21 +1246,6 @@ private:
|
||||
bool mIsTrusted;
|
||||
};
|
||||
|
||||
class AsyncClickHandler
|
||||
: public nsRunnable
|
||||
{
|
||||
public:
|
||||
AsyncClickHandler(HTMLInputElement* aInput);
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
nsresult InitFilePicker();
|
||||
nsresult InitColorPicker();
|
||||
|
||||
nsRefPtr<HTMLInputElement> mInput;
|
||||
PopupControlState mPopupControlState;
|
||||
};
|
||||
|
||||
class nsFilePickerShownCallback
|
||||
: public nsIFilePickerShownCallback
|
||||
{
|
||||
|
@ -470,11 +470,25 @@ GetHashtableElements(nsTHashtable<nsPtrHashKey<T> >& aHashtable, nsTArray<T*>& a
|
||||
aHashtable.EnumerateEntries(&GetHashtableEntry<T>, &aArray);
|
||||
}
|
||||
|
||||
void
|
||||
AudioContext::ShutdownDecoder()
|
||||
{
|
||||
mDecoder.Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
AudioContext::Shutdown()
|
||||
{
|
||||
Suspend();
|
||||
mDecoder.Shutdown();
|
||||
|
||||
// We need to hold the AudioContext object alive here to make sure that
|
||||
// it doesn't get destroyed before our decoder shutdown runnable has had
|
||||
// a chance to run.
|
||||
nsCOMPtr<nsIRunnable> threadShutdownEvent =
|
||||
NS_NewRunnableMethod(this, &AudioContext::ShutdownDecoder);
|
||||
if (threadShutdownEvent) {
|
||||
NS_DispatchToCurrentThread(threadShutdownEvent);
|
||||
}
|
||||
|
||||
// Stop all audio buffer source nodes, to make sure that they release
|
||||
// their self-references.
|
||||
|
@ -218,6 +218,7 @@ public:
|
||||
|
||||
private:
|
||||
void RemoveFromDecodeQueue(WebAudioDecodeJob* aDecodeJob);
|
||||
void ShutdownDecoder();
|
||||
|
||||
friend struct ::mozilla::WebAudioDecodeJob;
|
||||
|
||||
|
@ -943,7 +943,7 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JS::Handle<JSObject*> global,
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
|
||||
if (!::JS_LookupPropertyWithFlags(cx, global, className.get(), 0, val.address()))
|
||||
if (!::JS_LookupPropertyWithFlags(cx, global, className.get(), 0, &val))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (val.isObject()) {
|
||||
|
@ -284,7 +284,7 @@ nsXBLProtoImpl::ResolveAllFields(JSContext *cx, JS::Handle<JSObject*> obj) const
|
||||
JS::Rooted<JS::Value> dummy(cx);
|
||||
if (!::JS_LookupUCProperty(cx, obj,
|
||||
reinterpret_cast<const jschar*>(name.get()),
|
||||
name.Length(), dummy.address())) {
|
||||
name.Length(), &dummy)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -304,7 +304,7 @@ nsXBLProtoImpl::UndefineFields(JSContext *cx, JS::Handle<JSObject*> obj) const
|
||||
if (::JS_AlreadyHasOwnUCProperty(cx, obj, s, name.Length(), &hasProp) &&
|
||||
hasProp) {
|
||||
JS::Rooted<JS::Value> dummy(cx);
|
||||
::JS_DeleteUCProperty2(cx, obj, s, name.Length(), dummy.address());
|
||||
::JS_DeleteUCProperty2(cx, obj, s, name.Length(), &dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1932,7 +1932,7 @@ nsDOMClassInfo::ResolveConstructor(JSContext *cx, JSObject *aObj,
|
||||
JS::Rooted<JSObject*> global(cx, ::JS_GetGlobalForObject(cx, obj));
|
||||
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
if (!::JS_LookupProperty(cx, global, mData->mName, val.address())) {
|
||||
if (!::JS_LookupProperty(cx, global, mData->mName, &val)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
@ -2601,7 +2601,7 @@ ResolveGlobalName(const nsAString& aName, void* aClosure)
|
||||
JS::Rooted<JS::Value> dummy(closure->cx);
|
||||
bool ok = JS_LookupUCProperty(closure->cx, closure->obj,
|
||||
aName.BeginReading(), aName.Length(),
|
||||
dummy.address());
|
||||
&dummy);
|
||||
if (!ok) {
|
||||
*closure->retval = false;
|
||||
return PL_DHASH_STOP;
|
||||
@ -3411,12 +3411,12 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
|
||||
JSAutoCompartment ac(cx, winobj);
|
||||
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
if (!JS_LookupProperty(cx, winobj, CutPrefix(class_parent_name), val.address())) {
|
||||
if (!JS_LookupProperty(cx, winobj, CutPrefix(class_parent_name), &val)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (val.isObject()) {
|
||||
if (!JS_LookupProperty(cx, &val.toObject(), "prototype", val.address())) {
|
||||
if (!JS_LookupProperty(cx, &val.toObject(), "prototype", &val)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
@ -4233,7 +4233,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
|
||||
if (!::JS_LookupPropertyWithFlagsById(cx, proto, id, flags,
|
||||
pobj.address(), val.address())) {
|
||||
pobj.address(), &val)) {
|
||||
*_retval = JS_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -216,7 +216,7 @@ DOMProxyHandler::delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Rooted<JSObject*> expando(cx);
|
||||
if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = GetExpandoObject(proxy))) {
|
||||
JS::Rooted<Value> v(cx);
|
||||
if (!JS_DeletePropertyById2(cx, expando, id, v.address()) ||
|
||||
if (!JS_DeletePropertyById2(cx, expando, id, &v) ||
|
||||
!JS_ValueToBoolean(cx, v, &b)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -204,7 +204,8 @@ BluetoothA2dpManager::HandleSinkPropertyChanged(const BluetoothSignal& aSignal)
|
||||
// Indicates if a stream is setup to a A2DP sink on the remote device.
|
||||
MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
|
||||
mA2dpConnected = value.get_bool();
|
||||
NotifyStatusChanged();
|
||||
NotifyConnectionStatusChanged();
|
||||
DispatchConnectionStatusChanged();
|
||||
} else if (name.EqualsLiteral("Playing")) {
|
||||
// Indicates if a stream is active to a A2DP sink on the remote device.
|
||||
MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
|
||||
@ -254,7 +255,16 @@ BluetoothA2dpManager::HandleSinkStateChanged(SinkState aState)
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothA2dpManager::NotifyStatusChanged()
|
||||
BluetoothA2dpManager::DispatchConnectionStatusChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
DispatchStatusChangedEvent(
|
||||
NS_LITERAL_STRING(A2DP_STATUS_CHANGED_ID), mDeviceAddress, mA2dpConnected);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothA2dpManager::NotifyConnectionStatusChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -72,12 +72,14 @@ private:
|
||||
void HandleSinkStateChanged(SinkState aState);
|
||||
void HandleShutdown();
|
||||
|
||||
void NotifyStatusChanged();
|
||||
void DispatchConnectionStatusChanged();
|
||||
void NotifyConnectionStatusChanged();
|
||||
|
||||
nsString mDeviceAddress;
|
||||
|
||||
// A2DP data member
|
||||
bool mA2dpConnected;
|
||||
bool mPlaying;
|
||||
nsString mDeviceAddress;
|
||||
SinkState mSinkState;
|
||||
|
||||
// AVRCP data member
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "nsCxPusher.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsIDOMBluetoothDeviceEvent.h"
|
||||
#include "nsIDOMBluetoothStatusChangedEvent.h"
|
||||
#include "nsTArrayHelpers.h"
|
||||
#include "DOMRequest.h"
|
||||
#include "nsThreadUtils.h"
|
||||
@ -333,14 +334,34 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData)
|
||||
false, false, device);
|
||||
DispatchTrustedEvent(event);
|
||||
} else if (aData.name().EqualsLiteral("PropertyChanged")) {
|
||||
NS_ASSERTION(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue,
|
||||
"PropertyChanged: Invalid value type");
|
||||
MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||
const InfallibleTArray<BluetoothNamedValue>& arr =
|
||||
v.get_ArrayOfBluetoothNamedValue();
|
||||
|
||||
NS_ASSERTION(arr.Length() == 1,
|
||||
"Got more than one property in a change message!");
|
||||
MOZ_ASSERT(arr.Length() == 1);
|
||||
SetPropertyByValue(arr[0]);
|
||||
} else if (aData.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID) ||
|
||||
aData.name().EqualsLiteral(HFP_STATUS_CHANGED_ID) ||
|
||||
aData.name().EqualsLiteral(SCO_STATUS_CHANGED_ID) ||
|
||||
aData.name().EqualsLiteral(A2DP_STATUS_CHANGED_ID)) {
|
||||
MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||
const InfallibleTArray<BluetoothNamedValue>& arr =
|
||||
v.get_ArrayOfBluetoothNamedValue();
|
||||
|
||||
MOZ_ASSERT(arr.Length() == 2 &&
|
||||
arr[0].value().type() == BluetoothValue::TnsString &&
|
||||
arr[1].value().type() == BluetoothValue::Tbool);
|
||||
nsString address = arr[0].value().get_nsString();
|
||||
bool status = arr[1].value().get_bool();
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
NS_NewDOMBluetoothStatusChangedEvent(
|
||||
getter_AddRefs(event), this, nullptr, nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMBluetoothStatusChangedEvent> e = do_QueryInterface(event);
|
||||
e->InitBluetoothStatusChangedEvent(aData.name(), false, false,
|
||||
address, status);
|
||||
DispatchTrustedEvent(event);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
nsCString warningMsg;
|
||||
@ -905,3 +926,7 @@ BluetoothAdapter::SendMediaPlayStatus(const JS::Value& aOptions,
|
||||
}
|
||||
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicefound)
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, a2dpstatuschanged)
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, hfpstatuschanged)
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, pairedstatuschanged)
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, scostatuschanged)
|
||||
|
@ -52,12 +52,26 @@ extern bool gBluetoothDebugFlag;
|
||||
#define KEY_ADAPTER "/B2G/bluetooth/adapter"
|
||||
|
||||
/**
|
||||
* When connection status of Bluetooth profiles change, we'll notify observers
|
||||
* of following topics.
|
||||
* When the connection status of a Bluetooth profile is changed, we'll notify
|
||||
* observers which register the following topics.
|
||||
*/
|
||||
#define BLUETOOTH_HFP_STATUS_CHANGED_ID "bluetooth-hfp-status-changed"
|
||||
#define BLUETOOTH_SCO_STATUS_CHANGED_ID "bluetooth-sco-status-changed"
|
||||
#define BLUETOOTH_A2DP_STATUS_CHANGED_ID "bluetooth-a2dp-status-changed"
|
||||
#define BLUETOOTH_A2DP_STATUS_CHANGED_ID "bluetooth-a2dp-status-changed"
|
||||
#define BLUETOOTH_HFP_STATUS_CHANGED_ID "bluetooth-hfp-status-changed"
|
||||
#define BLUETOOTH_SCO_STATUS_CHANGED_ID "bluetooth-sco-status-changed"
|
||||
|
||||
/**
|
||||
* When the connection status of a Bluetooth profile is changed, we'll
|
||||
* distribute one of the following events.
|
||||
*/
|
||||
#define A2DP_STATUS_CHANGED_ID "a2dpstatuschanged"
|
||||
#define HFP_STATUS_CHANGED_ID "hfpstatuschanged"
|
||||
#define SCO_STATUS_CHANGED_ID "scostatuschanged"
|
||||
|
||||
/**
|
||||
* When the pair status of a Bluetooth device is changed, we'll distribute an
|
||||
* event.
|
||||
*/
|
||||
#define PAIRED_STATUS_CHANGED_ID "pairedstatuschanged"
|
||||
|
||||
// Bluetooth address format: xx:xx:xx:xx:xx:xx (or xx_xx_xx_xx_xx_xx)
|
||||
#define BLUETOOTH_ADDRESS_LENGTH 17
|
||||
|
@ -454,21 +454,37 @@ BluetoothHfpManager::Get()
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHfpManager::NotifyStatusChanged(const char* aType)
|
||||
BluetoothHfpManager::DispatchConnectionStatusChanged(const nsAString& aType)
|
||||
{
|
||||
// Broadcast system message to Gaia
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
bool status = false;
|
||||
if (aType.EqualsLiteral(HFP_STATUS_CHANGED_ID)) {
|
||||
status = IsConnected();
|
||||
} else if (aType.EqualsLiteral(SCO_STATUS_CHANGED_ID)) {
|
||||
status = IsScoConnected();
|
||||
} else {
|
||||
BT_WARNING("Wrong type for DispatchConnectionStatusChanged");
|
||||
return;
|
||||
}
|
||||
|
||||
DispatchStatusChangedEvent(aType, mDeviceAddress, status);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHfpManager::NotifyConnectionStatusChanged(const nsAString& aType)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
BluetoothValue v;
|
||||
InfallibleTArray<BluetoothNamedValue> parameters;
|
||||
nsAutoString type, name;
|
||||
type = NS_ConvertUTF8toUTF16(aType);
|
||||
name.AssignLiteral("connected");
|
||||
|
||||
if (type.EqualsLiteral(BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
|
||||
nsString name = NS_LITERAL_STRING("connected");
|
||||
if (aType.EqualsLiteral(BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
|
||||
v = IsConnected();
|
||||
} else if (type.EqualsLiteral(BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
|
||||
} else if (aType.EqualsLiteral(BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
|
||||
v = IsScoConnected();
|
||||
} else {
|
||||
NS_WARNING("Wrong type for NotifyStatusChanged");
|
||||
BT_WARNING("Wrong type for NotifyConnectionStatusChanged");
|
||||
return;
|
||||
}
|
||||
parameters.AppendElement(BluetoothNamedValue(name, v));
|
||||
@ -477,7 +493,7 @@ BluetoothHfpManager::NotifyStatusChanged(const char* aType)
|
||||
v = mDeviceAddress;
|
||||
parameters.AppendElement(BluetoothNamedValue(name, v));
|
||||
|
||||
if (!BroadcastSystemMessage(type, parameters)) {
|
||||
if (!BroadcastSystemMessage(aType, parameters)) {
|
||||
NS_WARNING("Failed to broadcast system message to settings");
|
||||
}
|
||||
|
||||
@ -486,8 +502,9 @@ BluetoothHfpManager::NotifyStatusChanged(const char* aType)
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
NS_ENSURE_TRUE_VOID(obs);
|
||||
|
||||
if (NS_FAILED(obs->NotifyObservers(this, aType, mDeviceAddress.get()))) {
|
||||
NS_WARNING("Failed to notify bluetooth-sco-status-changed observsers!");
|
||||
if (NS_FAILED(obs->NotifyObservers(this, NS_ConvertUTF16toUTF8(aType).get(),
|
||||
mDeviceAddress.get()))) {
|
||||
NS_WARNING("Failed to notify observsers!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1482,7 +1499,8 @@ BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket)
|
||||
// Cache device path for NotifySettings() since we can't get socket address
|
||||
// when a headset disconnect with us
|
||||
mSocket->GetAddress(mDeviceAddress);
|
||||
NotifyStatusChanged(BLUETOOTH_HFP_STATUS_CHANGED_ID);
|
||||
NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
|
||||
DispatchConnectionStatusChanged(NS_LITERAL_STRING(HFP_STATUS_CHANGED_ID));
|
||||
|
||||
ListenSco();
|
||||
|
||||
@ -1537,7 +1555,8 @@ BluetoothHfpManager::OnDisconnect(BluetoothSocket* aSocket)
|
||||
DisconnectSco();
|
||||
|
||||
Listen();
|
||||
NotifyStatusChanged(BLUETOOTH_HFP_STATUS_CHANGED_ID);
|
||||
NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
|
||||
DispatchConnectionStatusChanged(NS_LITERAL_STRING(HFP_STATUS_CHANGED_ID));
|
||||
Reset();
|
||||
}
|
||||
|
||||
@ -1617,7 +1636,8 @@ BluetoothHfpManager::OnScoConnectSuccess()
|
||||
mScoRunnable = nullptr;
|
||||
}
|
||||
|
||||
NotifyStatusChanged(BLUETOOTH_SCO_STATUS_CHANGED_ID);
|
||||
NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
|
||||
DispatchConnectionStatusChanged(NS_LITERAL_STRING(SCO_STATUS_CHANGED_ID));
|
||||
|
||||
mScoSocketStatus = mScoSocket->GetConnectionStatus();
|
||||
}
|
||||
@ -1640,7 +1660,8 @@ BluetoothHfpManager::OnScoDisconnect()
|
||||
{
|
||||
if (mScoSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
|
||||
ListenSco();
|
||||
NotifyStatusChanged(BLUETOOTH_SCO_STATUS_CHANGED_ID);
|
||||
NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
|
||||
DispatchConnectionStatusChanged(NS_LITERAL_STRING(SCO_STATUS_CHANGED_ID));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,8 +117,9 @@ private:
|
||||
uint32_t FindFirstCall(uint16_t aState);
|
||||
uint32_t GetNumberOfCalls(uint16_t aState);
|
||||
|
||||
void DispatchConnectionStatusChanged(const nsAString& aType);
|
||||
void NotifyDialer(const nsAString& aCommand);
|
||||
void NotifyStatusChanged(const char* aType);
|
||||
void NotifyConnectionStatusChanged(const nsAString& aType);
|
||||
|
||||
bool SendCommand(const char* aCommand, uint32_t aValue = 0);
|
||||
bool SendLine(const char* aMessage);
|
||||
|
@ -788,9 +788,9 @@ BluetoothService::Notify(const BluetoothSignal& aData)
|
||||
MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 0,
|
||||
"Cancel: Wrong length of parameters");
|
||||
type.AssignLiteral("bluetooth-cancel");
|
||||
} else if (aData.name().EqualsLiteral("PairedStatusChanged")) {
|
||||
} else if (aData.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID)) {
|
||||
MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 1,
|
||||
"PairedStatusChagned: Wrong length of parameters");
|
||||
"pairedstatuschanged: Wrong length of parameters");
|
||||
type.AssignLiteral("bluetooth-pairedstatuschanged");
|
||||
} else {
|
||||
nsCString warningMsg;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
@ -173,4 +174,24 @@ ParseAtCommand(const nsACString& aAtCommand, const int aStart,
|
||||
aRetValues.AppendElement(tmp);
|
||||
}
|
||||
|
||||
void
|
||||
DispatchStatusChangedEvent(const nsAString& aType,
|
||||
const nsAString& aAddress,
|
||||
bool aStatus)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
InfallibleTArray<BluetoothNamedValue> data;
|
||||
data.AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("address"), nsString(aAddress)));
|
||||
data.AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("status"), aStatus));
|
||||
|
||||
BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->DistributeSignal(signal);
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -43,6 +43,11 @@ void
|
||||
ParseAtCommand(const nsACString& aAtCommand, const int aStart,
|
||||
nsTArray<nsCString>& aRetValues);
|
||||
|
||||
void
|
||||
DispatchStatusChangedEvent(const nsAString& aType,
|
||||
const nsAString& aDeviceAddress,
|
||||
bool aStatus);
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -467,6 +467,8 @@ GetIntCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
|
||||
static void
|
||||
CheckForError(DBusMessage* aMsg, void *aParam, const nsAString& aError)
|
||||
{
|
||||
NS_ENSURE_TRUE_VOID(aMsg);
|
||||
|
||||
BluetoothValue v;
|
||||
nsAutoString replyError;
|
||||
UnpackVoidMessage(aMsg, nullptr, v, replyError);
|
||||
@ -1484,16 +1486,27 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
|
||||
sDeviceProperties,
|
||||
ArrayLength(sDeviceProperties));
|
||||
|
||||
// Fire another task for sending system message of
|
||||
// "bluetooth-pairedstatuschanged"
|
||||
BluetoothNamedValue& property = v.get_ArrayOfBluetoothNamedValue()[0];
|
||||
if (property.name().EqualsLiteral("Paired")) {
|
||||
// Original approach: Broadcast system message of
|
||||
// "bluetooth-pairedstatuschanged" from BluetoothService.
|
||||
BluetoothValue newValue(v);
|
||||
ToLowerCase(newValue.get_ArrayOfBluetoothNamedValue()[0].name());
|
||||
BluetoothSignal signal(NS_LITERAL_STRING("PairedStatusChanged"),
|
||||
BluetoothSignal signal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
|
||||
NS_LITERAL_STRING(KEY_LOCAL_AGENT),
|
||||
newValue);
|
||||
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
|
||||
|
||||
// New approach: Dispatch event from BluetoothAdapter
|
||||
bool status = property.value();
|
||||
InfallibleTArray<BluetoothNamedValue> parameters;
|
||||
parameters.AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("address"), signalPath));
|
||||
parameters.AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("status"), status));
|
||||
signal.path() = NS_LITERAL_STRING(KEY_ADAPTER);
|
||||
signal.value() = parameters;
|
||||
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
|
||||
}
|
||||
} else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE, "AdapterAdded")) {
|
||||
const char* str;
|
||||
|
@ -22,6 +22,7 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'nsIDOMBluetoothDevice.idl',
|
||||
'nsIDOMBluetoothDeviceEvent.idl',
|
||||
'nsIDOMBluetoothManager.idl',
|
||||
'nsIDOMBluetoothStatusChangedEvent.idl',
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
|
@ -43,7 +43,7 @@ interface nsIDOMDOMRequest;
|
||||
interface nsIDOMBlob;
|
||||
interface nsIDOMBluetoothDevice;
|
||||
|
||||
[scriptable, builtinclass, uuid(1a0c6c90-23e3-4f4c-8076-98e4341c2024)]
|
||||
[scriptable, builtinclass, uuid(54bf9aa2-1208-47ab-ac96-c7df349fcf0e)]
|
||||
interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
|
||||
{
|
||||
readonly attribute DOMString address;
|
||||
@ -102,4 +102,16 @@ interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
|
||||
|
||||
// Fired when discoverying and any device is discovered.
|
||||
[implicit_jscontext] attribute jsval ondevicefound;
|
||||
|
||||
// Fired when pairing process is completed
|
||||
[implicit_jscontext] attribute jsval onpairedstatuschanged;
|
||||
|
||||
// Fired when a2dp connection status changed
|
||||
[implicit_jscontext] attribute jsval ona2dpstatuschanged;
|
||||
|
||||
// Fired when handsfree connection status changed
|
||||
[implicit_jscontext] attribute jsval onhfpstatuschanged;
|
||||
|
||||
// Fired when sco connection status changed
|
||||
[implicit_jscontext] attribute jsval onscostatuschanged;
|
||||
};
|
||||
|
24
dom/bluetooth/nsIDOMBluetoothStatusChangedEvent.idl
Normal file
24
dom/bluetooth/nsIDOMBluetoothStatusChangedEvent.idl
Normal file
@ -0,0 +1,24 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(07f6d8d0-d364-4033-92e2-d69de323d7b7)]
|
||||
interface nsIDOMBluetoothStatusChangedEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute DOMString address;
|
||||
readonly attribute boolean status;
|
||||
|
||||
[noscript] void initBluetoothStatusChangedEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in DOMString aAddress,
|
||||
in boolean aStatus);
|
||||
};
|
||||
|
||||
dictionary BluetoothStatusChangedEventInit : EventInit
|
||||
{
|
||||
DOMString address;
|
||||
bool status;
|
||||
};
|
@ -523,7 +523,8 @@ LockedFile::SetLocation(JSContext* aCx,
|
||||
}
|
||||
|
||||
uint64_t location;
|
||||
if (!JS::ToUint64(aCx, aLocation, &location)) {
|
||||
JS::Rooted<JS::Value> value(aCx, aLocation);
|
||||
if (!JS::ToUint64(aCx, value, &location)) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ GetJSValFromKeyPathString(JSContext* aCx,
|
||||
if (!JS_DeleteUCProperty2(aCx, targetObject,
|
||||
targetObjectPropName.get(),
|
||||
targetObjectPropName.Length(),
|
||||
succeeded.address())) {
|
||||
&succeeded)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
NS_ASSERTION(JSVAL_IS_BOOLEAN(succeeded), "Wtf?");
|
||||
|
@ -823,7 +823,7 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier id)
|
||||
|
||||
NS_ASSERTION(NPIdentifierIsInt(id) || NPIdentifierIsString(id),
|
||||
"id must be either string or int!\n");
|
||||
ok = ::JS_DeletePropertyById2(cx, npjsobj->mJSObj, NPIdentifierToJSId(id), deleted.address());
|
||||
ok = ::JS_DeletePropertyById2(cx, npjsobj->mJSObj, NPIdentifierToJSId(id), &deleted);
|
||||
if (ok && deleted == JSVAL_TRUE) {
|
||||
// FIXME: See bug 425823, we shouldn't need to do this, and once
|
||||
// that bug is fixed we can remove this code.
|
||||
|
18
dom/webidl/BluetoothStatusChangedEvent.webidl
Normal file
18
dom/webidl/BluetoothStatusChangedEvent.webidl
Normal file
@ -0,0 +1,18 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
[Constructor(DOMString type, optional BluetoothStatusChangedEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
|
||||
interface BluetoothStatusChangedEvent : Event
|
||||
{
|
||||
readonly attribute DOMString address;
|
||||
readonly attribute boolean status;
|
||||
};
|
||||
|
||||
dictionary BluetoothStatusChangedEventInit : EventInit
|
||||
{
|
||||
DOMString address = "";
|
||||
boolean status = false;
|
||||
};
|
@ -16,6 +16,7 @@ interface DummyInterface {
|
||||
void funcHttpConnDict(optional HttpConnDict arg);
|
||||
void funcWebSocketDict(optional WebSocketDict arg);
|
||||
void funcDNSCacheDict(optional DNSCacheDict arg);
|
||||
void funcDNSLookupDict(optional DNSLookupDict arg);
|
||||
void funcConnStatusDict(optional ConnStatusDict arg);
|
||||
void frameRequestCallback(FrameRequestCallback arg);
|
||||
void CameraPictureOptions(optional CameraPictureOptions arg);
|
||||
|
@ -50,6 +50,12 @@ dictionary DNSCacheDict {
|
||||
sequence<double> expiration;
|
||||
};
|
||||
|
||||
dictionary DNSLookupDict {
|
||||
sequence<DOMString> address;
|
||||
DOMString error;
|
||||
boolean answer;
|
||||
};
|
||||
|
||||
dictionary ConnStatusDict {
|
||||
DOMString status;
|
||||
};
|
||||
|
@ -469,6 +469,7 @@ webidl_files += \
|
||||
ifdef MOZ_B2G_BT
|
||||
webidl_files += \
|
||||
BluetoothDeviceEvent.webidl \
|
||||
BluetoothStatusChangedEvent.webidl \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -142,13 +142,14 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure that the DOM_OBJECT_SLOT always has a PrivateValue set, as this
|
||||
// will be accessed in the Trace() method if WorkerPrivate::Create()
|
||||
// triggers a GC.
|
||||
js::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::PrivateValue(nullptr));
|
||||
|
||||
nsRefPtr<WorkerPrivate> worker =
|
||||
WorkerPrivate::Create(aCx, obj, parent, scriptURL, aIsChromeWorker);
|
||||
if (!worker) {
|
||||
// It'd be better if we could avoid allocating the JSObject until after we
|
||||
// make sure we have a WorkerPrivate, but failing that we should at least
|
||||
// make sure that the DOM_OBJECT_SLOT always has a PrivateValue.
|
||||
js::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::PrivateValue(nullptr));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -573,6 +573,10 @@ Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride,
|
||||
const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
if (aSize.width <= 0 || aSize.height <= 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurfaceRawData> newSurf = new SourceSurfaceRawData();
|
||||
|
||||
if (newSurf->InitWrappingData(aData, aSize, aStride, aFormat, false)) {
|
||||
|
@ -157,12 +157,21 @@ DataSourceSurfaceCG::InitFromData(unsigned char *aData,
|
||||
int32_t aStride,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
if (aSize.width <= 0 || aSize.height <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *data = malloc(aStride * aSize.height);
|
||||
memcpy(data, aData, aStride * aSize.height);
|
||||
|
||||
mImage = CreateCGImage(data, data, aSize, aStride, aFormat);
|
||||
|
||||
return mImage;
|
||||
if (!mImage) {
|
||||
delete data;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CGContextRef CreateBitmapContextForImage(CGImageRef image)
|
||||
|
@ -22,20 +22,15 @@ namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/* static */ TemporaryRef<CanvasClient>
|
||||
CanvasClient::CreateCanvasClient(CompositableType aCompositableHostType,
|
||||
CanvasClient::CreateCanvasClient(CanvasClientType aType,
|
||||
CompositableForwarder* aForwarder,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
if (aCompositableHostType == BUFFER_IMAGE_SINGLE) {
|
||||
return new CanvasClient2D(aForwarder, aFlags);
|
||||
if (aType == CanvasClientGLContext &&
|
||||
aForwarder->GetCompositorBackendType() == LAYERS_OPENGL) {
|
||||
return new CanvasClientSurfaceStream(aForwarder, aFlags);
|
||||
}
|
||||
if (aCompositableHostType == BUFFER_IMAGE_BUFFERED) {
|
||||
if (aForwarder->GetCompositorBackendType() == LAYERS_OPENGL) {
|
||||
return new CanvasClientWebGL(aForwarder, aFlags);
|
||||
}
|
||||
return new CanvasClient2D(aForwarder, aFlags);
|
||||
}
|
||||
return nullptr;
|
||||
return new CanvasClient2D(aForwarder, aFlags);
|
||||
}
|
||||
|
||||
void
|
||||
@ -72,28 +67,32 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
}
|
||||
|
||||
void
|
||||
CanvasClientWebGL::Updated()
|
||||
CanvasClientSurfaceStream::Updated()
|
||||
{
|
||||
mForwarder->UpdateTextureNoSwap(this, 1, mDeprecatedTextureClient->GetDescriptor());
|
||||
if (mNeedsUpdate) {
|
||||
mForwarder->UpdateTextureNoSwap(this, 1, mDeprecatedTextureClient->GetDescriptor());
|
||||
mNeedsUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CanvasClientWebGL::CanvasClientWebGL(CompositableForwarder* aFwd,
|
||||
TextureFlags aFlags)
|
||||
CanvasClientSurfaceStream::CanvasClientSurfaceStream(CompositableForwarder* aFwd,
|
||||
TextureFlags aFlags)
|
||||
: CanvasClient(aFwd, aFlags)
|
||||
, mNeedsUpdate(false)
|
||||
{
|
||||
mTextureInfo.mCompositableType = BUFFER_IMAGE_BUFFERED;
|
||||
mTextureInfo.mCompositableType = BUFFER_IMAGE_SINGLE;
|
||||
}
|
||||
|
||||
void
|
||||
CanvasClientWebGL::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
{
|
||||
if (!mDeprecatedTextureClient) {
|
||||
mDeprecatedTextureClient = CreateDeprecatedTextureClient(TEXTURE_STREAM_GL);
|
||||
MOZ_ASSERT(mDeprecatedTextureClient, "Failed to create texture client");
|
||||
}
|
||||
|
||||
NS_ASSERTION(aLayer->mGLContext, "CanvasClientWebGL should only be used with GL canvases");
|
||||
NS_ASSERTION(aLayer->mGLContext, "CanvasClientSurfaceStream should only be used with GL canvases");
|
||||
|
||||
// the content type won't be used
|
||||
mDeprecatedTextureClient->EnsureAllocated(aSize, gfxASurface::CONTENT_COLOR);
|
||||
@ -122,15 +121,21 @@ CanvasClientWebGL::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
|
||||
MOZ_ASSERT(false);
|
||||
#endif
|
||||
mNeedsUpdate = true;
|
||||
} else {
|
||||
SurfaceStreamHandle handle = stream->GetShareHandle();
|
||||
mDeprecatedTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
|
||||
SurfaceDescriptor *desc = mDeprecatedTextureClient->GetDescriptor();
|
||||
if (desc->type() != SurfaceDescriptor::TSurfaceStreamDescriptor ||
|
||||
desc->get_SurfaceStreamDescriptor().handle() != handle) {
|
||||
*desc = SurfaceStreamDescriptor(handle, false);
|
||||
|
||||
// Bug 894405
|
||||
//
|
||||
// Ref this so the SurfaceStream doesn't disappear unexpectedly. The
|
||||
// Compositor will need to unref it when finished.
|
||||
aLayer->mGLContext->AddRef();
|
||||
// Bug 894405
|
||||
//
|
||||
// Ref this so the SurfaceStream doesn't disappear unexpectedly. The
|
||||
// Compositor will need to unref it when finished.
|
||||
aLayer->mGLContext->AddRef();
|
||||
mNeedsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
aLayer->Painted();
|
||||
|
@ -26,7 +26,11 @@ public:
|
||||
* message will be sent to the compositor to create a corresponding image
|
||||
* host.
|
||||
*/
|
||||
static TemporaryRef<CanvasClient> CreateCanvasClient(CompositableType aImageHostType,
|
||||
enum CanvasClientType {
|
||||
CanvasClientSurface,
|
||||
CanvasClientGLContext,
|
||||
};
|
||||
static TemporaryRef<CanvasClient> CreateCanvasClient(CanvasClientType aType,
|
||||
CompositableForwarder* aFwd,
|
||||
TextureFlags aFlags);
|
||||
|
||||
@ -69,11 +73,11 @@ public:
|
||||
|
||||
// Used for GL canvases where we don't need to do any readback, i.e., with a
|
||||
// GL backend.
|
||||
class CanvasClientWebGL : public CanvasClient
|
||||
class CanvasClientSurfaceStream : public CanvasClient
|
||||
{
|
||||
public:
|
||||
CanvasClientWebGL(CompositableForwarder* aFwd,
|
||||
TextureFlags aFlags);
|
||||
CanvasClientSurfaceStream(CompositableForwarder* aFwd,
|
||||
TextureFlags aFlags);
|
||||
|
||||
TextureInfo GetTextureInfo() const MOZ_OVERRIDE
|
||||
{
|
||||
@ -82,6 +86,9 @@ public:
|
||||
|
||||
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer);
|
||||
virtual void Updated() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
bool mNeedsUpdate;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ ClientCanvasLayer::RenderLayer()
|
||||
flags |= TEXTURE_DEALLOCATE_CLIENT;
|
||||
}
|
||||
}
|
||||
mCanvasClient = CanvasClient::CreateCanvasClient(GetCompositableClientType(),
|
||||
mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
|
||||
ClientManager(), flags);
|
||||
if (!mCanvasClient) {
|
||||
return;
|
||||
|
@ -25,6 +25,7 @@ class CanvasClientWebGL;
|
||||
class ClientCanvasLayer : public CopyableCanvasLayer,
|
||||
public ClientLayer
|
||||
{
|
||||
typedef CanvasClient::CanvasClientType CanvasClientType;
|
||||
public:
|
||||
ClientCanvasLayer(ClientLayerManager* aLayerManager) :
|
||||
CopyableCanvasLayer(aLayerManager, static_cast<ClientLayer*>(this))
|
||||
@ -75,18 +76,18 @@ protected:
|
||||
return static_cast<ClientLayerManager*>(mManager);
|
||||
}
|
||||
|
||||
CompositableType GetCompositableClientType()
|
||||
CanvasClientType GetCanvasClientType()
|
||||
{
|
||||
if (mGLContext) {
|
||||
return BUFFER_IMAGE_BUFFERED;
|
||||
return CanvasClient::CanvasClientGLContext;
|
||||
}
|
||||
return BUFFER_IMAGE_SINGLE;
|
||||
return CanvasClient::CanvasClientSurface;
|
||||
}
|
||||
|
||||
RefPtr<CanvasClient> mCanvasClient;
|
||||
|
||||
friend class CanvasClient2D;
|
||||
friend class CanvasClientWebGL;
|
||||
friend class CanvasClientSurfaceStream;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,8 @@ CanvasLayerComposite::RenderLayer(const nsIntPoint& aOffset,
|
||||
gfx::Point(aOffset.x, aOffset.y),
|
||||
gfx::ToFilter(filter),
|
||||
clipRect);
|
||||
|
||||
LayerManagerComposite::RemoveMaskEffect(mMaskLayer);
|
||||
}
|
||||
|
||||
CompositableHost*
|
||||
|
@ -40,6 +40,7 @@ ColorLayerComposite::RenderLayer(const nsIntPoint& aOffset,
|
||||
rect, clipRect,
|
||||
transform, gfx::Point(aOffset.x, aOffset.y));
|
||||
|
||||
LayerManagerComposite::RemoveMaskEffect(GetMaskLayer());
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
|
@ -104,7 +104,18 @@ CompositableHost::AddMaskEffect(EffectChain& aEffects,
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
bool aIs3D)
|
||||
{
|
||||
RefPtr<TextureSource> source = GetDeprecatedTextureHost();
|
||||
RefPtr<TextureSource> source;
|
||||
RefPtr<DeprecatedTextureHost> oldHost = GetDeprecatedTextureHost();
|
||||
if (oldHost) {
|
||||
oldHost->Lock();
|
||||
source = oldHost;
|
||||
} else {
|
||||
RefPtr<TextureHost> host = GetTextureHost();
|
||||
if (host) {
|
||||
host->Lock();
|
||||
source = host->GetTextureSources();
|
||||
}
|
||||
}
|
||||
|
||||
if (!source) {
|
||||
NS_WARNING("Using compositable with no texture host as mask layer");
|
||||
@ -119,6 +130,20 @@ CompositableHost::AddMaskEffect(EffectChain& aEffects,
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CompositableHost::RemoveMaskEffect()
|
||||
{
|
||||
RefPtr<DeprecatedTextureHost> oldHost = GetDeprecatedTextureHost();
|
||||
if (oldHost) {
|
||||
oldHost->Unlock();
|
||||
} else {
|
||||
RefPtr<TextureHost> host = GetTextureHost();
|
||||
if (host) {
|
||||
host->Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ TemporaryRef<CompositableHost>
|
||||
CompositableHost::Create(const TextureInfo& aTextureInfo)
|
||||
{
|
||||
|
@ -172,6 +172,8 @@ public:
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
bool aIs3D = false);
|
||||
|
||||
void RemoveMaskEffect();
|
||||
|
||||
Compositor* GetCompositor() const
|
||||
{
|
||||
return mCompositor;
|
||||
|
@ -163,6 +163,8 @@ ContainerRender(ContainerT* aContainer,
|
||||
rect, clipRect,
|
||||
transform, gfx::Point(aOffset.x, aOffset.y));
|
||||
}
|
||||
|
||||
LayerManagerComposite::RemoveMaskEffect(aContainer->GetMaskLayer());
|
||||
}
|
||||
|
||||
ContainerLayerComposite::ContainerLayerComposite(LayerManagerComposite *aManager)
|
||||
|
@ -67,12 +67,28 @@ ImageHost::Composite(EffectChain& aEffectChain,
|
||||
source,
|
||||
aFilter);
|
||||
aEffectChain.mPrimaryEffect = effect;
|
||||
|
||||
gfx::Rect pictureRect(0, 0,
|
||||
mPictureRect.width,
|
||||
mPictureRect.height);
|
||||
//XXX: We might have multiple texture sources here (e.g. 3 YCbCr textures), and we're
|
||||
// only iterating over the tiles of the first one. Are we assuming that the tiling
|
||||
// will be identical? Can we ensure that somehow?
|
||||
TileIterator* it = source->AsTileIterator();
|
||||
if (it) {
|
||||
it->BeginTileIteration();
|
||||
do {
|
||||
nsIntRect tileRect = it->GetTileRect();
|
||||
gfx::Rect rect(tileRect.x, tileRect.y, tileRect.width, tileRect.height);
|
||||
if (mHasPictureRect) {
|
||||
rect = rect.Intersect(pictureRect);
|
||||
effect->mTextureCoords = Rect(Float(rect.x - tileRect.x)/ tileRect.width,
|
||||
Float(rect.y - tileRect.y) / tileRect.height,
|
||||
Float(rect.width) / tileRect.width,
|
||||
Float(rect.height) / tileRect.height);
|
||||
} else {
|
||||
effect->mTextureCoords = Rect(0, 0, 1, 1);
|
||||
}
|
||||
GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
|
||||
aOpacity, aTransform, aOffset);
|
||||
GetCompositor()->DrawDiagnostics(gfx::Color(0.5,0.0,0.0,1.0),
|
||||
@ -81,14 +97,13 @@ ImageHost::Composite(EffectChain& aEffectChain,
|
||||
it->EndTileIteration();
|
||||
} else {
|
||||
IntSize textureSize = source->GetSize();
|
||||
gfx::Rect rect(0, 0,
|
||||
mPictureRect.width,
|
||||
mPictureRect.height);
|
||||
gfx::Rect rect;
|
||||
if (mHasPictureRect) {
|
||||
effect->mTextureCoords = Rect(Float(mPictureRect.x) / textureSize.width,
|
||||
Float(mPictureRect.y) / textureSize.height,
|
||||
Float(mPictureRect.width) / textureSize.width,
|
||||
Float(mPictureRect.height) / textureSize.height);
|
||||
rect = pictureRect;
|
||||
} else {
|
||||
effect->mTextureCoords = Rect(0, 0, 1, 1);
|
||||
rect = gfx::Rect(0, 0, textureSize.width, textureSize.height);
|
||||
|
@ -96,6 +96,8 @@ ImageLayerComposite::RenderLayer(const nsIntPoint& aOffset,
|
||||
gfx::Point(aOffset.x, aOffset.y),
|
||||
gfx::ToFilter(mFilter),
|
||||
clipRect);
|
||||
|
||||
LayerManagerComposite::RemoveMaskEffect(mMaskLayer);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -661,6 +661,21 @@ LayerManagerComposite::AddMaskEffect(Layer* aMaskLayer, EffectChain& aEffects, b
|
||||
return maskLayerComposite->GetCompositableHost()->AddMaskEffect(aEffects, transform, aIs3D);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
LayerManagerComposite::RemoveMaskEffect(Layer* aMaskLayer)
|
||||
{
|
||||
if (!aMaskLayer) {
|
||||
return;
|
||||
}
|
||||
LayerComposite* maskLayerComposite = static_cast<LayerComposite*>(aMaskLayer->ImplData());
|
||||
if (!maskLayerComposite->GetCompositableHost()) {
|
||||
NS_WARNING("Mask layer with no compositable host");
|
||||
return;
|
||||
}
|
||||
|
||||
maskLayerComposite->GetCompositableHost()->RemoveMaskEffect();
|
||||
}
|
||||
|
||||
TemporaryRef<DrawTarget>
|
||||
LayerManagerComposite::CreateDrawTarget(const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
|
@ -165,6 +165,8 @@ public:
|
||||
EffectChain& aEffect,
|
||||
bool aIs3D = false);
|
||||
|
||||
static void RemoveMaskEffect(Layer* aMaskLayer);
|
||||
|
||||
/**
|
||||
* Creates a DrawTarget which is optimized for inter-operating with this
|
||||
* layermanager.
|
||||
|
@ -454,7 +454,7 @@ MemoryTextureHost::MemoryTextureHost(uint64_t aID,
|
||||
MemoryTextureHost::~MemoryTextureHost()
|
||||
{
|
||||
DeallocateDeviceData();
|
||||
MOZ_COUNT_DTOR(ShmemTextureHost);
|
||||
MOZ_COUNT_DTOR(MemoryTextureHost);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -140,6 +140,7 @@ ThebesLayerComposite::RenderLayer(const nsIntPoint& aOffset,
|
||||
mValidRegion = tiledLayerProps.mValidRegion;
|
||||
}
|
||||
|
||||
LayerManagerComposite::RemoveMaskEffect(mMaskLayer);
|
||||
mCompositeManager->GetCompositor()->MakeCurrent();
|
||||
}
|
||||
|
||||
|
@ -405,7 +405,6 @@ ShadowLayerForwarder::UpdatedTexture(CompositableClient* aCompositable,
|
||||
TextureClient* aTexture,
|
||||
nsIntRegion* aRegion)
|
||||
{
|
||||
printf("ShadowLayerForwarder::UpdatedTexture %i\n", (int)aTexture->GetID());
|
||||
MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
|
||||
: MaybeRegion(null_t());
|
||||
mTxn->AddEdit(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
|
||||
|
@ -37,7 +37,6 @@ RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager,
|
||||
program->Activate();
|
||||
program->SetLayerQuadRect(aLayer->GetBounds());
|
||||
program->SetLayerTransform(aLayer->GetEffectiveTransform());
|
||||
program->SetTextureTransform(gfx3DMatrix());
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetRenderColor(color);
|
||||
program->LoadMask(aLayer->GetMaskLayer());
|
||||
|
@ -1038,7 +1038,6 @@ CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect,
|
||||
}
|
||||
program->SetLayerQuadRect(aRect);
|
||||
program->SetLayerTransform(aTransform);
|
||||
program->SetTextureTransform(gfx3DMatrix());
|
||||
program->SetRenderOffset(aOffset.x, aOffset.y);
|
||||
|
||||
switch (aEffectChain.mPrimaryEffect->mType) {
|
||||
@ -1136,6 +1135,7 @@ CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect,
|
||||
|
||||
program->SetYCbCrTextureUnits(Y, Cb, Cr);
|
||||
program->SetLayerOpacity(aOpacity);
|
||||
program->SetTextureTransform(gfx3DMatrix());
|
||||
|
||||
AutoBindTexture bindMask;
|
||||
if (maskType != MaskNone) {
|
||||
@ -1159,6 +1159,7 @@ CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect,
|
||||
program->Activate();
|
||||
program->SetTextureUnit(0);
|
||||
program->SetLayerOpacity(aOpacity);
|
||||
program->SetTextureTransform(gfx3DMatrix());
|
||||
|
||||
AutoBindTexture bindMask;
|
||||
if (maskType != MaskNone) {
|
||||
|
@ -22,7 +22,6 @@ AddCommonArgs(ProgramProfileOGL& aProfile)
|
||||
{
|
||||
aProfile.mUniforms.AppendElement(Argument("uLayerTransform"));
|
||||
aProfile.mUniforms.AppendElement(Argument("uLayerQuadTransform"));
|
||||
aProfile.mUniforms.AppendElement(Argument("uTextureTransform"));
|
||||
aProfile.mUniforms.AppendElement(Argument("uMatrixProj"));
|
||||
aProfile.mHasMatrixProj = true;
|
||||
aProfile.mUniforms.AppendElement(Argument("uRenderTargetOffset"));
|
||||
@ -33,6 +32,7 @@ AddCommonTextureArgs(ProgramProfileOGL& aProfile)
|
||||
{
|
||||
aProfile.mUniforms.AppendElement(Argument("uLayerOpacity"));
|
||||
aProfile.mUniforms.AppendElement(Argument("uTexture"));
|
||||
aProfile.mUniforms.AppendElement(Argument("uTextureTransform"));
|
||||
aProfile.mAttributes.AppendElement(Argument("aTexCoord"));
|
||||
}
|
||||
|
||||
@ -172,6 +172,7 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
|
||||
result.mUniforms.AppendElement(Argument("uYTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uCbTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uCrTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uTextureTransform"));
|
||||
result.mAttributes.AppendElement(Argument("aTexCoord"));
|
||||
result.mTextureCount = 3;
|
||||
break;
|
||||
@ -187,6 +188,7 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
|
||||
result.mUniforms.AppendElement(Argument("uLayerOpacity"));
|
||||
result.mUniforms.AppendElement(Argument("uBlackTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uWhiteTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uTextureTransform"));
|
||||
result.mAttributes.AppendElement(Argument("aTexCoord"));
|
||||
result.mTextureCount = 2;
|
||||
break;
|
||||
@ -202,6 +204,7 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
|
||||
result.mUniforms.AppendElement(Argument("uLayerOpacity"));
|
||||
result.mUniforms.AppendElement(Argument("uBlackTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uWhiteTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uTextureTransform"));
|
||||
result.mAttributes.AppendElement(Argument("aTexCoord"));
|
||||
result.mTextureCount = 2;
|
||||
break;
|
||||
@ -217,6 +220,7 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
|
||||
result.mUniforms.AppendElement(Argument("uLayerOpacity"));
|
||||
result.mUniforms.AppendElement(Argument("uBlackTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uWhiteTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uTextureTransform"));
|
||||
result.mAttributes.AppendElement(Argument("aTexCoord"));
|
||||
result.mTextureCount = 2;
|
||||
break;
|
||||
@ -232,6 +236,7 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
|
||||
result.mUniforms.AppendElement(Argument("uLayerOpacity"));
|
||||
result.mUniforms.AppendElement(Argument("uBlackTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uWhiteTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uTextureTransform"));
|
||||
result.mAttributes.AppendElement(Argument("aTexCoord"));
|
||||
result.mTextureCount = 2;
|
||||
break;
|
||||
@ -240,6 +245,7 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
|
||||
result.mVertexShaderString = sCopyVS;
|
||||
result.mFragmentShaderString = sCopy2DFS;
|
||||
result.mUniforms.AppendElement(Argument("uTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uTextureTransform"));
|
||||
result.mAttributes.AppendElement(Argument("aVertexCoord"));
|
||||
result.mAttributes.AppendElement(Argument("aTexCoord"));
|
||||
result.mTextureCount = 1;
|
||||
@ -249,6 +255,7 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
|
||||
result.mVertexShaderString = sCopyVS;
|
||||
result.mFragmentShaderString = sCopy2DRectFS;
|
||||
result.mUniforms.AppendElement(Argument("uTexture"));
|
||||
result.mUniforms.AppendElement(Argument("uTextureTransform"));
|
||||
result.mAttributes.AppendElement(Argument("aVertexCoord"));
|
||||
result.mAttributes.AppendElement(Argument("aTexCoord"));
|
||||
result.mTextureCount = 1;
|
||||
|
@ -462,9 +462,6 @@ TextureImageDeprecatedTextureHostOGL::Lock()
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mTexture->GetContentType() != gfxASurface::CONTENT_ALPHA,
|
||||
"Image layer has alpha image");
|
||||
|
||||
mFormat = mTexture->GetTextureFormat();
|
||||
|
||||
return true;
|
||||
@ -592,27 +589,23 @@ SurfaceStreamHostOGL::DeleteTextures()
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceStreamHostOGL::SwapTexturesImpl(const SurfaceDescriptor& aImage,
|
||||
nsIntRegion* aRegion)
|
||||
SurfaceStreamHostOGL::UpdateImpl(const SurfaceDescriptor& aImage,
|
||||
nsIntRegion* aRegion,
|
||||
nsIntPoint* aOffset)
|
||||
{
|
||||
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceStreamDescriptor,
|
||||
"Invalid descriptor");
|
||||
|
||||
mStreamGL = nullptr;
|
||||
// Bug 894405
|
||||
//
|
||||
// The SurfaceStream's GLContext was refed before being passed up to us, so
|
||||
// we need to ensure it gets unrefed when we are finished.
|
||||
const SurfaceStreamDescriptor& streamDesc =
|
||||
aImage.get_SurfaceStreamDescriptor();
|
||||
|
||||
if (aImage.type() == SurfaceDescriptor::TSurfaceStreamDescriptor) {
|
||||
// Bug 894405
|
||||
//
|
||||
// The SurfaceStream's GLContext was refed before being passed up to us, so
|
||||
// we need to ensure it gets unrefed when we are finished.
|
||||
const SurfaceStreamDescriptor& streamDesc =
|
||||
aImage.get_SurfaceStreamDescriptor();
|
||||
|
||||
SurfaceStream* surfStream = SurfaceStream::FromHandle(streamDesc.handle());
|
||||
if (surfStream) {
|
||||
mStreamGL = dont_AddRef(surfStream->GLContext());
|
||||
}
|
||||
}
|
||||
mStream = SurfaceStream::FromHandle(streamDesc.handle());
|
||||
MOZ_ASSERT(mStream);
|
||||
mStreamGL = dont_AddRef(mStream->GLContext());
|
||||
}
|
||||
|
||||
void
|
||||
@ -626,15 +619,8 @@ bool
|
||||
SurfaceStreamHostOGL::Lock()
|
||||
{
|
||||
mGL->MakeCurrent();
|
||||
SurfaceStream* surfStream = nullptr;
|
||||
SharedSurface* sharedSurf = nullptr;
|
||||
const SurfaceStreamDescriptor& streamDesc =
|
||||
mBuffer->get_SurfaceStreamDescriptor();
|
||||
|
||||
surfStream = SurfaceStream::FromHandle(streamDesc.handle());
|
||||
MOZ_ASSERT(surfStream);
|
||||
|
||||
sharedSurf = surfStream->SwapConsumer();
|
||||
SharedSurface* sharedSurf = mStream->SwapConsumer();
|
||||
if (!sharedSurf) {
|
||||
// We don't have a valid surf to show yet.
|
||||
return false;
|
||||
|
@ -652,7 +652,6 @@ public:
|
||||
virtual ~SurfaceStreamHostOGL()
|
||||
{
|
||||
DeleteTextures();
|
||||
*mBuffer = SurfaceDescriptor();
|
||||
}
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
|
||||
@ -672,8 +671,9 @@ public:
|
||||
bool IsValid() const MOZ_OVERRIDE { return true; }
|
||||
|
||||
// override from DeprecatedTextureHost
|
||||
virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage,
|
||||
nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
|
||||
virtual void UpdateImpl(const SurfaceDescriptor& aImage,
|
||||
nsIntRegion* aRegion,
|
||||
nsIntPoint* aOffset);
|
||||
virtual bool Lock() MOZ_OVERRIDE;
|
||||
virtual void Unlock() MOZ_OVERRIDE;
|
||||
|
||||
@ -720,6 +720,7 @@ public:
|
||||
, mTextureTarget(LOCAL_GL_TEXTURE_2D)
|
||||
, mUploadTexture(0)
|
||||
, mWrapMode(LOCAL_GL_CLAMP_TO_EDGE)
|
||||
, mStream(nullptr)
|
||||
{}
|
||||
|
||||
protected:
|
||||
@ -732,6 +733,7 @@ protected:
|
||||
GLuint mUploadTexture;
|
||||
GLenum mWrapMode;
|
||||
nsRefPtr<GLContext> mStreamGL;
|
||||
gfx::SurfaceStream *mStream;
|
||||
};
|
||||
|
||||
class TiledDeprecatedTextureHostOGL : public DeprecatedTextureHost
|
||||
|
@ -19,56 +19,5 @@ MOCHITEST_FILES = $(addprefix mochitest/, \
|
||||
test_acceleration.html \
|
||||
)
|
||||
|
||||
# CPP_UNIT_TESTS disabled for now because they dont work in libxul builds.
|
||||
#ifndef BUILD_STATIC_LIBS
|
||||
#
|
||||
#CPP_UNIT_TESTS = \
|
||||
# TestColorNames.cpp \
|
||||
# TestRect.cpp \
|
||||
# TestRegion.cpp \
|
||||
# $(NULL)
|
||||
#
|
||||
## These are built but not run. gfxColorManagementTest.cpp can't even
|
||||
## be built, because it has not been updated for qcms.
|
||||
#CPP_DISABLED_UNIT_TESTS = \
|
||||
# gfxFontSelectionTest.cpp \
|
||||
# gfxSurfaceRefCountTest.cpp \
|
||||
# gfxTextRunPerfTest.cpp \
|
||||
# gfxWordCacheTest.cpp \
|
||||
# $(NULL)
|
||||
## gfxColorManagementTest.cpp \
|
||||
#
|
||||
#
|
||||
## rules.mk will put the CPP_UNIT_TESTS into SIMPLE_PROGRAMS twice if we
|
||||
## define SIMPLE_PROGRAMS based on CPPSRCS directly.
|
||||
#CPPSRCS = $(CPP_DISABLED_UNIT_TESTS)
|
||||
#SIMPLE_PROGRAMS = $(CPP_DISABLED_UNIT_TESTS:.cpp=$(BIN_SUFFIX))
|
||||
#
|
||||
#LIBS = \
|
||||
# $(HELPER_OBJS) \
|
||||
# $(call EXPAND_LIBNAME_PATH,thebes,../thebes) \
|
||||
# $(call EXPAND_LIBNAME_PATH,gkgfx,../src) \
|
||||
# $(MOZ_UNICHARUTIL_LIBS) \
|
||||
# $(XPCOM_LIBS) \
|
||||
# $(MOZ_JS_LIBS) \
|
||||
# $(TK_LIBS) \
|
||||
# $(NULL)
|
||||
#
|
||||
#endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
OS_LIBS += $(call EXPAND_LIBNAME,usp10)
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
||||
OS_LIBS += -framework Cocoa
|
||||
endif
|
||||
|
||||
ifdef MOZ_WIDGET_GTK
|
||||
OS_LIBS += $(MOZ_PANGO_LIBS) $(XLIBS)
|
||||
CXXFLAGS += $(MOZ_PANGO_CFLAGS)
|
||||
endif
|
||||
|
@ -1,501 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TestHarness.h"
|
||||
|
||||
#include "nsRect.h"
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestConstructors()
|
||||
{
|
||||
// Create a rectangle
|
||||
RectType rect1(10, 20, 30, 40);
|
||||
|
||||
// Make sure the rectangle was properly initialized
|
||||
if ((rect1.x != 10) || (rect1.y != 20) ||
|
||||
(rect1.width != 30) || (rect1.height != 40)) {
|
||||
fail("[1] Make sure the rectangle was properly initialized with constructor");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a second rect using the copy constructor
|
||||
RectType rect2(rect1);
|
||||
|
||||
// Make sure the rectangle was properly initialized
|
||||
if ((rect2.x != rect1.x) || (rect2.y != rect1.y) ||
|
||||
(rect2.width != rect1.width) || (rect2.height != rect1.height)) {
|
||||
fail("[2] Make sure the rectangle was properly initialized with copy constructor");
|
||||
return false;
|
||||
}
|
||||
|
||||
passed("TestConstructors");
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestEqualityOperator()
|
||||
{
|
||||
RectType rect1(10, 20, 30, 40);
|
||||
RectType rect2(rect1);
|
||||
|
||||
// Test the equality operator
|
||||
if (!(rect1 == rect2)) {
|
||||
fail("[1] Test the equality operator");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test the inequality operator
|
||||
if (rect1 != rect2) {
|
||||
fail("[2] Test the inequality operator");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that two empty rects are equal
|
||||
rect1.Empty();
|
||||
rect2.Empty();
|
||||
if (!(rect1 == rect2)) {
|
||||
fail("[3] Make sure that two empty rects are equal");
|
||||
return false;
|
||||
}
|
||||
|
||||
passed("TestEqualityOperator");
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestContainment()
|
||||
{
|
||||
RectType rect1(10, 10, 50, 50);
|
||||
|
||||
// Test the point containment methods
|
||||
//
|
||||
|
||||
// Basic test of a point in the middle of the rect
|
||||
if (!rect1.Contains(rect1.x + rect1.width/2, rect1.y + rect1.height/2)) {
|
||||
fail("[1] Basic test of a point in the middle of the rect");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test against a point at the left/top edges
|
||||
if (!rect1.Contains(rect1.x, rect1.y)) {
|
||||
fail("[2] Test against a point at the left/top edges");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test against a point at the right/bottom extents
|
||||
if (rect1.Contains(rect1.XMost(), rect1.YMost())) {
|
||||
fail("[3] Test against a point at the right/bottom extents");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test the rect containment methods
|
||||
//
|
||||
RectType rect2(rect1);
|
||||
|
||||
// Test against a rect that's the same as rect1
|
||||
if (!rect1.Contains(rect2)) {
|
||||
fail("[4] Test against a rect that's the same as rect1");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test against a rect whose left edge (only) is outside of rect1
|
||||
rect2.x--;
|
||||
if (rect1.Contains(rect2)) {
|
||||
fail("[5] Test against a rect whose left edge (only) is outside of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.x++;
|
||||
|
||||
// Test against a rect whose top edge (only) is outside of rect1
|
||||
rect2.y--;
|
||||
if (rect1.Contains(rect2)) {
|
||||
fail("[6] Test against a rect whose top edge (only) is outside of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.y++;
|
||||
|
||||
// Test against a rect whose right edge (only) is outside of rect1
|
||||
rect2.x++;
|
||||
if (rect1.Contains(rect2)) {
|
||||
fail("[7] Test against a rect whose right edge (only) is outside of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.x--;
|
||||
|
||||
// Test against a rect whose bottom edge (only) is outside of rect1
|
||||
rect2.y++;
|
||||
if (rect1.Contains(rect2)) {
|
||||
fail("[8] Test against a rect whose bottom edge (only) is outside of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.y--;
|
||||
|
||||
passed("TestContainment");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test the method that returns a boolean result but doesn't return a
|
||||
// a rectangle
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestIntersects()
|
||||
{
|
||||
RectType rect1(10, 10, 50, 50);
|
||||
RectType rect2(rect1);
|
||||
|
||||
// Test against a rect that's the same as rect1
|
||||
if (!rect1.Intersects(rect2)) {
|
||||
fail("[1] Test against a rect that's the same as rect1");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test against a rect that's enclosed by rect1
|
||||
rect2.Inflate(-1, -1);
|
||||
if (!rect1.Contains(rect2) || !rect1.Intersects(rect2)) {
|
||||
fail("[2] Test against a rect that's enclosed by rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.Inflate(1, 1);
|
||||
|
||||
// Make sure inflate and deflate worked correctly
|
||||
if (rect1 != rect2) {
|
||||
fail("[3] Make sure inflate and deflate worked correctly");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test against a rect that overlaps the left edge of rect1
|
||||
rect2.x--;
|
||||
if (!rect1.Intersects(rect2)) {
|
||||
fail("[4] Test against a rect that overlaps the left edge of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.x++;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the left
|
||||
rect2.x -= rect2.width;
|
||||
if (rect1.Intersects(rect2)) {
|
||||
fail("[5] Test against a rect that's outside of rect1 on the left");
|
||||
return false;
|
||||
}
|
||||
rect2.x += rect2.width;
|
||||
|
||||
// Test against a rect that overlaps the top edge of rect1
|
||||
rect2.y--;
|
||||
if (!rect1.Intersects(rect2)) {
|
||||
fail("[6] Test against a rect that overlaps the top edge of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.y++;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the top
|
||||
rect2.y -= rect2.height;
|
||||
if (rect1.Intersects(rect2)) {
|
||||
fail("[7] Test against a rect that's outside of rect1 on the top");
|
||||
return false;
|
||||
}
|
||||
rect2.y += rect2.height;
|
||||
|
||||
// Test against a rect that overlaps the right edge of rect1
|
||||
rect2.x++;
|
||||
if (!rect1.Intersects(rect2)) {
|
||||
fail("[8] Test against a rect that overlaps the right edge of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.x--;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the right
|
||||
rect2.x += rect2.width;
|
||||
if (rect1.Intersects(rect2)) {
|
||||
fail("[9] Test against a rect that's outside of rect1 on the right");
|
||||
return false;
|
||||
}
|
||||
rect2.x -= rect2.width;
|
||||
|
||||
// Test against a rect that overlaps the bottom edge of rect1
|
||||
rect2.y++;
|
||||
if (!rect1.Intersects(rect2)) {
|
||||
fail("[10] Test against a rect that overlaps the bottom edge of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.y--;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the bottom
|
||||
rect2.y += rect2.height;
|
||||
if (rect1.Intersects(rect2)) {
|
||||
fail("[11] Test against a rect that's outside of rect1 on the bottom");
|
||||
return false;
|
||||
}
|
||||
rect2.y -= rect2.height;
|
||||
|
||||
passed("TestIntersects");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test the method that returns a boolean result and an intersection rect
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestIntersection()
|
||||
{
|
||||
RectType rect1(10, 10, 50, 50);
|
||||
RectType rect2(rect1);
|
||||
RectType dest;
|
||||
|
||||
// Test against a rect that's the same as rect1
|
||||
if (!dest.IntersectRect(rect1, rect2) || (dest != rect1)) {
|
||||
fail("[1] Test against a rect that's the same as rect1");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test against a rect that's enclosed by rect1
|
||||
rect2.Inflate(-1, -1);
|
||||
if (!dest.IntersectRect(rect1, rect2) || (dest != rect2)) {
|
||||
fail("[2] Test against a rect that's enclosed by rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.Inflate(1, 1);
|
||||
|
||||
// Test against a rect that overlaps the left edge of rect1
|
||||
rect2.x--;
|
||||
if (!dest.IntersectRect(rect1, rect2) ||
|
||||
(dest != RectType(rect1.x, rect1.y, rect1.width - 1, rect1.height))) {
|
||||
fail("[3] Test against a rect that overlaps the left edge of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.x++;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the left
|
||||
rect2.x -= rect2.width;
|
||||
if (dest.IntersectRect(rect1, rect2)) {
|
||||
fail("[4] Test against a rect that's outside of rect1 on the left");
|
||||
return false;
|
||||
}
|
||||
// Make sure an empty rect is returned
|
||||
if (!dest.IsEmpty()) {
|
||||
fail("[4] Make sure an empty rect is returned");
|
||||
return false;
|
||||
}
|
||||
rect2.x += rect2.width;
|
||||
|
||||
// Test against a rect that overlaps the top edge of rect1
|
||||
rect2.y--;
|
||||
if (!dest.IntersectRect(rect1, rect2) ||
|
||||
(dest != RectType(rect1.x, rect1.y, rect1.width, rect1.height - 1))) {
|
||||
fail("[5] Test against a rect that overlaps the top edge of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.y++;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the top
|
||||
rect2.y -= rect2.height;
|
||||
if (dest.IntersectRect(rect1, rect2)) {
|
||||
fail("[6] Test against a rect that's outside of rect1 on the top");
|
||||
return false;
|
||||
}
|
||||
// Make sure an empty rect is returned
|
||||
if (!dest.IsEmpty()) {
|
||||
fail("[6] Make sure an empty rect is returned");
|
||||
return false;
|
||||
}
|
||||
rect2.y += rect2.height;
|
||||
|
||||
// Test against a rect that overlaps the right edge of rect1
|
||||
rect2.x++;
|
||||
if (!dest.IntersectRect(rect1, rect2) ||
|
||||
(dest != RectType(rect1.x + 1, rect1.y, rect1.width - 1, rect1.height))) {
|
||||
fail("[7] Test against a rect that overlaps the right edge of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.x--;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the right
|
||||
rect2.x += rect2.width;
|
||||
if (dest.IntersectRect(rect1, rect2)) {
|
||||
fail("[8] Test against a rect that's outside of rect1 on the right");
|
||||
return false;
|
||||
}
|
||||
// Make sure an empty rect is returned
|
||||
if (!dest.IsEmpty()) {
|
||||
fail("[8] Make sure an empty rect is returned");
|
||||
return false;
|
||||
}
|
||||
rect2.x -= rect2.width;
|
||||
|
||||
// Test against a rect that overlaps the bottom edge of rect1
|
||||
rect2.y++;
|
||||
if (!dest.IntersectRect(rect1, rect2) ||
|
||||
(dest != RectType(rect1.x, rect1.y + 1, rect1.width, rect1.height - 1))) {
|
||||
fail("[9] Test against a rect that overlaps the bottom edge of rect1");
|
||||
return false;
|
||||
}
|
||||
rect2.y--;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the bottom
|
||||
rect2.y += rect2.height;
|
||||
if (dest.IntersectRect(rect1, rect2)) {
|
||||
fail("[10] Test against a rect that's outside of rect1 on the bottom");
|
||||
return false;
|
||||
}
|
||||
// Make sure an empty rect is returned
|
||||
if (!dest.IsEmpty()) {
|
||||
fail("[10] Make sure an empty rect is returned");
|
||||
return false;
|
||||
}
|
||||
rect2.y -= rect2.height;
|
||||
|
||||
// Test against a rect with zero width or height
|
||||
rect1.SetRect(100, 100, 100, 100);
|
||||
rect2.SetRect(150, 100, 0, 100);
|
||||
if (dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) {
|
||||
fail("[11] Intersection of rects with zero width or height should be empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tests against a rect with negative width or height
|
||||
//
|
||||
|
||||
// Test against a rect with negative width
|
||||
rect1.SetRect(100, 100, 100, 100);
|
||||
rect2.SetRect(100, 100, -100, 100);
|
||||
if (dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) {
|
||||
fail("[12] Intersection of rects with negative width or height should be empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Those two rects exactly overlap in some way...
|
||||
// but we still want to return an empty rect
|
||||
rect1.SetRect(100, 100, 100, 100);
|
||||
rect2.SetRect(200, 200, -100, -100);
|
||||
if (dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) {
|
||||
fail("[13] Intersection of rects with negative width or height should be empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test against two identical rects with negative height
|
||||
rect1.SetRect(100, 100, 100, -100);
|
||||
rect2.SetRect(100, 100, 100, -100);
|
||||
if (dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) {
|
||||
fail("[14] Intersection of rects with negative width or height should be empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
passed("TestIntersection");
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestUnion()
|
||||
{
|
||||
RectType rect1;
|
||||
RectType rect2(10, 10, 50, 50);
|
||||
RectType dest;
|
||||
|
||||
// Check the case where the receiver is an empty rect
|
||||
rect1.Empty();
|
||||
if (!dest.UnionRect(rect1, rect2) || (dest != rect2)) {
|
||||
fail("[1] Check the case where the receiver is an empty rect");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the case where the source rect is an empty rect
|
||||
rect1 = rect2;
|
||||
rect2.Empty();
|
||||
if (!dest.UnionRect(rect1, rect2) || (dest != rect1)) {
|
||||
fail("[2] Check the case where the source rect is an empty rect");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test the case where both rects are empty
|
||||
rect1.Empty();
|
||||
rect2.Empty();
|
||||
if (dest.UnionRect(rect1, rect2)) {
|
||||
fail("[3] Test the case where both rects are empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test union case where the two rects don't overlap at all
|
||||
rect1.SetRect(10, 10, 50, 50);
|
||||
rect2.SetRect(100, 100, 50, 50);
|
||||
if (!dest.UnionRect(rect1, rect2) ||
|
||||
(dest != RectType(rect1.x, rect1.y, rect2.XMost() - rect1.x, rect2.YMost() - rect1.y))) {
|
||||
fail("[4] Test union case where the two rects don't overlap at all");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test union case where the two rects overlap
|
||||
rect1.SetRect(30, 30, 50, 50);
|
||||
rect2.SetRect(10, 10, 50, 50);
|
||||
if (!dest.UnionRect(rect1, rect2) ||
|
||||
(dest != RectType(rect2.x, rect2.y, rect1.XMost() - rect2.x, rect1.YMost() - rect2.y))) {
|
||||
fail("[5] Test union case where the two rects overlap");
|
||||
return false;
|
||||
}
|
||||
|
||||
passed("TestUnion");
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ScopedXPCOM xpcom("TestRect");
|
||||
if (xpcom.failed())
|
||||
return -1;
|
||||
|
||||
int rv = 0;
|
||||
|
||||
//-----------------------
|
||||
// Test nsRect
|
||||
//
|
||||
printf("===== nsRect tests =====\n");
|
||||
|
||||
if (!TestConstructors<nsRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestEqualityOperator<nsRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestContainment<nsRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestIntersects<nsRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestIntersection<nsRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestUnion<nsRect>())
|
||||
rv = -1;
|
||||
|
||||
//-----------------------
|
||||
// Test nsIntRect
|
||||
//
|
||||
printf("===== nsIntRect tests =====\n");
|
||||
|
||||
if (!TestConstructors<nsIntRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestEqualityOperator<nsIntRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestContainment<nsIntRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestIntersects<nsIntRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestIntersection<nsIntRect>())
|
||||
rv = -1;
|
||||
|
||||
if (!TestUnion<nsIntRect>())
|
||||
rv = -1;
|
||||
|
||||
return rv;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
# Color Management Test Directive File
|
||||
#
|
||||
# Format:
|
||||
# InputProfileFilename OutputProfileFilename <CRC32 For Each Intent>
|
||||
#
|
||||
sRGB_IEC61966-2-1_noBPC.icc DELL2407WFP-2B283C91.icc 3d68eb2 3371242e
|
||||
sRGB_IEC61966-2-1_noBPC.icc G22LWk-2489A79.icc de8c5443 d56a9e64
|
||||
sRGB_IEC61966-2-1_noBPC.icc MBP20080419-1.icc 4eab8dbf 5297944c
|
||||
sRGB_IEC61966-2-1_noBPC.icc PhLCD17a.icm a703324f 8b92f57e
|
||||
sRGB_IEC61966-2-1_noBPC.icc identity.icc 4c90101e ad73cf0c
|
||||
sRGB_IEC61966-2-1_noBPC.icc murphy.icc b6d926ed 30c4bdfa
|
||||
sRGB_v4_ICC_preference.icc DELL2407WFP-2B283C91.icc 426d8cc3 c77d12ac
|
||||
sRGB_v4_ICC_preference.icc G22LWk-2489A79.icc 55006650 384b6fc2
|
||||
sRGB_v4_ICC_preference.icc MBP20080419-1.icc f297fdbe eae8670f
|
||||
sRGB_v4_ICC_preference.icc PhLCD17a.icm bab9e368 1bbb1b84
|
||||
sRGB_v4_ICC_preference.icc identity.icc fd0d9f54 7d1366b8
|
||||
sRGB_v4_ICC_preference.icc murphy.icc 96f8808 26a59d30
|
||||
sRGB_IEC61966-2-1_noBPC.icc sRGB_v4_ICC_preference.icc 18873ed 6fbaf5db
|
||||
sRGB_v4_ICC_preference.icc sRGB_IEC61966-2-1_noBPC.icc 1fb81a8b 931afa97
|
||||
DELL2407WFP-2B283C91.icc G22LWk-2489A79.icc fd1ad5d6 3013a7d5
|
||||
MBP20080419-1.icc PhLCD17a.icm f7596c76 108012b2
|
@ -1,559 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <cctype>
|
||||
|
||||
#include "qcms.h"
|
||||
|
||||
using std::isspace;
|
||||
|
||||
/* Nabbed from the http://www.jonh.net/~jonh/md5/crc32/crc32.c. License is
|
||||
* "do anything, no restrictions." */
|
||||
unsigned long crc32(const unsigned char *s, unsigned int len);
|
||||
|
||||
/*
|
||||
* Test Framework Header stuff
|
||||
*/
|
||||
|
||||
#define ASSERT(foo) { \
|
||||
if (!(foo)) { \
|
||||
fprintf(stderr, "%s: Failed Assertion Line %d\n", __FILE__, __LINE__); \
|
||||
exit(-1); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CHECK(condition, var, value, message, label) { \
|
||||
if (!(condition)) { \
|
||||
var = value; \
|
||||
fprintf(stderr, message); \
|
||||
goto label; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a,b) ((a) <= (b) ? (a) : (b))
|
||||
#define ABS(a) ((a < 0) ? -a : a)
|
||||
|
||||
#define BITMAP_PIXEL_COUNT (256 * 256 * 256)
|
||||
#define BITMAP_SIZE (BITMAP_PIXEL_COUNT * 3)
|
||||
|
||||
/* Relative, Perceptual, and Saturation all take the same code path through
|
||||
* LCMS. As such, we just check perceptual and absolute. */
|
||||
int testedIntents[] = {INTENT_PERCEPTUAL, INTENT_ABSOLUTE_COLORIMETRIC};
|
||||
#define TESTED_INTENT_COUNT (sizeof(testedIntents)/sizeof(int))
|
||||
|
||||
const char *profileDir = "testprofiles";
|
||||
|
||||
/* Parameters detailing a single test. */
|
||||
struct TestParams {
|
||||
|
||||
/* name of the input profile. */
|
||||
char *iProfileName;
|
||||
|
||||
/* name of the output profile. */
|
||||
char *oProfileName;
|
||||
|
||||
/* Golden CRC32s. */
|
||||
unsigned goldenCRCs[TESTED_INTENT_COUNT];
|
||||
|
||||
/* Did we read golden sums? */
|
||||
int hasGolden;
|
||||
|
||||
/* Generated CRC32. */
|
||||
unsigned ourCRCs[TESTED_INTENT_COUNT];
|
||||
|
||||
/* Linked list pointer. */
|
||||
struct TestParams *next;
|
||||
|
||||
};
|
||||
|
||||
/* Top level context structure for the test run. */
|
||||
struct TestContext {
|
||||
|
||||
/* Base path for files. */
|
||||
char *basePath;
|
||||
|
||||
/* Linked list of param structures. */
|
||||
struct TestParams *paramList;
|
||||
|
||||
/* Our GIANT, ~50 meg buffers for every pixel value. */
|
||||
unsigned char *src, *fixedX, *floatX;
|
||||
|
||||
};
|
||||
|
||||
/* Reads a line from the directive file. Returns 0 on success,
|
||||
-1 on malformed file. */
|
||||
static int
|
||||
ReadTestFileLine(struct TestContext *ctx, FILE *handle)
|
||||
{
|
||||
|
||||
/* Locals. */
|
||||
char buff[4096];
|
||||
int status = 0;
|
||||
char *iter, *base;
|
||||
char *strings[2];
|
||||
char *rv;
|
||||
unsigned i;
|
||||
struct TestParams *params = NULL;
|
||||
|
||||
/* Check input. */
|
||||
ASSERT(ctx != NULL);
|
||||
ASSERT(handle != NULL);
|
||||
|
||||
/* Null out string pointers. */
|
||||
for (i = 0; i < 2; ++i)
|
||||
strings[i] = NULL;
|
||||
|
||||
/* Read in the line. */
|
||||
rv = fgets(buff, 4096, handle);
|
||||
if (feof(handle))
|
||||
goto done;
|
||||
CHECK(rv != NULL, status, -1, "Bad Test File\n", error);
|
||||
|
||||
/* Allow for comments and blanklines. */
|
||||
if ((buff[0] == '#') || isspace(buff[0]))
|
||||
goto done;
|
||||
|
||||
/* Allocate a param file. */
|
||||
params = (struct TestParams *) calloc(sizeof(struct TestParams), 1);
|
||||
ASSERT(params);
|
||||
|
||||
/* Parse the profile names. */
|
||||
iter = buff;
|
||||
for (i = 0; i < 2; ++i) {
|
||||
for (base = iter; (*iter != '\0') && !isspace(*iter); ++iter);
|
||||
*iter = '\0';
|
||||
CHECK((iter - base) > 0, status, -1, "Bad Test File\n", error);
|
||||
strings[i] = strdup(base);
|
||||
++iter;
|
||||
}
|
||||
|
||||
/* Fill the param file. */
|
||||
params->iProfileName = strings[0];
|
||||
params->oProfileName = strings[1];
|
||||
|
||||
/* Skip any whitespace. */
|
||||
for (; (*iter != '\0') && isspace(*iter); ++iter);
|
||||
|
||||
/* if we have more to parse, we should have golden CRCs. */
|
||||
if (*iter != '\0') {
|
||||
for (i = 0; i < TESTED_INTENT_COUNT; ++i) {
|
||||
params->goldenCRCs[i] = strtoul(iter, &base, 16);
|
||||
CHECK((errno != EINVAL) && (errno != ERANGE) && (base != iter),
|
||||
status, -1, "Bad Checksum List\n", error);
|
||||
iter = base;
|
||||
}
|
||||
params->hasGolden = 1;
|
||||
}
|
||||
|
||||
/* Link up our param structure. */
|
||||
params->next = ctx->paramList;
|
||||
ctx->paramList = params;
|
||||
|
||||
done:
|
||||
return status;
|
||||
|
||||
error:
|
||||
|
||||
/* Free the strings. */
|
||||
for (i = 0; i < 2; ++i)
|
||||
free(strings[i]);
|
||||
|
||||
/* Free the param structure. */
|
||||
if (params != NULL)
|
||||
free(params);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Initializes the test context. 0 on success, -1 on failure. */
|
||||
static int
|
||||
TestInit(struct TestContext *ctx, const char *filePath)
|
||||
{
|
||||
|
||||
/* Locals. */
|
||||
FILE *tfHandle = NULL;
|
||||
const char *iter, *last;
|
||||
unsigned n;
|
||||
int status = 0;
|
||||
unsigned i, j, k, l;
|
||||
struct TestParams *curr, *before, *after;
|
||||
|
||||
/* Checks. */
|
||||
ASSERT(ctx != NULL);
|
||||
ASSERT(filePath != NULL);
|
||||
|
||||
/* Allocate our buffers. If it's going to fail, we should know now. */
|
||||
ctx->src = (unsigned char *) malloc(BITMAP_SIZE);
|
||||
CHECK(ctx->src != NULL, status, -1, "Can't allocate enough memory\n", error);
|
||||
ctx->fixedX = (unsigned char *) malloc(BITMAP_SIZE);
|
||||
CHECK(ctx->fixedX != NULL, status, -1, "Can't allocate enough memory\n", error);
|
||||
ctx->floatX = (unsigned char *) malloc(BITMAP_SIZE);
|
||||
CHECK(ctx->floatX != NULL, status, -1, "Can't allocate enough memory\n", error);
|
||||
|
||||
/* Open the test file. */
|
||||
tfHandle = fopen(filePath, "r");
|
||||
CHECK(tfHandle != NULL, status, -1, "Unable to open test file\n", done);
|
||||
|
||||
/* Extract the base. XXX: Do we need to worry about windows separators? */
|
||||
for (last = iter = filePath; *iter != '\0'; ++iter)
|
||||
if (*iter == '/')
|
||||
last = iter;
|
||||
n = last - filePath;
|
||||
ctx->basePath = (char *) malloc(n + 1);
|
||||
ASSERT(ctx->basePath != NULL);
|
||||
memcpy(ctx->basePath, filePath, n);
|
||||
ctx->basePath[n] = '\0';
|
||||
|
||||
/* Read through the directive file. */
|
||||
while (!feof(tfHandle)) {
|
||||
CHECK(!ReadTestFileLine(ctx, tfHandle), status, -1,
|
||||
"Failed to Read Test File\n", error);
|
||||
}
|
||||
|
||||
/* Reverse the list so that we process things in the order we read them
|
||||
in. */
|
||||
curr = ctx->paramList;
|
||||
before = NULL;
|
||||
while (curr->next != NULL) {
|
||||
after = curr->next;
|
||||
curr->next = before;
|
||||
before = curr;
|
||||
curr = after;
|
||||
}
|
||||
curr->next = before;
|
||||
ctx->paramList = curr;
|
||||
|
||||
/* Generate our source bitmap. */
|
||||
printf("Generating source bitmap...");
|
||||
fflush(stdout);
|
||||
for (i = 0; i < 256; ++i) {
|
||||
for (j = 0; j < 256; ++j)
|
||||
for (k = 0; k < 256; ++k) {
|
||||
l = ((256 * 256 * i) + (256 * j) + k) * 3;
|
||||
ctx->src[l] = (unsigned char) i;
|
||||
ctx->src[l + 1] = (unsigned char) j;
|
||||
ctx->src[l + 2] = (unsigned char) k;
|
||||
}
|
||||
}
|
||||
ASSERT(l == (BITMAP_SIZE - 3));
|
||||
printf("done!\n");
|
||||
|
||||
goto done;
|
||||
|
||||
error:
|
||||
/* Free up the buffers. */
|
||||
if (ctx->src != NULL)
|
||||
free(ctx->src);
|
||||
if (ctx->fixedX != NULL)
|
||||
free(ctx->fixedX);
|
||||
if (ctx->floatX != NULL)
|
||||
free(ctx->floatX);
|
||||
|
||||
done:
|
||||
|
||||
/* We're done with the test directive file. */
|
||||
if (tfHandle != NULL)
|
||||
fclose(tfHandle);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Runs a test for the given param structure. Returns 0 on success (even if
|
||||
* the test itself fails), -1 on code failure.
|
||||
*
|
||||
* 'mode' is either "generate" or "check".
|
||||
*
|
||||
* 'intentIndex' is an index in testedIntents
|
||||
*/
|
||||
static int
|
||||
RunTest(struct TestContext *ctx, struct TestParams *params,
|
||||
char *mode, unsigned intentIndex)
|
||||
{
|
||||
|
||||
/* Locals. */
|
||||
cmsHPROFILE inProfile = NULL;
|
||||
cmsHPROFILE outProfile = NULL;
|
||||
cmsHTRANSFORM transformFixed = NULL;
|
||||
cmsHTRANSFORM transformFloat = NULL;
|
||||
char *filePath;
|
||||
unsigned i;
|
||||
int difference;
|
||||
int failures;
|
||||
int status = 0;
|
||||
|
||||
/* Allocate a big enough string for either file path. */
|
||||
filePath = (char *)malloc(strlen(ctx->basePath) + 1 +
|
||||
strlen(profileDir) + 1 +
|
||||
MAX(strlen(params->iProfileName),
|
||||
strlen(params->oProfileName)) + 1);
|
||||
ASSERT(filePath != NULL);
|
||||
|
||||
/* Set up the profile path for the input profile. */
|
||||
strcpy(filePath, ctx->basePath);
|
||||
strcat(filePath, "/");
|
||||
strcat(filePath, profileDir);
|
||||
strcat(filePath, "/");
|
||||
strcat(filePath, params->iProfileName);
|
||||
inProfile = cmsOpenProfileFromFile(filePath, "r");
|
||||
CHECK(inProfile != NULL, status, -1, "unable to open input profile!\n", done);
|
||||
|
||||
/* Set up the profile path for the output profile. */
|
||||
strcpy(filePath, ctx->basePath);
|
||||
strcat(filePath, "/");
|
||||
strcat(filePath, profileDir);
|
||||
strcat(filePath, "/");
|
||||
strcat(filePath, params->oProfileName);
|
||||
outProfile = cmsOpenProfileFromFile(filePath, "r");
|
||||
CHECK(outProfile != NULL, status, -1, "unable to open input profile!\n", done);
|
||||
|
||||
/* Precache. */
|
||||
cmsPrecacheProfile(inProfile, CMS_PRECACHE_LI16W_FORWARD);
|
||||
cmsPrecacheProfile(inProfile, CMS_PRECACHE_LI8F_FORWARD);
|
||||
cmsPrecacheProfile(outProfile, CMS_PRECACHE_LI1616_REVERSE);
|
||||
cmsPrecacheProfile(outProfile, CMS_PRECACHE_LI168_REVERSE);
|
||||
|
||||
/* Create the fixed transform. */
|
||||
transformFixed = cmsCreateTransform(inProfile, TYPE_RGB_8,
|
||||
outProfile, TYPE_RGB_8,
|
||||
testedIntents[intentIndex], 0);
|
||||
CHECK(transformFixed != NULL, status, -1,
|
||||
"unable to create fixed transform!\n", done);
|
||||
|
||||
/* Do the fixed transform. */
|
||||
cmsDoTransform(transformFixed, ctx->src, ctx->fixedX, BITMAP_PIXEL_COUNT);
|
||||
|
||||
/* Compute the CRC of the fixed transform. */
|
||||
params->ourCRCs[intentIndex] = crc32(ctx->fixedX, BITMAP_SIZE);
|
||||
|
||||
/* If we're just generating, we have everything we need. */
|
||||
if (!strcmp(mode, "generate")) {
|
||||
printf("In: %s, Out: %s, Intent: %u Generated\n",
|
||||
params->iProfileName, params->oProfileName, testedIntents[intentIndex]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Create the float transform. */
|
||||
transformFloat = cmsCreateTransform(inProfile, TYPE_RGB_8,
|
||||
outProfile, TYPE_RGB_8,
|
||||
testedIntents[intentIndex],
|
||||
cmsFLAGS_FLOATSHAPER);
|
||||
CHECK(transformFloat != NULL, status, -1,
|
||||
"unable to create float transform!\n", done);
|
||||
|
||||
/* Make sure we have golden values. */
|
||||
CHECK(params->hasGolden, status, -1,
|
||||
"Error: Check mode enabled but no golden values in file\n", done);
|
||||
|
||||
/* Print out header. */
|
||||
printf("In: %s, Out: %s, Intent: %u\n",
|
||||
params->iProfileName, params->oProfileName,
|
||||
testedIntents[intentIndex]);
|
||||
|
||||
/* CRC check the fixed point path. */
|
||||
if (params->goldenCRCs[intentIndex] == params->ourCRCs[intentIndex])
|
||||
printf("\tPASSED - CRC Check of Fixed Point Path\n");
|
||||
else
|
||||
printf("\tFAILED - CRC Check of Fixed Point Path - Expected %x, Got %x\n",
|
||||
params->goldenCRCs[intentIndex], params->ourCRCs[intentIndex]);
|
||||
|
||||
/* Do the floating point transform. */
|
||||
cmsDoTransform(transformFloat, ctx->src, ctx->floatX, BITMAP_PIXEL_COUNT);
|
||||
|
||||
/* Compare fixed with floating. */
|
||||
failures = 0;
|
||||
for (i = 0; i < BITMAP_SIZE; ++i) {
|
||||
difference = (int)ctx->fixedX[i] - (int)ctx->floatX[i];
|
||||
/* Allow off-by-one from fixed point, nothing more. */
|
||||
if (ABS(difference) > 1)
|
||||
++failures;
|
||||
}
|
||||
if (failures == 0)
|
||||
printf("\tPASSED - floating point path within acceptable parameters\n");
|
||||
else
|
||||
printf("\tWARNING - floating point path off by 2 or more in %d cases!\n",
|
||||
failures);
|
||||
|
||||
done:
|
||||
|
||||
/* Free the temporary string. */
|
||||
free(filePath);
|
||||
|
||||
/* Close the transforms and profiles if non-null. */
|
||||
if (transformFixed != NULL)
|
||||
cmsDeleteTransform(transformFixed);
|
||||
if (transformFloat != NULL)
|
||||
cmsDeleteTransform(transformFloat);
|
||||
if (inProfile != NULL)
|
||||
cmsCloseProfile(inProfile);
|
||||
if (outProfile != NULL)
|
||||
cmsCloseProfile(outProfile);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Writes the in memory data structures out to the original test directive
|
||||
* file, using the generated CRCs as golden CRCs. */
|
||||
static int
|
||||
WriteTestFile(struct TestContext *ctx, const char *filename)
|
||||
{
|
||||
|
||||
/* Locals. */
|
||||
FILE *tfHandle = NULL;
|
||||
int status = 0;
|
||||
struct TestParams *iter;
|
||||
unsigned i;
|
||||
|
||||
/* Check Input. */
|
||||
ASSERT(ctx != NULL);
|
||||
ASSERT(filename != NULL);
|
||||
|
||||
/* Open the file in write mode. */
|
||||
tfHandle = fopen(filename, "w");
|
||||
CHECK(tfHandle != NULL, status, -1, "Couldn't Open Test File For Writing",
|
||||
done);
|
||||
|
||||
/* Print Instructional Comment. */
|
||||
fprintf(tfHandle, "# Color Management Test Directive File\n#\n# Format:\n"
|
||||
"# InputProfileFilename OutputProfileFilename "
|
||||
"<CRC32 For Each Intent>\n#\n");
|
||||
/* Iterate and Print. */
|
||||
for (iter = ctx->paramList; iter != NULL; iter = iter->next) {
|
||||
fprintf(tfHandle, "%s %s", iter->iProfileName, iter->oProfileName);
|
||||
for (i = 0; i < TESTED_INTENT_COUNT; ++i)
|
||||
fprintf(tfHandle, " %x", iter->ourCRCs[i]);
|
||||
fprintf(tfHandle, "\n");
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
/* Close the test file. */
|
||||
if (tfHandle != NULL)
|
||||
fclose(tfHandle);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Main Function. */
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
|
||||
/* Locals. */
|
||||
struct TestContext ctx;
|
||||
struct TestParams *iter;
|
||||
unsigned i;
|
||||
int status = 0;
|
||||
|
||||
/* Zero out context. */
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
|
||||
if ((argc != 3) ||
|
||||
(strcmp(argv[1], "generate") && strcmp(argv[1], "check"))) {
|
||||
printf("Usage: %s generate|check PATH/FILE.cmtest\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize the test. */
|
||||
TestInit(&ctx, argv[2]);
|
||||
|
||||
/* Run each individual test. */
|
||||
iter = ctx.paramList;
|
||||
while (iter != NULL) {
|
||||
|
||||
/* For each intent. */
|
||||
for (i = 0; i < TESTED_INTENT_COUNT; ++i)
|
||||
CHECK(!RunTest(&ctx, iter, argv[1], i),
|
||||
status, -1, "RunTest Failed\n", done);
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
/* If we're generating, write back out. */
|
||||
if (!strcmp(argv[1], "generate"))
|
||||
WriteTestFile(&ctx, argv[2]);
|
||||
|
||||
done:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CRC32 Implementation.
|
||||
*/
|
||||
|
||||
static unsigned long crc32_tab[] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||
0x2d02ef8dL
|
||||
};
|
||||
|
||||
/* Return a 32-bit CRC of the contents of the buffer. */
|
||||
|
||||
unsigned long
|
||||
crc32(const unsigned char *s, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned long crc32val;
|
||||
|
||||
crc32val = 0;
|
||||
for (i = 0; i < len; i ++)
|
||||
{
|
||||
crc32val =
|
||||
crc32_tab[(crc32val ^ s[i]) & 0xff] ^
|
||||
(crc32val >> 8);
|
||||
}
|
||||
return crc32val;
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ relativesrcdir = @relativesrcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)
|
||||
|
||||
# Create a GTest library
|
||||
MODULE_NAME = gfxtest
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
@ -3,13 +3,14 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TestHarness.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "nsColor.h"
|
||||
#include "nsColorNames.h"
|
||||
#include "prprf.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
// define an array of all color names
|
||||
#define GFX_COLOR(_name, _value) #_name,
|
||||
@ -25,6 +26,8 @@ static const nscolor kColors[] = {
|
||||
};
|
||||
#undef GFX_COLOR
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
static const char* kJunkNames[] = {
|
||||
nullptr,
|
||||
"",
|
||||
@ -34,15 +37,9 @@ static const char* kJunkNames[] = {
|
||||
"#@$&@#*@*$@$#"
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ScopedXPCOM xpcom("TestColorNames");
|
||||
if (xpcom.failed())
|
||||
return 1;
|
||||
|
||||
static
|
||||
void RunColorTests() {
|
||||
nscolor rgb;
|
||||
int rv = 0;
|
||||
|
||||
// First make sure we can find all of the tags that are supposed to
|
||||
// be in the table. Futz with the case to make sure any case will
|
||||
// work
|
||||
@ -52,27 +49,17 @@ int main(int argc, char** argv)
|
||||
nsCString tagName(kColorNames[index]);
|
||||
|
||||
// Check that color lookup by name gets the right rgb value
|
||||
if (!NS_ColorNameToRGB(NS_ConvertASCIItoUTF16(tagName), &rgb)) {
|
||||
fail("can't find '%s'", tagName.get());
|
||||
rv = 1;
|
||||
}
|
||||
if (rgb != kColors[index]) {
|
||||
fail("name='%s' ColorNameToRGB=%x kColors[%d]=%08x",
|
||||
tagName.get(), rgb, index, kColors[index]);
|
||||
rv = 1;
|
||||
}
|
||||
ASSERT_TRUE(NS_ColorNameToRGB(NS_ConvertASCIItoUTF16(tagName), &rgb)) <<
|
||||
"can't find '" << tagName.get() << "'";
|
||||
ASSERT_TRUE((rgb == kColors[index])) <<
|
||||
"failed at index " << index << " out of " << ArrayLength(kColorNames);
|
||||
|
||||
// fiddle with the case to make sure we can still find it
|
||||
tagName.SetCharAt(tagName.CharAt(0) - 32, 0);
|
||||
if (!NS_ColorNameToRGB(NS_ConvertASCIItoUTF16(tagName), &rgb)) {
|
||||
fail("can't find '%s'", tagName.get());
|
||||
rv = 1;
|
||||
}
|
||||
if (rgb != kColors[index]) {
|
||||
fail("name='%s' ColorNameToRGB=%x kColors[%d]=%08x",
|
||||
tagName.get(), rgb, index, kColors[index]);
|
||||
rv = 1;
|
||||
}
|
||||
ASSERT_TRUE(NS_ColorNameToRGB(NS_ConvertASCIItoUTF16(tagName), &rgb)) <<
|
||||
"can't find '" << tagName.get() << "'";
|
||||
ASSERT_TRUE((rgb == kColors[index])) <<
|
||||
"failed at index " << index << " out of " << ArrayLength(kColorNames);
|
||||
|
||||
// Check that parsing an RGB value in hex gets the right values
|
||||
uint8_t r = NS_GET_R(rgb);
|
||||
@ -86,26 +73,27 @@ int main(int argc, char** argv)
|
||||
char cbuf[50];
|
||||
PR_snprintf(cbuf, sizeof(cbuf), "%02x%02x%02x", r, g, b);
|
||||
nscolor hexrgb;
|
||||
if (!NS_HexToRGB(NS_ConvertASCIItoUTF16(cbuf), &hexrgb)) {
|
||||
fail("hex conversion to color of '%s'", cbuf);
|
||||
rv = 1;
|
||||
}
|
||||
if (hexrgb != rgb) {
|
||||
fail("rgb=%x hexrgb=%x", rgb, hexrgb);
|
||||
rv = 1;
|
||||
}
|
||||
ASSERT_TRUE(NS_HexToRGB(NS_ConvertASCIItoUTF16(cbuf), &hexrgb)) <<
|
||||
"hex conversion to color of '" << cbuf << "'";
|
||||
ASSERT_TRUE(hexrgb == rgb);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void RunJunkColorTests() {
|
||||
nscolor rgb;
|
||||
// Now make sure we don't find some garbage
|
||||
for (uint32_t i = 0; i < ArrayLength(kJunkNames); i++) {
|
||||
nsCString tag(kJunkNames[i]);
|
||||
if (NS_ColorNameToRGB(NS_ConvertASCIItoUTF16(tag), &rgb)) {
|
||||
fail("found '%s'", kJunkNames[i] ? kJunkNames[i] : "(null)");
|
||||
rv = 1;
|
||||
}
|
||||
ASSERT_FALSE(NS_ColorNameToRGB(NS_ConvertASCIItoUTF16(tag), &rgb)) <<
|
||||
"Failed at junk color " << kJunkNames[i];
|
||||
}
|
||||
|
||||
if (rv == 0)
|
||||
passed("TestColorNames");
|
||||
return rv;
|
||||
}
|
||||
|
||||
TEST(Gfx, ColorNames) {
|
||||
RunColorTests();
|
||||
}
|
||||
|
||||
TEST(Gfx, JunkColorNames) {
|
||||
RunJunkColorTests();
|
||||
}
|
367
gfx/tests/gtest/TestRect.cpp
Normal file
367
gfx/tests/gtest/TestRect.cpp
Normal file
@ -0,0 +1,367 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "nsRect.h"
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestConstructors()
|
||||
{
|
||||
// Create a rectangle
|
||||
RectType rect1(10, 20, 30, 40);
|
||||
|
||||
// Make sure the rectangle was properly initialized
|
||||
EXPECT_TRUE(rect1.x == 10 && rect1.y == 20 &&
|
||||
rect1.width == 30 && rect1.height == 40) <<
|
||||
"[1] Make sure the rectangle was properly initialized with constructor";
|
||||
|
||||
// Create a second rect using the copy constructor
|
||||
RectType rect2(rect1);
|
||||
|
||||
// Make sure the rectangle was properly initialized
|
||||
EXPECT_TRUE(rect2.x == rect1.x && rect2.y == rect2.y &&
|
||||
rect2.width == rect2.width && rect2.height == rect2.height) <<
|
||||
"[2] Make sure the rectangle was properly initialized with copy constructor";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestEqualityOperator()
|
||||
{
|
||||
RectType rect1(10, 20, 30, 40);
|
||||
RectType rect2(rect1);
|
||||
|
||||
// Test the equality operator
|
||||
EXPECT_TRUE(rect1 == rect2) <<
|
||||
"[1] Test the equality operator";
|
||||
|
||||
EXPECT_FALSE(!rect1.IsEqualInterior(rect2)) <<
|
||||
"[2] Test the inequality operator";
|
||||
|
||||
// Make sure that two empty rects are equal
|
||||
rect1.SetEmpty();
|
||||
rect2.SetEmpty();
|
||||
EXPECT_TRUE(rect1 == rect2) <<
|
||||
"[3] Make sure that two empty rects are equal";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestContainment()
|
||||
{
|
||||
RectType rect1(10, 10, 50, 50);
|
||||
|
||||
// Test the point containment methods
|
||||
//
|
||||
|
||||
// Basic test of a point in the middle of the rect
|
||||
EXPECT_FALSE(!rect1.Contains(rect1.x + rect1.width/2, rect1.y + rect1.height/2)) <<
|
||||
"[1] Basic test of a point in the middle of the rect";
|
||||
|
||||
// Test against a point at the left/top edges
|
||||
EXPECT_FALSE(!rect1.Contains(rect1.x, rect1.y)) <<
|
||||
"[2] Test against a point at the left/top edges";
|
||||
|
||||
// Test against a point at the right/bottom extents
|
||||
EXPECT_FALSE(rect1.Contains(rect1.XMost(), rect1.YMost())) <<
|
||||
"[3] Test against a point at the right/bottom extents";
|
||||
|
||||
// Test the rect containment methods
|
||||
//
|
||||
RectType rect2(rect1);
|
||||
|
||||
// Test against a rect that's the same as rect1
|
||||
EXPECT_FALSE(!rect1.Contains(rect2)) <<
|
||||
"[4] Test against a rect that's the same as rect1";
|
||||
|
||||
// Test against a rect whose left edge (only) is outside of rect1
|
||||
rect2.x--;
|
||||
EXPECT_FALSE(rect1.Contains(rect2)) <<
|
||||
"[5] Test against a rect whose left edge (only) is outside of rect1";
|
||||
rect2.x++;
|
||||
|
||||
// Test against a rect whose top edge (only) is outside of rect1
|
||||
rect2.y--;
|
||||
EXPECT_FALSE(rect1.Contains(rect2)) <<
|
||||
"[6] Test against a rect whose top edge (only) is outside of rect1";
|
||||
rect2.y++;
|
||||
|
||||
// Test against a rect whose right edge (only) is outside of rect1
|
||||
rect2.x++;
|
||||
EXPECT_FALSE(rect1.Contains(rect2)) <<
|
||||
"[7] Test against a rect whose right edge (only) is outside of rect1";
|
||||
rect2.x--;
|
||||
|
||||
// Test against a rect whose bottom edge (only) is outside of rect1
|
||||
rect2.y++;
|
||||
EXPECT_FALSE(rect1.Contains(rect2)) <<
|
||||
"[8] Test against a rect whose bottom edge (only) is outside of rect1";
|
||||
rect2.y--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test the method that returns a boolean result but doesn't return a
|
||||
// a rectangle
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestIntersects()
|
||||
{
|
||||
RectType rect1(10, 10, 50, 50);
|
||||
RectType rect2(rect1);
|
||||
|
||||
// Test against a rect that's the same as rect1
|
||||
EXPECT_FALSE(!rect1.Intersects(rect2)) <<
|
||||
"[1] Test against a rect that's the same as rect1";
|
||||
|
||||
// Test against a rect that's enclosed by rect1
|
||||
rect2.Inflate(-1, -1);
|
||||
EXPECT_FALSE(!rect1.Contains(rect2) || !rect1.Intersects(rect2)) <<
|
||||
"[2] Test against a rect that's enclosed by rect1";
|
||||
rect2.Inflate(1, 1);
|
||||
|
||||
// Make sure inflate and deflate worked correctly
|
||||
EXPECT_TRUE(rect1.IsEqualInterior(rect2)) <<
|
||||
"[3] Make sure inflate and deflate worked correctly";
|
||||
|
||||
// Test against a rect that overlaps the left edge of rect1
|
||||
rect2.x--;
|
||||
EXPECT_FALSE(!rect1.Intersects(rect2)) <<
|
||||
"[4] Test against a rect that overlaps the left edge of rect1";
|
||||
rect2.x++;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the left
|
||||
rect2.x -= rect2.width;
|
||||
EXPECT_FALSE(rect1.Intersects(rect2)) <<
|
||||
"[5] Test against a rect that's outside of rect1 on the left";
|
||||
rect2.x += rect2.width;
|
||||
|
||||
// Test against a rect that overlaps the top edge of rect1
|
||||
rect2.y--;
|
||||
EXPECT_FALSE(!rect1.Intersects(rect2)) <<
|
||||
"[6] Test against a rect that overlaps the top edge of rect1";
|
||||
rect2.y++;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the top
|
||||
rect2.y -= rect2.height;
|
||||
EXPECT_FALSE(rect1.Intersects(rect2)) <<
|
||||
"[7] Test against a rect that's outside of rect1 on the top";
|
||||
rect2.y += rect2.height;
|
||||
|
||||
// Test against a rect that overlaps the right edge of rect1
|
||||
rect2.x++;
|
||||
EXPECT_FALSE(!rect1.Intersects(rect2)) <<
|
||||
"[8] Test against a rect that overlaps the right edge of rect1";
|
||||
rect2.x--;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the right
|
||||
rect2.x += rect2.width;
|
||||
EXPECT_FALSE(rect1.Intersects(rect2)) <<
|
||||
"[9] Test against a rect that's outside of rect1 on the right";
|
||||
rect2.x -= rect2.width;
|
||||
|
||||
// Test against a rect that overlaps the bottom edge of rect1
|
||||
rect2.y++;
|
||||
EXPECT_FALSE(!rect1.Intersects(rect2)) <<
|
||||
"[10] Test against a rect that overlaps the bottom edge of rect1";
|
||||
rect2.y--;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the bottom
|
||||
rect2.y += rect2.height;
|
||||
EXPECT_FALSE(rect1.Intersects(rect2)) <<
|
||||
"[11] Test against a rect that's outside of rect1 on the bottom";
|
||||
rect2.y -= rect2.height;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test the method that returns a boolean result and an intersection rect
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestIntersection()
|
||||
{
|
||||
RectType rect1(10, 10, 50, 50);
|
||||
RectType rect2(rect1);
|
||||
RectType dest;
|
||||
|
||||
// Test against a rect that's the same as rect1
|
||||
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect1))) <<
|
||||
"[1] Test against a rect that's the same as rect1";
|
||||
|
||||
// Test against a rect that's enclosed by rect1
|
||||
rect2.Inflate(-1, -1);
|
||||
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect2))) <<
|
||||
"[2] Test against a rect that's enclosed by rect1";
|
||||
rect2.Inflate(1, 1);
|
||||
|
||||
// Test against a rect that overlaps the left edge of rect1
|
||||
rect2.x--;
|
||||
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
|
||||
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width - 1, rect1.height)))) <<
|
||||
"[3] Test against a rect that overlaps the left edge of rect1";
|
||||
rect2.x++;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the left
|
||||
rect2.x -= rect2.width;
|
||||
EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) <<
|
||||
"[4] Test against a rect that's outside of rect1 on the left";
|
||||
// Make sure an empty rect is returned
|
||||
EXPECT_FALSE(!dest.IsEmpty()) <<
|
||||
"[4] Make sure an empty rect is returned";
|
||||
rect2.x += rect2.width;
|
||||
|
||||
// Test against a rect that overlaps the top edge of rect1
|
||||
rect2.y--;
|
||||
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
|
||||
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width, rect1.height - 1)))) <<
|
||||
"[5] Test against a rect that overlaps the top edge of rect1";
|
||||
rect2.y++;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the top
|
||||
rect2.y -= rect2.height;
|
||||
EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) <<
|
||||
"[6] Test against a rect that's outside of rect1 on the top";
|
||||
// Make sure an empty rect is returned
|
||||
EXPECT_FALSE(!dest.IsEmpty()) <<
|
||||
"[6] Make sure an empty rect is returned";
|
||||
rect2.y += rect2.height;
|
||||
|
||||
// Test against a rect that overlaps the right edge of rect1
|
||||
rect2.x++;
|
||||
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
|
||||
!(dest.IsEqualInterior(RectType(rect1.x + 1, rect1.y, rect1.width - 1, rect1.height)))) <<
|
||||
"[7] Test against a rect that overlaps the right edge of rect1";
|
||||
rect2.x--;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the right
|
||||
rect2.x += rect2.width;
|
||||
EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) <<
|
||||
"[8] Test against a rect that's outside of rect1 on the right";
|
||||
// Make sure an empty rect is returned
|
||||
EXPECT_FALSE(!dest.IsEmpty()) <<
|
||||
"[8] Make sure an empty rect is returned";
|
||||
rect2.x -= rect2.width;
|
||||
|
||||
// Test against a rect that overlaps the bottom edge of rect1
|
||||
rect2.y++;
|
||||
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
|
||||
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y + 1, rect1.width, rect1.height - 1)))) <<
|
||||
"[9] Test against a rect that overlaps the bottom edge of rect1";
|
||||
rect2.y--;
|
||||
|
||||
// Test against a rect that's outside of rect1 on the bottom
|
||||
rect2.y += rect2.height;
|
||||
EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) <<
|
||||
"[10] Test against a rect that's outside of rect1 on the bottom";
|
||||
// Make sure an empty rect is returned
|
||||
EXPECT_FALSE(!dest.IsEmpty()) <<
|
||||
"[10] Make sure an empty rect is returned";
|
||||
rect2.y -= rect2.height;
|
||||
|
||||
// Test against a rect with zero width or height
|
||||
rect1.SetRect(100, 100, 100, 100);
|
||||
rect2.SetRect(150, 100, 0, 100);
|
||||
EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) <<
|
||||
"[11] Intersection of rects with zero width or height should be empty";
|
||||
|
||||
// Tests against a rect with negative width or height
|
||||
//
|
||||
|
||||
// Test against a rect with negative width
|
||||
rect1.SetRect(100, 100, 100, 100);
|
||||
rect2.SetRect(100, 100, -100, 100);
|
||||
EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) <<
|
||||
"[12] Intersection of rects with negative width or height should be empty";
|
||||
|
||||
// Those two rects exactly overlap in some way...
|
||||
// but we still want to return an empty rect
|
||||
rect1.SetRect(100, 100, 100, 100);
|
||||
rect2.SetRect(200, 200, -100, -100);
|
||||
EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) <<
|
||||
"[13] Intersection of rects with negative width or height should be empty";
|
||||
|
||||
// Test against two identical rects with negative height
|
||||
rect1.SetRect(100, 100, 100, -100);
|
||||
rect2.SetRect(100, 100, 100, -100);
|
||||
EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) <<
|
||||
"[14] Intersection of rects with negative width or height should be empty";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RectType>
|
||||
static bool
|
||||
TestUnion()
|
||||
{
|
||||
RectType rect1;
|
||||
RectType rect2(10, 10, 50, 50);
|
||||
RectType dest;
|
||||
|
||||
// Check the case where the receiver is an empty rect
|
||||
rect1.SetEmpty();
|
||||
dest.UnionRect(rect1, rect2);
|
||||
EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect2)) <<
|
||||
"[1] Check the case where the receiver is an empty rect";
|
||||
|
||||
// Check the case where the source rect is an empty rect
|
||||
rect1 = rect2;
|
||||
rect2.SetEmpty();
|
||||
dest.UnionRect(rect1, rect2);
|
||||
EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect1)) <<
|
||||
"[2] Check the case where the source rect is an empty rect";
|
||||
|
||||
// Test the case where both rects are empty
|
||||
rect1.SetEmpty();
|
||||
rect2.SetEmpty();
|
||||
dest.UnionRect(rect1, rect2);
|
||||
EXPECT_FALSE(!dest.IsEmpty()) <<
|
||||
"[3] Test the case where both rects are empty";
|
||||
|
||||
// Test union case where the two rects don't overlap at all
|
||||
rect1.SetRect(10, 10, 50, 50);
|
||||
rect2.SetRect(100, 100, 50, 50);
|
||||
dest.UnionRect(rect1, rect2);
|
||||
EXPECT_FALSE(dest.IsEmpty() ||
|
||||
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect2.XMost() - rect1.x, rect2.YMost() - rect1.y)))) <<
|
||||
"[4] Test union case where the two rects don't overlap at all";
|
||||
|
||||
// Test union case where the two rects overlap
|
||||
rect1.SetRect(30, 30, 50, 50);
|
||||
rect2.SetRect(10, 10, 50, 50);
|
||||
dest.UnionRect(rect1, rect2);
|
||||
EXPECT_FALSE(dest.IsEmpty() ||
|
||||
!(dest.IsEqualInterior(RectType(rect2.x, rect2.y, rect1.XMost() - rect2.x, rect1.YMost() - rect2.y)))) <<
|
||||
"[5] Test union case where the two rects overlap";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(Gfx, nsRect) {
|
||||
TestConstructors<nsRect>();
|
||||
TestEqualityOperator<nsRect>();
|
||||
TestContainment<nsRect>();
|
||||
TestIntersects<nsRect>();
|
||||
TestIntersection<nsRect>();
|
||||
TestUnion<nsRect>();
|
||||
}
|
||||
|
||||
TEST(Gfx, nsIntRect) {
|
||||
TestConstructors<nsIntRect>();
|
||||
TestEqualityOperator<nsIntRect>();
|
||||
TestContainment<nsIntRect>();
|
||||
TestIntersects<nsIntRect>();
|
||||
TestIntersection<nsIntRect>();
|
||||
TestUnion<nsIntRect>();
|
||||
}
|
||||
|
@ -3,20 +3,17 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TestHarness.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "nsRegion.h"
|
||||
|
||||
class TestLargestRegion {
|
||||
static bool TestSingleRect(nsRect r) {
|
||||
public:
|
||||
static void TestSingleRect(nsRect r) {
|
||||
nsRegion region(r);
|
||||
if (!region.GetLargestRectangle().IsEqualInterior(r)) {
|
||||
fail("largest rect of singleton %d %d %d %d", r.x, r.y, r.width, r.height);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
EXPECT_TRUE(region.GetLargestRectangle().IsEqualInterior(r));
|
||||
}
|
||||
// Construct a rectangle, remove part of it, then check the remainder
|
||||
static bool TestNonRectangular() {
|
||||
static void TestNonRectangular() {
|
||||
nsRegion r(nsRect(0, 0, 30, 30));
|
||||
|
||||
const int nTests = 19;
|
||||
@ -52,24 +49,19 @@ class TestLargestRegion {
|
||||
{ nsRect(0, 10, 20, 20), 300 }
|
||||
};
|
||||
|
||||
bool success = true;
|
||||
for (int32_t i = 0; i < nTests; i++) {
|
||||
nsRegion r2;
|
||||
r2.Sub(r, tests[i].rect);
|
||||
|
||||
if (!r2.IsComplex())
|
||||
fail("nsRegion code got unexpectedly smarter!");
|
||||
EXPECT_TRUE(r2.IsComplex()) << "nsRegion code got unexpectedly smarter!";
|
||||
|
||||
nsRect largest = r2.GetLargestRectangle();
|
||||
if (largest.width * largest.height != tests[i].expectedArea) {
|
||||
fail("Did not successfully find largest rectangle in non-rectangular region on iteration %d", i);
|
||||
success = false;
|
||||
}
|
||||
EXPECT_TRUE(largest.width * largest.height == tests[i].expectedArea) <<
|
||||
"Did not successfully find largest rectangle in non-rectangular region on iteration " << i;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
static bool TwoRectTest() {
|
||||
static void TwoRectTest() {
|
||||
nsRegion r(nsRect(0, 0, 100, 100));
|
||||
const int nTests = 4;
|
||||
struct {
|
||||
@ -81,68 +73,54 @@ class TestLargestRegion {
|
||||
{ nsRect(25, 0, 75, 40), nsRect(0, 60, 75, 40), 2000 },
|
||||
{ nsRect(0, 0, 75, 40), nsRect(25, 60, 75, 40), 2000 },
|
||||
};
|
||||
bool success = true;
|
||||
for (int32_t i = 0; i < nTests; i++) {
|
||||
nsRegion r2;
|
||||
|
||||
r2.Sub(r, tests[i].rect1);
|
||||
r2.Sub(r2, tests[i].rect2);
|
||||
|
||||
if (!r2.IsComplex())
|
||||
fail("nsRegion code got unexpectedly smarter!");
|
||||
EXPECT_TRUE(r2.IsComplex()) << "nsRegion code got unexpectedly smarter!";
|
||||
|
||||
nsRect largest = r2.GetLargestRectangle();
|
||||
if (largest.width * largest.height != tests[i].expectedArea) {
|
||||
fail("Did not successfully find largest rectangle in two-rect-subtract region on iteration %d", i);
|
||||
success = false;
|
||||
}
|
||||
EXPECT_TRUE(largest.width * largest.height == tests[i].expectedArea) <<
|
||||
"Did not successfully find largest rectangle in two-rect-subtract region on iteration " << i;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
static bool TestContainsSpecifiedRect() {
|
||||
static void TestContainsSpecifiedRect() {
|
||||
nsRegion r(nsRect(0, 0, 100, 100));
|
||||
r.Or(r, nsRect(0, 300, 50, 50));
|
||||
if (!r.GetLargestRectangle(nsRect(0, 300, 10, 10)).IsEqualInterior(nsRect(0, 300, 50, 50))) {
|
||||
fail("Chose wrong rectangle");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
EXPECT_TRUE(r.GetLargestRectangle(nsRect(0, 300, 10, 10)).IsEqualInterior(nsRect(0, 300, 50, 50))) <<
|
||||
"Chose wrong rectangle";
|
||||
}
|
||||
static bool TestContainsSpecifiedOverflowingRect() {
|
||||
static void TestContainsSpecifiedOverflowingRect() {
|
||||
nsRegion r(nsRect(0, 0, 100, 100));
|
||||
r.Or(r, nsRect(0, 300, 50, 50));
|
||||
if (!r.GetLargestRectangle(nsRect(0, 290, 10, 20)).IsEqualInterior(nsRect(0, 300, 50, 50))) {
|
||||
fail("Chose wrong rectangle");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
static bool Test() {
|
||||
if (!TestSingleRect(nsRect(0, 52, 720, 480)) ||
|
||||
!TestSingleRect(nsRect(-20, 40, 50, 20)) ||
|
||||
!TestSingleRect(nsRect(-20, 40, 10, 8)) ||
|
||||
!TestSingleRect(nsRect(-20, -40, 10, 8)) ||
|
||||
!TestSingleRect(nsRect(-10, -10, 20, 20)))
|
||||
return false;
|
||||
if (!TestNonRectangular())
|
||||
return false;
|
||||
if (!TwoRectTest())
|
||||
return false;
|
||||
if (!TestContainsSpecifiedRect())
|
||||
return false;
|
||||
if (!TestContainsSpecifiedOverflowingRect())
|
||||
return false;
|
||||
passed("TestLargestRegion");
|
||||
return true;
|
||||
EXPECT_TRUE(r.GetLargestRectangle(nsRect(0, 290, 10, 20)).IsEqualInterior(nsRect(0, 300, 50, 50))) <<
|
||||
"Chose wrong rectangle";
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
ScopedXPCOM xpcom("TestRegion");
|
||||
if (xpcom.failed())
|
||||
return -1;
|
||||
if (!TestLargestRegion::Test())
|
||||
return -1;
|
||||
return 0;
|
||||
TEST(Gfx, RegionSingleRect) {
|
||||
TestLargestRegion::TestSingleRect(nsRect(0, 52, 720, 480));
|
||||
TestLargestRegion::TestSingleRect(nsRect(-20, 40, 50, 20));
|
||||
TestLargestRegion::TestSingleRect(nsRect(-20, 40, 10, 8));
|
||||
TestLargestRegion::TestSingleRect(nsRect(-20, -40, 10, 8));
|
||||
TestLargestRegion::TestSingleRect(nsRect(-10, -10, 20, 20));
|
||||
}
|
||||
|
||||
TEST(Gfx, RegionNonRectangular) {
|
||||
TestLargestRegion::TestNonRectangular();
|
||||
}
|
||||
|
||||
TEST(Gfx, RegionTwoRectTest) {
|
||||
TestLargestRegion::TwoRectTest();
|
||||
}
|
||||
|
||||
TEST(Gfx, RegionContainsSpecifiedRect) {
|
||||
TestLargestRegion::TestContainsSpecifiedRect();
|
||||
}
|
||||
|
||||
TEST(Gfx, RegionTestContainsSpecifiedOverflowingRect) {
|
||||
TestLargestRegion::TestContainsSpecifiedOverflowingRect();
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsString.h"
|
||||
@ -16,14 +18,6 @@
|
||||
|
||||
#include "gfxFontTest.h"
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#include "gfxTestCocoaHelper.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
#include "gtk/gtk.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
enum {
|
||||
@ -122,7 +116,7 @@ struct TestEntry {
|
||||
nsCString fontName;
|
||||
LiteralArray glyphs;
|
||||
};
|
||||
|
||||
|
||||
void SetRTL()
|
||||
{
|
||||
isRTL = true;
|
||||
@ -186,9 +180,7 @@ struct TestEntry {
|
||||
nsTArray<ExpectItem> expectItems;
|
||||
};
|
||||
|
||||
nsTArray<TestEntry> testList;
|
||||
|
||||
already_AddRefed<gfxContext>
|
||||
static already_AddRefed<gfxContext>
|
||||
MakeContext ()
|
||||
{
|
||||
const int size = 200;
|
||||
@ -198,13 +190,13 @@ MakeContext ()
|
||||
surface = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(size, size),
|
||||
gfxASurface::ContentFromFormat(gfxASurface::ImageFormatRGB24));
|
||||
gfxContext *ctx = new gfxContext(surface);
|
||||
NS_IF_ADDREF(ctx);
|
||||
return ctx;
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surface);
|
||||
return ctx.forget();
|
||||
}
|
||||
|
||||
TestEntry*
|
||||
AddTest (const char *utf8FamilyString,
|
||||
AddTest (nsTArray<TestEntry>& testList,
|
||||
const char *utf8FamilyString,
|
||||
const gfxFontStyle& fontStyle,
|
||||
int stringType,
|
||||
const char *string)
|
||||
@ -219,8 +211,6 @@ AddTest (const char *utf8FamilyString,
|
||||
return &(testList[testList.Length()-1]);
|
||||
}
|
||||
|
||||
void SetupTests();
|
||||
|
||||
void
|
||||
DumpStore (gfxFontTestStore *store) {
|
||||
if (store->items.Length() == 0) {
|
||||
@ -231,7 +221,7 @@ DumpStore (gfxFontTestStore *store) {
|
||||
i < store->items.Length();
|
||||
i++)
|
||||
{
|
||||
printf ("Run[% 2d]: '%s' ", i, nsPromiseFlatCString(store->items[i].platformFont).get());
|
||||
printf ("Run[% 2d]: '%s' ", i, store->items[i].platformFont.BeginReading());
|
||||
|
||||
for (int j = 0; j < store->items[i].num_glyphs; j++)
|
||||
printf ("%d ", int(store->items[i].glyphs[j].index));
|
||||
@ -243,7 +233,7 @@ DumpStore (gfxFontTestStore *store) {
|
||||
void
|
||||
DumpTestExpect (TestEntry *test) {
|
||||
for (uint32_t i = 0; i < test->expectItems.Length(); i++) {
|
||||
printf ("Run[% 2d]: '%s' ", i, nsPromiseFlatCString(test->expectItems[i].fontName).get());
|
||||
printf ("Run[% 2d]: '%s' ", i, test->expectItems[i].fontName.BeginReading());
|
||||
for (uint32_t j = 0; j < test->expectItems[i].glyphs.data.Length(); j++)
|
||||
printf ("%d ", int(test->expectItems[i].glyphs.data[j]));
|
||||
|
||||
@ -251,7 +241,9 @@ DumpTestExpect (TestEntry *test) {
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
void SetupTests(nsTArray<TestEntry>& testList);
|
||||
|
||||
static bool
|
||||
RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
nsRefPtr<gfxFontGroup> fontGroup;
|
||||
|
||||
@ -277,76 +269,44 @@ RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
}
|
||||
|
||||
gfxFontTestStore::NewStore();
|
||||
textRun->Draw(ctx, gfxPoint(0,0), 0, length, nullptr, nullptr);
|
||||
textRun->Draw(ctx, gfxPoint(0,0), gfxFont::GLYPH_FILL, 0, length, nullptr, nullptr, nullptr);
|
||||
gfxFontTestStore *s = gfxFontTestStore::CurrentStore();
|
||||
|
||||
gTextRunCache->RemoveTextRun(textRun);
|
||||
|
||||
if (!test->Check(s)) {
|
||||
DumpStore(s);
|
||||
printf (" expected:\n");
|
||||
DumpTestExpect(test);
|
||||
gfxFontTestStore::DeleteStore();
|
||||
return false;
|
||||
}
|
||||
|
||||
gfxFontTestStore::DeleteStore();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv) {
|
||||
TEST(Gfx, FontSelection) {
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
gtk_init(&argc, &argv);
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
CocoaPoolInit();
|
||||
#endif
|
||||
|
||||
// Initialize XPCOM
|
||||
nsresult rv = NS_InitXPCOM2(nullptr, nullptr, nullptr);
|
||||
if (NS_FAILED(rv))
|
||||
return -1;
|
||||
|
||||
if (!gfxPlatform::GetPlatform())
|
||||
return -1;
|
||||
|
||||
// let's get all the xpcom goop out of the system
|
||||
fflush (stderr);
|
||||
fflush (stdout);
|
||||
|
||||
// don't need to query, we might need to set up some prefs later
|
||||
if (0) {
|
||||
nsresult rv;
|
||||
|
||||
nsAdoptingCString str = Preferences::GetCString("font.name.sans-serif.x-western");
|
||||
printf ("sans-serif.x-western: %s\n", nsPromiseFlatCString(str).get());
|
||||
}
|
||||
|
||||
// set up the tests
|
||||
SetupTests();
|
||||
nsTArray<TestEntry> testList;
|
||||
SetupTests(testList);
|
||||
|
||||
nsRefPtr<gfxContext> context = MakeContext();
|
||||
|
||||
for (uint test = 0;
|
||||
for (uint32_t test = 0;
|
||||
test < testList.Length();
|
||||
test++)
|
||||
{
|
||||
printf ("==== Test %d\n", test);
|
||||
bool result = RunTest (&testList[test], context);
|
||||
if (result) {
|
||||
printf ("Test %d succeeded\n", test);
|
||||
passed++;
|
||||
} else {
|
||||
printf ("Test %d failed\n", test);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
printf ("PASSED: %d FAILED: %d\n", passed, failed);
|
||||
fflush (stderr);
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
// The tests themselves
|
@ -68,31 +68,31 @@
|
||||
|
||||
|
||||
void
|
||||
SetupTests()
|
||||
SetupTests(nsTArray<TestEntry>& testList)
|
||||
{
|
||||
TestEntry *t;
|
||||
|
||||
/* some common styles */
|
||||
gfxFontStyle style_western_normal_16 (FONT_STYLE_NORMAL,
|
||||
NS_FONT_STRETCH_NORMAL,
|
||||
gfxFontStyle style_western_normal_16 (mozilla::gfx::FONT_STYLE_NORMAL,
|
||||
400,
|
||||
0,
|
||||
16.0,
|
||||
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
|
||||
0.0,
|
||||
false, false, false,
|
||||
false, false,
|
||||
NS_LITERAL_STRING(""));
|
||||
|
||||
gfxFontStyle style_western_bold_16 (FONT_STYLE_NORMAL,
|
||||
NS_FONT_STRETCH_NORMAL,
|
||||
gfxFontStyle style_western_bold_16 (mozilla::gfx::FONT_STYLE_NORMAL,
|
||||
700,
|
||||
0,
|
||||
16.0,
|
||||
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
|
||||
0.0,
|
||||
false, false, false,
|
||||
false, false,
|
||||
NS_LITERAL_STRING(""));
|
||||
|
||||
/* Test 0 */
|
||||
t = AddTest ("sans-serif",
|
||||
t = AddTest (testList, "sans-serif",
|
||||
style_western_normal_16,
|
||||
S_ASCII,
|
||||
"ABCD");
|
||||
@ -102,7 +102,7 @@ SetupTests()
|
||||
t->Expect ("gtk2-pango", "Albany AMT", GLYPHS(36, 37, 38, 39));
|
||||
|
||||
/* Test 1 */
|
||||
t = AddTest ("verdana,sans-serif",
|
||||
t = AddTest (testList, "verdana,sans-serif",
|
||||
style_western_normal_16,
|
||||
S_UTF8,
|
||||
"foo\xe2\x80\x91""bar");
|
||||
@ -116,7 +116,7 @@ SetupTests()
|
||||
t->Expect ("macosx", "Verdana", GLYPHS(69, 68, 85));
|
||||
|
||||
/* Test 2 */
|
||||
t = AddTest ("sans-serif",
|
||||
t = AddTest (testList, "sans-serif",
|
||||
style_western_bold_16,
|
||||
S_ASCII,
|
||||
"ABCD");
|
||||
@ -126,28 +126,28 @@ SetupTests()
|
||||
t->Expect ("gtk2-pango", "Albany AMT Bold", GLYPHS(36, 37, 38, 39));
|
||||
|
||||
/* Test 3: RTL Arabic with a ligature and leading and trailing whitespace */
|
||||
t = AddTest ("sans-serif",
|
||||
t = AddTest (testList, "sans-serif",
|
||||
style_western_normal_16,
|
||||
S_UTF8,
|
||||
" \xd8\xaa\xd9\x85 ");
|
||||
t->SetRTL();
|
||||
t->Expect ("macosx", "Helvetica", GLYPHS(3));
|
||||
t->Expect ("macosx", "AlBayan", GLYPHS(47));
|
||||
t->Expect ("macosx", "ArialMT", GLYPHS(919, 993));
|
||||
t->Expect ("macosx", "Helvetica", GLYPHS(3));
|
||||
t->Expect ("win32", "Arial", GLYPHS(3, 919, 994, 3));
|
||||
|
||||
/* Test 4: LTR Arabic with leading and trailing whitespace */
|
||||
t = AddTest ("sans-serif",
|
||||
t = AddTest (testList, "sans-serif",
|
||||
style_western_normal_16,
|
||||
S_UTF8,
|
||||
" \xd9\x85\xd8\xaa ");
|
||||
t->Expect ("macosx", "Helvetica", GLYPHS(3));
|
||||
t->Expect ("macosx", "AlBayan", GLYPHS(2, 47));
|
||||
t->Expect ("macosx", "ArialMT", GLYPHS(993, 919));
|
||||
t->Expect ("macosx", "Helvetica", GLYPHS(3));
|
||||
t->Expect ("win32", "Arial", GLYPHS(3, 994, 919, 3));
|
||||
|
||||
/* Test 5: RTL ASCII with leading whitespace */
|
||||
t = AddTest ("sans-serif",
|
||||
t = AddTest (testList, "sans-serif",
|
||||
style_western_normal_16,
|
||||
S_ASCII,
|
||||
" ab");
|
||||
@ -157,7 +157,7 @@ SetupTests()
|
||||
t->Expect ("gtk2-pango", "Albany AMT", GLYPHS(3, 68, 69));
|
||||
|
||||
/* Test 6: RTL ASCII with trailing whitespace */
|
||||
t = AddTest ("sans-serif",
|
||||
t = AddTest (testList, "sans-serif",
|
||||
style_western_normal_16,
|
||||
S_ASCII,
|
||||
"ab ");
|
||||
@ -168,7 +168,7 @@ SetupTests()
|
||||
|
||||
/* Test 7: Simple ASCII ligature */
|
||||
/* Do we have a Windows font with ligatures? Can we use DejaVu Sans? */
|
||||
t = AddTest ("sans-serif",
|
||||
t = AddTest (testList, "sans-serif",
|
||||
style_western_normal_16,
|
||||
S_ASCII,
|
||||
"fi");
|
||||
@ -177,19 +177,22 @@ SetupTests()
|
||||
|
||||
/* Test 8: DEVANAGARI VOWEL I reordering */
|
||||
/* The glyph for DEVANAGARI VOWEL I 2367 (101) is displayed before the glyph for 2361 (99) */
|
||||
t = AddTest ("sans-serif",
|
||||
t = AddTest (testList, "sans-serif",
|
||||
style_western_normal_16,
|
||||
S_UTF8,
|
||||
"\xe0\xa4\x9a\xe0\xa4\xbe\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x8f"); // 2330 2366 2361 2367 2319
|
||||
t->Expect ("macosx", "DevanagariMT", GLYPHS(71, 100, 101, 99, 60));
|
||||
t->Expect ("win32", "Mangal", GLYPHS(133, 545, 465, 161, 102));
|
||||
|
||||
// Disabled Test 9 & 10 because these appear to vary on mac
|
||||
|
||||
/* Test 9: NWJ test */
|
||||
t = AddTest ("Kartika",
|
||||
style_western_normal_16,
|
||||
S_UTF8,
|
||||
"\xe0\xb4\xb3\xe0\xb5\x8d\xe2\x80\x8d");
|
||||
t->Expect ("win32", "Kartika", GLYPHS(332));
|
||||
//t = AddTest (testList, "Kartika",
|
||||
// style_western_normal_16,
|
||||
// S_UTF8,
|
||||
// "\xe0\xb4\xb3\xe0\xb5\x8d\xe2\x80\x8d");
|
||||
//t->Expect ("macosx", "MalayalamMN", GLYPHS(360));
|
||||
//t->Expect ("win32", "Kartika", GLYPHS(332));
|
||||
|
||||
/* Test 10: NWJ fallback test */
|
||||
/* it isn't clear what we should actually do in this case. Ideally
|
||||
@ -197,9 +200,11 @@ SetupTests()
|
||||
we use sans-serif (i.e. Arial) CSS says we should should really
|
||||
use Arial for U+200D.
|
||||
*/
|
||||
t = AddTest ("sans-serif",
|
||||
style_western_normal_16,
|
||||
S_UTF8,
|
||||
"\xe0\xb4\xb3\xe0\xb5\x8d\xe2\x80\x8d");
|
||||
t->Expect ("win32", "Kartika", GLYPHS(332));
|
||||
//t = AddTest (testList, "sans-serif",
|
||||
// style_western_normal_16,
|
||||
// S_UTF8,
|
||||
// "\xe0\xb4\xb3\xe0\xb5\x8d\xe2\x80\x8d");
|
||||
// Disabled because these appear to vary
|
||||
//t->Expect ("macosx", "MalayalamMN", GLYPHS(360));
|
||||
//t->Expect ("win32", "Kartika", GLYPHS(332));
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
#include "cairo.h"
|
||||
#include "cairo/cairo.h"
|
||||
|
||||
int
|
||||
GetASurfaceRefCount(gfxASurface *s) {
|
||||
@ -138,13 +140,12 @@ TestExistingSurface () {
|
||||
return failures;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv) {
|
||||
TEST(Gfx, SurfaceRefCount) {
|
||||
int fail;
|
||||
|
||||
fail = TestNewSurface();
|
||||
fprintf (stderr, "TestNewSurface: %d failures\n", fail);
|
||||
EXPECT_TRUE(fail == 0) << "TestNewSurface: " << fail << " failures";
|
||||
fail = TestExistingSurface();
|
||||
fprintf (stderr, "TestExistingSurface: %d failures\n", fail);
|
||||
EXPECT_TRUE(fail == 0) << "TestExistingSurface: " << fail << " failures";
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
@ -18,14 +20,6 @@
|
||||
|
||||
#include "gfxFontTest.h"
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#include "gfxTestCocoaHelper.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
#include "gtk/gtk.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
struct TestEntry {
|
||||
@ -38,7 +32,7 @@ TestEntry testList[] = {
|
||||
{ nullptr, nullptr } // terminator
|
||||
};
|
||||
|
||||
already_AddRefed<gfxContext>
|
||||
static already_AddRefed<gfxContext>
|
||||
MakeContext ()
|
||||
{
|
||||
const int size = 200;
|
||||
@ -48,24 +42,23 @@ MakeContext ()
|
||||
surface = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(size, size),
|
||||
gfxASurface::ContentFromFormat(gfxASurface::ImageFormatRGB24));
|
||||
gfxContext *ctx = new gfxContext(surface);
|
||||
NS_IF_ADDREF(ctx);
|
||||
return ctx;
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surface);
|
||||
return ctx.forget();
|
||||
}
|
||||
|
||||
nsRefPtr<gfxFontGroup> fontGroup;
|
||||
const char* lastFamilies = nullptr;
|
||||
|
||||
void
|
||||
static void
|
||||
RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
nsRefPtr<gfxFontGroup> fontGroup;
|
||||
if (!lastFamilies || strcmp(lastFamilies, test->mFamilies)) {
|
||||
gfxFontStyle style_western_normal_16 (FONT_STYLE_NORMAL,
|
||||
NS_FONT_STRETCH_NORMAL,
|
||||
gfxFontStyle style_western_normal_16 (mozilla::gfx::FONT_STYLE_NORMAL,
|
||||
400,
|
||||
0,
|
||||
16.0,
|
||||
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
|
||||
0.0,
|
||||
false, false, false,
|
||||
false, false,
|
||||
NS_LITERAL_STRING(""));
|
||||
|
||||
fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16, nullptr);
|
||||
@ -84,6 +77,7 @@ RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
};
|
||||
uint32_t flags = gfxTextRunFactory::TEXT_IS_PERSISTENT;
|
||||
uint32_t length;
|
||||
gfxFontTestStore::NewStore();
|
||||
if (isASCII) {
|
||||
flags |= gfxTextRunFactory::TEXT_IS_ASCII |
|
||||
gfxTextRunFactory::TEXT_IS_8BIT;
|
||||
@ -97,33 +91,14 @@ RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
|
||||
// Should we test drawing?
|
||||
// textRun->Draw(ctx, gfxPoint(0,0), 0, length, nullptr, nullptr, nullptr);
|
||||
|
||||
|
||||
textRun->GetAdvanceWidth(0, length, nullptr);
|
||||
gfxFontTestStore::DeleteStore();
|
||||
}
|
||||
|
||||
uint32_t iterations = 20;
|
||||
|
||||
int
|
||||
main (int argc, char **argv) {
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
gtk_init(&argc, &argv);
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
CocoaPoolInit();
|
||||
#endif
|
||||
|
||||
// Initialize XPCOM
|
||||
nsresult rv = NS_InitXPCOM2(nullptr, nullptr, nullptr);
|
||||
if (NS_FAILED(rv))
|
||||
return -1;
|
||||
|
||||
if (!gfxPlatform::GetPlatform())
|
||||
return -1;
|
||||
|
||||
// let's get all the xpcom goop out of the system
|
||||
fflush (stderr);
|
||||
fflush (stdout);
|
||||
uint32_t iterations = 1;
|
||||
|
||||
TEST(Gfx, TextRunPref) {
|
||||
nsRefPtr<gfxContext> context = MakeContext();
|
||||
|
||||
// Start timing
|
||||
@ -139,9 +114,7 @@ main (int argc, char **argv) {
|
||||
}
|
||||
|
||||
PRIntervalTime end = PR_IntervalNow();
|
||||
|
||||
|
||||
printf("Elapsed time (ms): %d\n", PR_IntervalToMilliseconds(end - start));
|
||||
|
||||
fflush (stderr);
|
||||
fflush (stdout);
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsString.h"
|
||||
@ -17,14 +19,6 @@
|
||||
#include "gfxFontTest.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#include "gfxTestCocoaHelper.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
#include "gtk/gtk.h"
|
||||
#endif
|
||||
|
||||
class FrameTextRunCache;
|
||||
|
||||
static FrameTextRunCache *gTextRuns = nullptr;
|
||||
@ -61,9 +55,11 @@ MakeTextRun(const PRUnichar *aText, uint32_t aLength,
|
||||
{
|
||||
nsAutoPtr<gfxTextRun> textRun;
|
||||
if (aLength == 0) {
|
||||
textRun = aFontGroup->MakeEmptyTextRun(aParams, aFlags);
|
||||
abort();
|
||||
//textRun = aFontGroup->MakeEmptyTextRun(aParams, aFlags);
|
||||
} else if (aLength == 1 && aText[0] == ' ') {
|
||||
textRun = aFontGroup->MakeSpaceTextRun(aParams, aFlags);
|
||||
abort();
|
||||
//textRun = aFontGroup->MakeSpaceTextRun(aParams, aFlags);
|
||||
} else {
|
||||
textRun = aFontGroup->MakeTextRun(aText, aLength, aParams, aFlags);
|
||||
}
|
||||
@ -77,7 +73,7 @@ MakeTextRun(const PRUnichar *aText, uint32_t aLength,
|
||||
return textRun.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxContext>
|
||||
static already_AddRefed<gfxContext>
|
||||
MakeContext ()
|
||||
{
|
||||
const int size = 200;
|
||||
@ -87,43 +83,22 @@ MakeContext ()
|
||||
surface = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(gfxIntSize(size, size),
|
||||
gfxASurface::ContentFromFormat(gfxASurface::ImageFormatRGB24));
|
||||
gfxContext *ctx = new gfxContext(surface);
|
||||
NS_IF_ADDREF(ctx);
|
||||
return ctx;
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surface);
|
||||
return ctx.forget();
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv) {
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
gtk_init(&argc, &argv);
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
CocoaPoolInit();
|
||||
#endif
|
||||
|
||||
// Initialize XPCOM
|
||||
nsresult rv = NS_InitXPCOM2(nullptr, nullptr, nullptr);
|
||||
if (NS_FAILED(rv))
|
||||
return -1;
|
||||
|
||||
if (!gfxPlatform::GetPlatform())
|
||||
return -1;
|
||||
|
||||
// let's get all the xpcom goop out of the system
|
||||
fflush (stderr);
|
||||
fflush (stdout);
|
||||
|
||||
TEST(Gfx, WordCache) {
|
||||
gTextRuns = new FrameTextRunCache();
|
||||
|
||||
nsRefPtr<gfxContext> ctx = MakeContext();
|
||||
{
|
||||
gfxFontStyle style (FONT_STYLE_NORMAL,
|
||||
NS_FONT_STRETCH_NORMAL,
|
||||
gfxFontStyle style (mozilla::gfx::FONT_STYLE_NORMAL,
|
||||
139,
|
||||
10.0,
|
||||
0,
|
||||
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
|
||||
0.0,
|
||||
false, false, false,
|
||||
false, false,
|
||||
NS_LITERAL_STRING(""));
|
||||
|
||||
nsRefPtr<gfxFontGroup> fontGroup =
|
||||
@ -152,6 +127,7 @@ main (int argc, char **argv) {
|
||||
tr2->GetAdvanceWidth(0, str2.Length(), nullptr);
|
||||
}
|
||||
|
||||
fflush (stderr);
|
||||
fflush (stdout);
|
||||
delete gTextRuns;
|
||||
gTextRuns = nullptr;
|
||||
|
||||
}
|
@ -9,9 +9,17 @@ MODULE = 'gfxtest'
|
||||
LIBRARY_NAME = 'gfxtest'
|
||||
|
||||
GTEST_CPP_SOURCES += [
|
||||
# Hangs on linux in ApplyGdkScreenFontOptions
|
||||
#'gfxFontSelectionTest.cpp',
|
||||
'gfxSurfaceRefCountTest.cpp',
|
||||
# Test works but it doesn't assert anything
|
||||
#'gfxTextRunPerfTest.cpp',
|
||||
'gfxWordCacheTest.cpp',
|
||||
'TestAsyncPanZoomController.cpp',
|
||||
'TestLayers.cpp',
|
||||
'TestTiledLayerBuffer.cpp',
|
||||
'TestRegion.cpp',
|
||||
'TestColorNames.cpp',
|
||||
]
|
||||
|
||||
# Because of gkmedia on windows we wont find these
|
||||
@ -20,6 +28,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows':
|
||||
GTEST_CPP_SOURCES += [
|
||||
'TestBase.cpp',
|
||||
'TestMoz2D.cpp',
|
||||
'TestRect.cpp',
|
||||
'TestPoint.cpp',
|
||||
'TestScaling.cpp',
|
||||
]
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -9,7 +9,7 @@
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "cairo.h"
|
||||
#include "cairo/cairo.h"
|
||||
|
||||
#include "gfxFont.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
@ -284,7 +284,7 @@ JavaScriptChild::AnswerDelete(const ObjectId &objId, const nsString &id, ReturnS
|
||||
return fail(cx, rs);
|
||||
|
||||
RootedValue v(cx);
|
||||
if (!JS_DeletePropertyById2(cx, obj, internedId, v.address()))
|
||||
if (!JS_DeletePropertyById2(cx, obj, internedId, &v))
|
||||
return fail(cx, rs);
|
||||
|
||||
JSBool b;
|
||||
|
@ -508,9 +508,13 @@ class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
|
||||
}
|
||||
|
||||
T *address() const { return ptr; }
|
||||
T get() const { return *ptr; }
|
||||
const T& get() const { return *ptr; }
|
||||
|
||||
operator T() const { return get(); }
|
||||
/*
|
||||
* Return a reference so passing a MutableHandle<T> to something that takes
|
||||
* a |const T&| is not a GC hazard.
|
||||
*/
|
||||
operator const T&() const { return get(); }
|
||||
T operator->() const { return get(); }
|
||||
|
||||
private:
|
||||
|
@ -5709,12 +5709,12 @@ GenerateFFIInterpreterExit(ModuleCompiler &m, const ModuleCompiler::ExitDescript
|
||||
}
|
||||
|
||||
static int32_t
|
||||
ValueToInt32(JSContext *cx, Value *val)
|
||||
ValueToInt32(JSContext *cx, MutableHandleValue val)
|
||||
{
|
||||
int32_t i32;
|
||||
if (!ToInt32(cx, val[0], &i32))
|
||||
if (!ToInt32(cx, val, &i32))
|
||||
return false;
|
||||
val[0] = Int32Value(i32);
|
||||
val.set(Int32Value(i32));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2744,13 +2744,36 @@ BaselineCompiler::emit_JSOP_RUNONCE()
|
||||
return callVM(RunOnceScriptPrologueInfo);
|
||||
}
|
||||
|
||||
static bool
|
||||
DoCreateRestParameter(JSContext *cx, BaselineFrame *frame, MutableHandleValue res)
|
||||
{
|
||||
unsigned numFormals = frame->numFormalArgs() - 1;
|
||||
unsigned numActuals = frame->numActualArgs();
|
||||
unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0;
|
||||
Value *rest = frame->argv() + numFormals;
|
||||
|
||||
JSObject *obj = NewDenseCopiedArray(cx, numRest, rest, NULL);
|
||||
if (!obj)
|
||||
return false;
|
||||
types::FixRestArgumentsType(cx, obj);
|
||||
res.setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool(*DoCreateRestParameterFn)(JSContext *cx, BaselineFrame *, MutableHandleValue);
|
||||
static const VMFunction DoCreateRestParameterInfo =
|
||||
FunctionInfo<DoCreateRestParameterFn>(DoCreateRestParameter);
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_REST()
|
||||
{
|
||||
frame.syncStack(0);
|
||||
|
||||
ICRest_Fallback::Compiler stubCompiler(cx);
|
||||
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
|
||||
prepareVMCall();
|
||||
masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
if (!callVM(DoCreateRestParameterInfo))
|
||||
return false;
|
||||
|
||||
frame.push(R0);
|
||||
|
@ -8197,44 +8197,6 @@ ICTypeOf_Typed::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Rest_Fallback
|
||||
//
|
||||
|
||||
static bool
|
||||
DoCreateRestParameter(JSContext *cx, BaselineFrame *frame, ICRest_Fallback *stub,
|
||||
MutableHandleValue res)
|
||||
{
|
||||
FallbackICSpew(cx, stub, "Rest");
|
||||
|
||||
unsigned numFormals = frame->numFormalArgs() - 1;
|
||||
unsigned numActuals = frame->numActualArgs();
|
||||
unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0;
|
||||
Value *rest = frame->argv() + numFormals;
|
||||
|
||||
JSObject *obj = NewDenseCopiedArray(cx, numRest, rest, NULL);
|
||||
if (!obj)
|
||||
return false;
|
||||
res.setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool(*DoCreateRestParameterFn)(JSContext *cx, BaselineFrame *, ICRest_Fallback *,
|
||||
MutableHandleValue);
|
||||
static const VMFunction DoCreateRestParameterInfo =
|
||||
FunctionInfo<DoCreateRestParameterFn>(DoCreateRestParameter);
|
||||
|
||||
bool
|
||||
ICRest_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
{
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
masm.push(BaselineStubReg); // stub
|
||||
masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg()); // frame pointer
|
||||
|
||||
return tailCallVM(DoCreateRestParameterInfo, masm);
|
||||
}
|
||||
|
||||
static bool
|
||||
DoRetSubFallback(JSContext *cx, BaselineFrame *frame, ICRetSub_Fallback *stub,
|
||||
HandleValue val, uint8_t **resumeAddr)
|
||||
|
@ -5527,38 +5527,6 @@ class ICTypeOf_Typed : public ICFallbackStub
|
||||
};
|
||||
};
|
||||
|
||||
// Rest
|
||||
// JSOP_REST
|
||||
class ICRest_Fallback : public ICFallbackStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
ICRest_Fallback(IonCode *stubCode)
|
||||
: ICFallbackStub(ICStub::Rest_Fallback, stubCode)
|
||||
{ }
|
||||
|
||||
public:
|
||||
static inline ICRest_Fallback *New(ICStubSpace *space, IonCode *code) {
|
||||
if (!code)
|
||||
return NULL;
|
||||
return space->allocate<ICRest_Fallback>(code);
|
||||
}
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
bool generateStubCode(MacroAssembler &masm);
|
||||
|
||||
public:
|
||||
Compiler(JSContext *cx)
|
||||
: ICStubCompiler(cx, ICStub::Rest_Fallback)
|
||||
{ }
|
||||
|
||||
ICStub *getStub(ICStubSpace *space) {
|
||||
return ICRest_Fallback::New(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Stub for JSOP_RETSUB ("returning" from a |finally| block).
|
||||
class ICRetSub_Fallback : public ICFallbackStub
|
||||
{
|
||||
|
@ -144,6 +144,12 @@ CodeGenerator::~CodeGenerator()
|
||||
js_delete(unassociatedScriptCounts_);
|
||||
}
|
||||
|
||||
typedef bool (*StringToNumberFn)(ThreadSafeContext *, JSString *, double *);
|
||||
typedef ParallelResult (*StringToNumberParFn)(ForkJoinSlice *, JSString *, double *);
|
||||
static const VMFunctionsModal StringToNumberInfo = VMFunctionsModal(
|
||||
FunctionInfo<StringToNumberFn>(StringToNumber),
|
||||
FunctionInfo<StringToNumberParFn>(StringToNumberPar));
|
||||
|
||||
bool
|
||||
CodeGenerator::visitValueToInt32(LValueToInt32 *lir)
|
||||
{
|
||||
@ -152,10 +158,19 @@ CodeGenerator::visitValueToInt32(LValueToInt32 *lir)
|
||||
|
||||
Register tag = masm.splitTagForTest(operand);
|
||||
|
||||
Label done, simple, isInt32, isBool, notDouble;
|
||||
Label done, simple, isInt32, isBool, isString, notDouble;
|
||||
// Type-check switch.
|
||||
masm.branchTestInt32(Assembler::Equal, tag, &isInt32);
|
||||
masm.branchTestBoolean(Assembler::Equal, tag, &isBool);
|
||||
MDefinition *input;
|
||||
if (lir->mode() == LValueToInt32::NORMAL)
|
||||
input = lir->mirNormal()->input();
|
||||
else
|
||||
input = lir->mirTruncate()->input();
|
||||
masm.branchEqualTypeIfNeeded(MIRType_Int32, input, tag, &isInt32);
|
||||
masm.branchEqualTypeIfNeeded(MIRType_Boolean, input, tag, &isBool);
|
||||
// Only convert strings to int if we are in a truncation context, like
|
||||
// bitwise operations.
|
||||
if (lir->mode() == LValueToInt32::TRUNCATE)
|
||||
masm.branchEqualTypeIfNeeded(MIRType_String, input, tag, &isString);
|
||||
masm.branchTestDouble(Assembler::NotEqual, tag, ¬Double);
|
||||
|
||||
// If the value is a double, see if it fits in a 32-bit int. We need to ask
|
||||
@ -163,16 +178,13 @@ CodeGenerator::visitValueToInt32(LValueToInt32 *lir)
|
||||
FloatRegister temp = ToFloatRegister(lir->tempFloat());
|
||||
masm.unboxDouble(operand, temp);
|
||||
|
||||
Label fails;
|
||||
switch (lir->mode()) {
|
||||
case LValueToInt32::TRUNCATE:
|
||||
Label fails, isDouble;
|
||||
masm.bind(&isDouble);
|
||||
if (lir->mode() == LValueToInt32::TRUNCATE) {
|
||||
if (!emitTruncateDouble(temp, output))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
JS_ASSERT(lir->mode() == LValueToInt32::NORMAL);
|
||||
masm.convertDoubleToInt32(temp, output, &fails, lir->mir()->canBeNegativeZero());
|
||||
break;
|
||||
} else {
|
||||
masm.convertDoubleToInt32(temp, output, &fails, lir->mirNormal()->canBeNegativeZero());
|
||||
}
|
||||
masm.jump(&done);
|
||||
|
||||
@ -183,10 +195,9 @@ CodeGenerator::visitValueToInt32(LValueToInt32 *lir)
|
||||
// which we can't handle here.
|
||||
masm.branchTestNull(Assembler::NotEqual, tag, &fails);
|
||||
} else {
|
||||
// Test for string or object - then fallthrough to null, which will
|
||||
// also handle undefined.
|
||||
masm.branchTestObject(Assembler::Equal, tag, &fails);
|
||||
masm.branchTestString(Assembler::Equal, tag, &fails);
|
||||
// Test for object - then fallthrough to null, which will also handle
|
||||
// undefined.
|
||||
masm.branchEqualTypeIfNeeded(MIRType_Object, input, tag, &fails);
|
||||
}
|
||||
|
||||
if (fails.used() && !bailoutFrom(&fails, lir->snapshot()))
|
||||
@ -196,14 +207,33 @@ CodeGenerator::visitValueToInt32(LValueToInt32 *lir)
|
||||
masm.mov(Imm32(0), output);
|
||||
masm.jump(&done);
|
||||
|
||||
// Unbox a string, call StringToNumber to get a double back, and jump back
|
||||
// to the snippet generated above about dealing with doubles.
|
||||
if (isString.used()) {
|
||||
masm.bind(&isString);
|
||||
Register str = masm.extractString(operand, ToRegister(lir->temp()));
|
||||
OutOfLineCode *ool = oolCallVM(StringToNumberInfo, lir, (ArgList(), str),
|
||||
StoreFloatRegisterTo(temp));
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
masm.jump(ool->entry());
|
||||
masm.bind(ool->rejoin());
|
||||
masm.jump(&isDouble);
|
||||
}
|
||||
|
||||
// Just unbox a bool, the result is 0 or 1.
|
||||
masm.bind(&isBool);
|
||||
masm.unboxBoolean(operand, output);
|
||||
masm.jump(&done);
|
||||
if (isBool.used()) {
|
||||
masm.bind(&isBool);
|
||||
masm.unboxBoolean(operand, output);
|
||||
masm.jump(&done);
|
||||
}
|
||||
|
||||
// Integers can be unboxed.
|
||||
masm.bind(&isInt32);
|
||||
masm.unboxInt32(operand, output);
|
||||
if (isInt32.used()) {
|
||||
masm.bind(&isInt32);
|
||||
masm.unboxInt32(operand, output);
|
||||
}
|
||||
|
||||
masm.bind(&done);
|
||||
|
||||
@ -4038,7 +4068,7 @@ CodeGenerator::visitEmulatesUndefinedAndBranch(LEmulatesUndefinedAndBranch *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSString *(*ConcatStringsFn)(JSContext *, HandleString, HandleString);
|
||||
typedef JSString *(*ConcatStringsFn)(ThreadSafeContext *, HandleString, HandleString);
|
||||
typedef ParallelResult (*ConcatStringsParFn)(ForkJoinSlice *, HandleString, HandleString,
|
||||
MutableHandleString);
|
||||
static const VMFunctionsModal ConcatStringsInfo = VMFunctionsModal(
|
||||
@ -6135,7 +6165,10 @@ CodeGenerator::visitThrow(LThrow *lir)
|
||||
}
|
||||
|
||||
typedef bool (*BitNotFn)(JSContext *, HandleValue, int *p);
|
||||
static const VMFunction BitNotInfo = FunctionInfo<BitNotFn>(BitNot);
|
||||
typedef ParallelResult (*BitNotParFn)(ForkJoinSlice *, HandleValue, int32_t *);
|
||||
static const VMFunctionsModal BitNotInfo = VMFunctionsModal(
|
||||
FunctionInfo<BitNotFn>(BitNot),
|
||||
FunctionInfo<BitNotParFn>(BitNotPar));
|
||||
|
||||
bool
|
||||
CodeGenerator::visitBitNotV(LBitNotV *lir)
|
||||
@ -6145,11 +6178,22 @@ CodeGenerator::visitBitNotV(LBitNotV *lir)
|
||||
}
|
||||
|
||||
typedef bool (*BitopFn)(JSContext *, HandleValue, HandleValue, int *p);
|
||||
static const VMFunction BitAndInfo = FunctionInfo<BitopFn>(BitAnd);
|
||||
static const VMFunction BitOrInfo = FunctionInfo<BitopFn>(BitOr);
|
||||
static const VMFunction BitXorInfo = FunctionInfo<BitopFn>(BitXor);
|
||||
static const VMFunction BitLhsInfo = FunctionInfo<BitopFn>(BitLsh);
|
||||
static const VMFunction BitRhsInfo = FunctionInfo<BitopFn>(BitRsh);
|
||||
typedef ParallelResult (*BitopParFn)(ForkJoinSlice *, HandleValue, HandleValue, int32_t *);
|
||||
static const VMFunctionsModal BitAndInfo = VMFunctionsModal(
|
||||
FunctionInfo<BitopFn>(BitAnd),
|
||||
FunctionInfo<BitopParFn>(BitAndPar));
|
||||
static const VMFunctionsModal BitOrInfo = VMFunctionsModal(
|
||||
FunctionInfo<BitopFn>(BitOr),
|
||||
FunctionInfo<BitopParFn>(BitOrPar));
|
||||
static const VMFunctionsModal BitXorInfo = VMFunctionsModal(
|
||||
FunctionInfo<BitopFn>(BitXor),
|
||||
FunctionInfo<BitopParFn>(BitXorPar));
|
||||
static const VMFunctionsModal BitLhsInfo = VMFunctionsModal(
|
||||
FunctionInfo<BitopFn>(BitLsh),
|
||||
FunctionInfo<BitopParFn>(BitLshPar));
|
||||
static const VMFunctionsModal BitRhsInfo = VMFunctionsModal(
|
||||
FunctionInfo<BitopFn>(BitRsh),
|
||||
FunctionInfo<BitopParFn>(BitRshPar));
|
||||
|
||||
bool
|
||||
CodeGenerator::visitBitOpV(LBitOpV *lir)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user