1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is Mozilla.org.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corp.
18 * Portions created by the Initial Developer are Copyright (C) 2003
19 * the Initial Developer. All Rights Reserved.
22 * Daniel Glazman (glazman@netscape.com) (Original author)
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
40 #include "nsHTMLEditor.h"
42 #include "nsIContent.h"
43 #include "nsIDocument.h"
44 #include "nsIEditor.h"
45 #include "nsIPresShell.h"
47 #include "nsISelection.h"
49 #include "nsTextEditUtils.h"
50 #include "nsEditorUtils.h"
51 #include "nsHTMLEditUtils.h"
52 #include "nsTextEditRules.h"
53 #include "nsIHTMLEditRules.h"
55 #include "nsIDOMHTMLElement.h"
56 #include "nsIDOMNSHTMLElement.h"
57 #include "nsIDOMNodeList.h"
59 #include "nsIDOMEventTarget.h"
61 #include "nsIPrefBranch.h"
62 #include "nsIPrefService.h"
63 #include "nsIServiceManager.h"
65 #include "nsIDOMCSSValue.h"
66 #include "nsIDOMCSSPrimitiveValue.h"
67 #include "nsIDOMRGBColor.h"
69 #define BLACK_BG_RGB_TRIGGER 0xd0
72 nsHTMLEditor::AbsolutePositionSelection(PRBool aEnabled
)
74 nsAutoEditBatch
beginBatching(this);
75 nsAutoRules
beginRulesSniffing(this,
76 aEnabled
? kOpSetAbsolutePosition
:
77 kOpRemoveAbsolutePosition
,
80 // the line below does not match the code; should it be removed?
81 // Find out if the selection is collapsed:
82 nsCOMPtr
<nsISelection
> selection
;
83 nsresult res
= GetSelection(getter_AddRefs(selection
));
84 if (NS_FAILED(res
)) return res
;
85 if (!selection
) return NS_ERROR_NULL_POINTER
;
87 nsTextRulesInfo
ruleInfo(aEnabled
?
88 nsTextEditRules::kSetAbsolutePosition
:
89 nsTextEditRules::kRemoveAbsolutePosition
);
90 PRBool cancel
, handled
;
91 res
= mRules
->WillDoAction(selection
, &ruleInfo
, &cancel
, &handled
);
92 if (NS_FAILED(res
) || cancel
)
95 return mRules
->DidDoAction(selection
, &ruleInfo
, res
);
99 nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement
**_retval
)
101 nsCOMPtr
<nsIDOMElement
> element
;
102 nsresult res
= GetSelectionContainer(getter_AddRefs(element
));
103 if (NS_FAILED(res
)) return res
;
105 nsAutoString positionStr
;
106 nsCOMPtr
<nsIDOMNode
> node
= do_QueryInterface(element
);
107 nsCOMPtr
<nsIDOMNode
> resultNode
;
109 while (!resultNode
&& !nsEditor::NodeIsType(node
, nsEditProperty::html
)) {
110 res
= mHTMLCSSUtils
->GetComputedProperty(node
, nsEditProperty::cssPosition
,
112 if (NS_FAILED(res
)) return res
;
113 if (positionStr
.EqualsLiteral("absolute"))
116 nsCOMPtr
<nsIDOMNode
> parentNode
;
117 res
= node
->GetParentNode(getter_AddRefs(parentNode
));
118 if (NS_FAILED(res
)) return res
;
119 node
.swap(parentNode
);
123 element
= do_QueryInterface(resultNode
);
125 NS_IF_ADDREF(*_retval
);
130 nsHTMLEditor::GetSelectionContainerAbsolutelyPositioned(PRBool
*aIsSelectionContainerAbsolutelyPositioned
)
132 *aIsSelectionContainerAbsolutelyPositioned
= (mAbsolutelyPositionedObject
!= nsnull
);
137 nsHTMLEditor::GetAbsolutePositioningEnabled(PRBool
* aIsEnabled
)
139 *aIsEnabled
= mIsAbsolutelyPositioningEnabled
;
144 nsHTMLEditor::SetAbsolutePositioningEnabled(PRBool aIsEnabled
)
146 mIsAbsolutelyPositioningEnabled
= aIsEnabled
;
151 nsHTMLEditor::RelativeChangeElementZIndex(nsIDOMElement
* aElement
,
155 NS_ENSURE_ARG_POINTER(aElement
);
156 NS_ENSURE_ARG_POINTER(aReturn
);
157 if (!aChange
) // early way out, no change
161 nsresult res
= GetElementZIndex(aElement
, &zIndex
);
162 if (NS_FAILED(res
)) return res
;
164 zIndex
= PR_MAX(zIndex
+ aChange
, 0);
165 SetElementZIndex(aElement
, zIndex
);
172 nsHTMLEditor::SetElementZIndex(nsIDOMElement
* aElement
,
175 NS_ENSURE_ARG_POINTER(aElement
);
177 nsAutoString zIndexStr
;
178 zIndexStr
.AppendInt(aZindex
);
180 mHTMLCSSUtils
->SetCSSProperty(aElement
,
181 nsEditProperty::cssZIndex
,
188 nsHTMLEditor::RelativeChangeZIndex(PRInt32 aChange
)
190 nsAutoEditBatch
beginBatching(this);
191 nsAutoRules
beginRulesSniffing(this,
192 (aChange
< 0) ? kOpDecreaseZIndex
:
196 // brade: can we get rid of this comment?
197 // Find out if the selection is collapsed:
198 nsCOMPtr
<nsISelection
> selection
;
199 nsresult res
= GetSelection(getter_AddRefs(selection
));
200 if (NS_FAILED(res
)) return res
;
201 if (!selection
) return NS_ERROR_NULL_POINTER
;
202 nsTextRulesInfo
ruleInfo((aChange
< 0) ? nsTextEditRules::kDecreaseZIndex
:
203 nsTextEditRules::kIncreaseZIndex
);
204 PRBool cancel
, handled
;
205 res
= mRules
->WillDoAction(selection
, &ruleInfo
, &cancel
, &handled
);
206 if (cancel
|| NS_FAILED(res
))
209 return mRules
->DidDoAction(selection
, &ruleInfo
, res
);
213 nsHTMLEditor::GetElementZIndex(nsIDOMElement
* aElement
,
216 nsAutoString zIndexStr
;
219 nsresult res
= mHTMLCSSUtils
->GetSpecifiedProperty(aElement
,
220 nsEditProperty::cssZIndex
,
222 if (NS_FAILED(res
)) return res
;
223 if (zIndexStr
.EqualsLiteral("auto")) {
224 // we have to look at the positioned ancestors
225 // cf. CSS 2 spec section 9.9.1
226 nsCOMPtr
<nsIDOMNode
> parentNode
;
227 res
= aElement
->GetParentNode(getter_AddRefs(parentNode
));
228 if (NS_FAILED(res
)) return res
;
229 nsCOMPtr
<nsIDOMNode
> node
= parentNode
;
230 nsAutoString positionStr
;
232 zIndexStr
.EqualsLiteral("auto") &&
233 !nsTextEditUtils::IsBody(node
)) {
234 res
= mHTMLCSSUtils
->GetComputedProperty(node
,
235 nsEditProperty::cssPosition
,
237 if (NS_FAILED(res
)) return res
;
238 if (positionStr
.EqualsLiteral("absolute")) {
239 // ah, we found one, what's its z-index ? If its z-index is auto,
240 // we have to continue climbing the document's tree
241 res
= mHTMLCSSUtils
->GetComputedProperty(node
,
242 nsEditProperty::cssZIndex
,
244 if (NS_FAILED(res
)) return res
;
246 res
= node
->GetParentNode(getter_AddRefs(parentNode
));
247 if (NS_FAILED(res
)) return res
;
252 if (!zIndexStr
.EqualsLiteral("auto")) {
254 *aZindex
= zIndexStr
.ToInteger(&errorCode
);
261 nsHTMLEditor::CreateGrabber(nsIDOMNode
* aParentNode
, nsIDOMElement
** aReturn
)
263 // let's create a grabber through the element factory
264 nsresult res
= CreateAnonymousElement(NS_LITERAL_STRING("span"),
266 NS_LITERAL_STRING("mozGrabber"),
271 return NS_ERROR_FAILURE
;
273 // add the mouse listener so we can detect a click on a resizer
274 nsCOMPtr
<nsIDOMEventTarget
> evtTarget(do_QueryInterface(*aReturn
));
275 evtTarget
->AddEventListener(NS_LITERAL_STRING("mousedown"), mMouseListenerP
, PR_FALSE
);
281 nsHTMLEditor::RefreshGrabber()
283 NS_ENSURE_TRUE(mAbsolutelyPositionedObject
, NS_ERROR_NULL_POINTER
);
285 nsresult res
= GetPositionAndDimensions(mAbsolutelyPositionedObject
,
288 mPositionedObjectWidth
,
289 mPositionedObjectHeight
,
290 mPositionedObjectBorderLeft
,
291 mPositionedObjectBorderTop
,
292 mPositionedObjectMarginLeft
,
293 mPositionedObjectMarginTop
);
295 if (NS_FAILED(res
)) return res
;
297 SetAnonymousElementPosition(mPositionedObjectX
+12,
298 mPositionedObjectY
-14,
304 nsHTMLEditor::HideGrabber()
307 mAbsolutelyPositionedObject
->RemoveAttribute(NS_LITERAL_STRING("_moz_abspos"));
308 if (NS_FAILED(res
)) return res
;
310 mAbsolutelyPositionedObject
= nsnull
;
311 NS_ENSURE_TRUE(mGrabber
, NS_ERROR_NULL_POINTER
);
313 // get the presshell's document observer interface.
314 nsCOMPtr
<nsIPresShell
> ps
= do_QueryReferent(mPresShellWeak
);
315 if (!ps
) return NS_ERROR_NOT_INITIALIZED
;
317 nsCOMPtr
<nsIDOMNode
> parentNode
;
318 res
= mGrabber
->GetParentNode(getter_AddRefs(parentNode
));
319 NS_ENSURE_SUCCESS(res
, res
);
321 nsCOMPtr
<nsIContent
> parentContent
= do_QueryInterface(parentNode
);
322 if (!parentContent
) return NS_ERROR_NULL_POINTER
;
324 DeleteRefToAnonymousNode(mGrabber
, parentContent
, ps
);
326 DeleteRefToAnonymousNode(mPositioningShadow
, parentContent
, ps
);
327 mPositioningShadow
= nsnull
;
333 nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement
* aElement
)
335 NS_ENSURE_ARG_POINTER(aElement
);
338 NS_ERROR("call HideGrabber first");
339 return NS_ERROR_UNEXPECTED
;
342 nsAutoString classValue
;
343 nsresult res
= CheckPositionedElementBGandFG(aElement
, classValue
);
344 if (NS_FAILED(res
)) return res
;
346 res
= aElement
->SetAttribute(NS_LITERAL_STRING("_moz_abspos"),
348 if (NS_FAILED(res
)) return res
;
350 // first, let's keep track of that element...
351 mAbsolutelyPositionedObject
= aElement
;
353 nsCOMPtr
<nsIDOMNode
> parentNode
;
354 res
= aElement
->GetParentNode(getter_AddRefs(parentNode
));
355 NS_ENSURE_SUCCESS(res
, res
);
357 res
= CreateGrabber(parentNode
, getter_AddRefs(mGrabber
));
358 NS_ENSURE_SUCCESS(res
, res
);
360 // and set its position
361 return RefreshGrabber();
365 nsHTMLEditor::StartMoving(nsIDOMElement
*aHandle
)
367 nsCOMPtr
<nsIDOMNode
> parentNode
;
368 nsresult res
= mGrabber
->GetParentNode(getter_AddRefs(parentNode
));
369 NS_ENSURE_SUCCESS(res
, res
);
371 // now, let's create the resizing shadow
372 res
= CreateShadow(getter_AddRefs(mPositioningShadow
),
373 parentNode
, mAbsolutelyPositionedObject
);
374 NS_ENSURE_SUCCESS(res
,res
);
375 res
= SetShadowPosition(mPositioningShadow
, mAbsolutelyPositionedObject
,
376 mPositionedObjectX
, mPositionedObjectY
);
377 NS_ENSURE_SUCCESS(res
,res
);
379 // make the shadow appear
380 mPositioningShadow
->RemoveAttribute(NS_LITERAL_STRING("class"));
383 mHTMLCSSUtils
->SetCSSPropertyPixels(mPositioningShadow
,
384 NS_LITERAL_STRING("width"),
385 mPositionedObjectWidth
);
386 mHTMLCSSUtils
->SetCSSPropertyPixels(mPositioningShadow
,
387 NS_LITERAL_STRING("height"),
388 mPositionedObjectHeight
);
395 nsHTMLEditor::SnapToGrid(PRInt32
& newX
, PRInt32
& newY
)
397 if (mSnapToGridEnabled
&& mGridSize
) {
398 newX
= (PRInt32
) floor( ((float)newX
/ (float)mGridSize
) + 0.5f
) * mGridSize
;
399 newY
= (PRInt32
) floor( ((float)newY
/ (float)mGridSize
) + 0.5f
) * mGridSize
;
404 nsHTMLEditor::GrabberClicked()
406 // add a mouse move listener to the editor
407 nsresult res
= NS_OK
;
408 if (!mMouseMotionListenerP
) {
409 mMouseMotionListenerP
= new ResizerMouseMotionListener(this);
410 if (!mMouseMotionListenerP
) {return NS_ERROR_NULL_POINTER
;}
412 nsCOMPtr
<nsPIDOMEventTarget
> piTarget
= GetPIDOMEventTarget();
413 NS_ENSURE_TRUE(piTarget
, NS_ERROR_FAILURE
);
415 res
= piTarget
->AddEventListenerByIID(mMouseMotionListenerP
,
416 NS_GET_IID(nsIDOMMouseMotionListener
));
417 NS_ASSERTION(NS_SUCCEEDED(res
),
418 "failed to register mouse motion listener");
420 mGrabberClicked
= PR_TRUE
;
425 nsHTMLEditor::EndMoving()
427 if (mPositioningShadow
) {
428 nsCOMPtr
<nsIPresShell
> ps
= do_QueryReferent(mPresShellWeak
);
429 if (!ps
) return NS_ERROR_NOT_INITIALIZED
;
431 nsCOMPtr
<nsIDOMNode
> parentNode
;
432 nsresult res
= mGrabber
->GetParentNode(getter_AddRefs(parentNode
));
433 NS_ENSURE_SUCCESS(res
, res
);
435 nsCOMPtr
<nsIContent
> parentContent( do_QueryInterface(parentNode
) );
436 if (!parentContent
) return NS_ERROR_FAILURE
;
438 DeleteRefToAnonymousNode(mPositioningShadow
, parentContent
, ps
);
440 mPositioningShadow
= nsnull
;
442 nsCOMPtr
<nsPIDOMEventTarget
> piTarget
= GetPIDOMEventTarget();
444 if (piTarget
&& mMouseMotionListenerP
) {
448 piTarget
->RemoveEventListenerByIID(mMouseMotionListenerP
,
449 NS_GET_IID(nsIDOMMouseMotionListener
));
450 NS_ASSERTION(NS_SUCCEEDED(res
), "failed to remove mouse motion listener");
452 mMouseMotionListenerP
= nsnull
;
454 mGrabberClicked
= PR_FALSE
;
455 mIsMoving
= PR_FALSE
;
456 nsCOMPtr
<nsISelection
> selection
;
457 GetSelection(getter_AddRefs(selection
));
459 return NS_ERROR_NOT_INITIALIZED
;
461 return CheckSelectionStateForAnonymousButtons(selection
);
464 nsHTMLEditor::SetFinalPosition(PRInt32 aX
, PRInt32 aY
)
466 nsresult res
= EndMoving();
467 if (NS_FAILED(res
)) return res
;
469 // we have now to set the new width and height of the resized object
470 // we don't set the x and y position because we don't control that in
471 // a normal HTML layout
472 PRInt32 newX
= mPositionedObjectX
+ aX
- mOriginalX
- (mPositionedObjectBorderLeft
+mPositionedObjectMarginLeft
);
473 PRInt32 newY
= mPositionedObjectY
+ aY
- mOriginalY
- (mPositionedObjectBorderTop
+mPositionedObjectMarginTop
);
475 SnapToGrid(newX
, newY
);
481 // we want one transaction only from a user's point of view
482 nsAutoEditBatch
batchIt(this);
484 mHTMLCSSUtils
->SetCSSPropertyPixels(mAbsolutelyPositionedObject
,
485 nsEditProperty::cssTop
,
488 mHTMLCSSUtils
->SetCSSPropertyPixels(mAbsolutelyPositionedObject
,
489 nsEditProperty::cssLeft
,
492 // keep track of that size
493 mPositionedObjectX
= newX
;
494 mPositionedObjectY
= newY
;
496 return RefreshResizers();
500 nsHTMLEditor::AddPositioningOffet(PRInt32
& aX
, PRInt32
& aY
)
502 // Get the positioning offset
504 nsCOMPtr
<nsIPrefBranch
> prefBranch
=
505 do_GetService(NS_PREFSERVICE_CONTRACTID
, &res
);
506 PRInt32 positioningOffset
= 0;
507 if (NS_SUCCEEDED(res
) && prefBranch
) {
508 res
= prefBranch
->GetIntPref("editor.positioning.offset", &positioningOffset
);
509 if (NS_FAILED(res
)) // paranoia
510 positioningOffset
= 0;
513 aX
+= positioningOffset
;
514 aY
+= positioningOffset
;
518 nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement
* aElement
,
521 NS_ENSURE_ARG_POINTER(aElement
);
523 nsAutoString positionStr
;
524 mHTMLCSSUtils
->GetComputedProperty(aElement
, nsEditProperty::cssPosition
,
526 PRBool isPositioned
= (positionStr
.EqualsLiteral("absolute"));
528 // nothing to do if the element is already in the state we want
529 if (isPositioned
== aEnabled
)
532 nsAutoEditBatch
batchIt(this);
537 GetElementOrigin(aElement
, x
, y
);
539 mHTMLCSSUtils
->SetCSSProperty(aElement
,
540 nsEditProperty::cssPosition
,
541 NS_LITERAL_STRING("absolute"),
544 AddPositioningOffet(x
, y
);
546 SetElementPosition(aElement
, x
, y
);
548 // we may need to create a br if the positioned element is alone in its
550 nsCOMPtr
<nsIDOMNode
> parentNode
;
551 res
= aElement
->GetParentNode(getter_AddRefs(parentNode
));
552 if (NS_FAILED(res
)) return res
;
554 nsCOMPtr
<nsIDOMNodeList
> childNodes
;
555 res
= parentNode
->GetChildNodes(getter_AddRefs(childNodes
));
556 if (NS_FAILED(res
)) return res
;
557 if (!childNodes
) return NS_ERROR_NULL_POINTER
;
559 res
= childNodes
->GetLength(&childCount
);
560 if (NS_FAILED(res
)) return res
;
562 if (childCount
== 1) {
563 nsCOMPtr
<nsIDOMNode
> brNode
;
564 res
= CreateBR(parentNode
, 0, address_of(brNode
));
568 mHTMLCSSUtils
->RemoveCSSProperty(aElement
,
569 nsEditProperty::cssPosition
,
570 EmptyString(), PR_FALSE
);
571 mHTMLCSSUtils
->RemoveCSSProperty(aElement
,
572 nsEditProperty::cssTop
,
573 EmptyString(), PR_FALSE
);
574 mHTMLCSSUtils
->RemoveCSSProperty(aElement
,
575 nsEditProperty::cssLeft
,
576 EmptyString(), PR_FALSE
);
577 mHTMLCSSUtils
->RemoveCSSProperty(aElement
,
578 nsEditProperty::cssZIndex
,
579 EmptyString(), PR_FALSE
);
581 if (!nsHTMLEditUtils::IsImage(aElement
)) {
582 mHTMLCSSUtils
->RemoveCSSProperty(aElement
,
583 nsEditProperty::cssWidth
,
584 EmptyString(), PR_FALSE
);
585 mHTMLCSSUtils
->RemoveCSSProperty(aElement
,
586 nsEditProperty::cssHeight
,
587 EmptyString(), PR_FALSE
);
590 PRBool hasStyleOrIdOrClass
;
591 res
= HasStyleOrIdOrClass(aElement
, &hasStyleOrIdOrClass
);
592 if (NS_FAILED(res
)) return res
;
593 if (!hasStyleOrIdOrClass
&& nsHTMLEditUtils::IsDiv(aElement
)) {
594 nsCOMPtr
<nsIHTMLEditRules
> htmlRules
= do_QueryInterface(mRules
);
595 if (!htmlRules
) return NS_ERROR_FAILURE
;
596 res
= htmlRules
->MakeSureElemStartsOrEndsOnCR(aElement
);
597 if (NS_FAILED(res
)) return res
;
598 res
= RemoveContainer(aElement
);
605 nsHTMLEditor::SetSnapToGridEnabled(PRBool aEnabled
)
607 mSnapToGridEnabled
= aEnabled
;
612 nsHTMLEditor::GetSnapToGridEnabled(PRBool
* aIsEnabled
)
614 *aIsEnabled
= mSnapToGridEnabled
;
619 nsHTMLEditor::SetGridSize(PRUint32 aSize
)
626 nsHTMLEditor::GetGridSize(PRUint32
* aSize
)
634 nsHTMLEditor::SetElementPosition(nsIDOMElement
*aElement
, PRInt32 aX
, PRInt32 aY
)
636 nsAutoEditBatch
batchIt(this);
638 mHTMLCSSUtils
->SetCSSPropertyPixels(aElement
,
639 nsEditProperty::cssLeft
,
642 mHTMLCSSUtils
->SetCSSPropertyPixels(aElement
,
643 nsEditProperty::cssTop
,
651 nsHTMLEditor::GetPositionedElement(nsIDOMElement
** aReturn
)
653 *aReturn
= mAbsolutelyPositionedObject
;
654 NS_IF_ADDREF(*aReturn
);
659 nsHTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement
* aElement
,
662 // we are going to outline the positioned element and bring it to the
663 // front to overlap any other element intersecting with it. But
664 // first, let's see what's the background and foreground colors of the
665 // positioned element.
666 // if background-image computed value is 'none,
667 // If the background color is 'auto' and R G B values of the foreground are
668 // each above #d0, use a black background
669 // If the background color is 'auto' and at least one of R G B values of
670 // the foreground is below #d0, use a white background
671 // Otherwise don't change background/foreground
675 nsAutoString bgImageStr
;
677 mHTMLCSSUtils
->GetComputedProperty(aElement
,
678 nsEditProperty::cssBackgroundImage
,
680 if (NS_FAILED(res
)) return res
;
681 if (bgImageStr
.EqualsLiteral("none")) {
682 nsAutoString bgColorStr
;
684 mHTMLCSSUtils
->GetComputedProperty(aElement
,
685 nsEditProperty::cssBackgroundColor
,
687 if (NS_FAILED(res
)) return res
;
688 if (bgColorStr
.EqualsLiteral("transparent")) {
690 nsCOMPtr
<nsIDOMViewCSS
> viewCSS
;
691 res
= mHTMLCSSUtils
->GetDefaultViewCSS(aElement
, getter_AddRefs(viewCSS
));
692 if (NS_FAILED(res
)) return res
;
693 nsCOMPtr
<nsIDOMCSSStyleDeclaration
> cssDecl
;
694 res
= viewCSS
->GetComputedStyle(aElement
, EmptyString(), getter_AddRefs(cssDecl
));
695 if (NS_FAILED(res
)) return res
;
696 // from these declarations, get the one we want and that one only
697 nsCOMPtr
<nsIDOMCSSValue
> colorCssValue
;
698 res
= cssDecl
->GetPropertyCSSValue(NS_LITERAL_STRING("color"), getter_AddRefs(colorCssValue
));
699 if (NS_FAILED(res
)) return res
;
702 res
= colorCssValue
->GetCssValueType(&type
);
703 if (NS_FAILED(res
)) return res
;
704 if (nsIDOMCSSValue::CSS_PRIMITIVE_VALUE
== type
) {
705 nsCOMPtr
<nsIDOMCSSPrimitiveValue
> val
= do_QueryInterface(colorCssValue
);
706 res
= val
->GetPrimitiveType(&type
);
707 if (NS_FAILED(res
)) return res
;
708 if (nsIDOMCSSPrimitiveValue::CSS_RGBCOLOR
== type
) {
709 nsCOMPtr
<nsIDOMRGBColor
> rgbColor
;
710 res
= val
->GetRGBColorValue(getter_AddRefs(rgbColor
));
711 if (NS_FAILED(res
)) return res
;
712 nsCOMPtr
<nsIDOMCSSPrimitiveValue
> red
, green
, blue
;
714 res
= rgbColor
->GetRed(getter_AddRefs(red
));
715 if (NS_FAILED(res
)) return res
;
716 res
= rgbColor
->GetGreen(getter_AddRefs(green
));
717 if (NS_FAILED(res
)) return res
;
718 res
= rgbColor
->GetBlue(getter_AddRefs(blue
));
719 if (NS_FAILED(res
)) return res
;
720 res
= red
->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER
, &r
);
721 if (NS_FAILED(res
)) return res
;
722 res
= green
->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER
, &g
);
723 if (NS_FAILED(res
)) return res
;
724 res
= blue
->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER
, &b
);
725 if (NS_FAILED(res
)) return res
;
726 if (r
>= BLACK_BG_RGB_TRIGGER
&&
727 g
>= BLACK_BG_RGB_TRIGGER
&&
728 b
>= BLACK_BG_RGB_TRIGGER
)
729 aReturn
.AssignLiteral("black");
731 aReturn
.AssignLiteral("white");