Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include <math.h>
7 #include "mozilla/Preferences.h"
8 #include "mozilla/dom/Selection.h"
9 #include "mozilla/dom/Element.h"
10 #include "mozilla/mozalloc.h"
11 #include "nsAString.h"
12 #include "nsAlgorithm.h"
13 #include "nsAutoPtr.h"
14 #include "nsCOMPtr.h"
15 #include "nsComputedDOMStyle.h"
16 #include "nsDebug.h"
17 #include "nsEditProperty.h"
18 #include "nsEditRules.h"
19 #include "nsEditor.h"
20 #include "nsEditorUtils.h"
21 #include "nsError.h"
22 #include "nsGkAtoms.h"
23 #include "nsHTMLCSSUtils.h"
24 #include "nsHTMLEditRules.h"
25 #include "nsHTMLEditUtils.h"
26 #include "nsHTMLEditor.h"
27 #include "nsHTMLObjectResizer.h"
28 #include "nsIContent.h"
29 #include "nsROCSSPrimitiveValue.h"
30 #include "nsIDOMCSSStyleDeclaration.h"
31 #include "nsIDOMElement.h"
32 #include "nsIDOMEventListener.h"
33 #include "nsIDOMEventTarget.h"
34 #include "nsIDOMNode.h"
35 #include "nsDOMCSSRGBColor.h"
36 #include "nsIDOMWindow.h"
37 #include "nsIEditor.h"
38 #include "nsIHTMLEditor.h"
39 #include "nsIHTMLObjectResizer.h"
40 #include "nsINode.h"
41 #include "nsIPresShell.h"
42 #include "nsISelection.h"
43 #include "nsISupportsImpl.h"
44 #include "nsISupportsUtils.h"
45 #include "nsLiteralString.h"
46 #include "nsReadableUtils.h"
47 #include "nsString.h"
48 #include "nsStringFwd.h"
49 #include "nsTextEditRules.h"
50 #include "nsTextEditUtils.h"
51 #include "nscore.h"
52 #include <algorithm>
54 using namespace mozilla;
55 using namespace mozilla::dom;
57 #define BLACK_BG_RGB_TRIGGER 0xd0
59 NS_IMETHODIMP
60 nsHTMLEditor::AbsolutePositionSelection(bool aEnabled)
61 {
62 nsAutoEditBatch beginBatching(this);
63 nsAutoRules beginRulesSniffing(this,
64 aEnabled ? EditAction::setAbsolutePosition :
65 EditAction::removeAbsolutePosition,
66 nsIEditor::eNext);
68 // the line below does not match the code; should it be removed?
69 // Find out if the selection is collapsed:
70 nsRefPtr<Selection> selection = GetSelection();
71 NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
73 nsTextRulesInfo ruleInfo(aEnabled ? EditAction::setAbsolutePosition :
74 EditAction::removeAbsolutePosition);
75 bool cancel, handled;
76 // Protect the edit rules object from dying
77 nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
78 nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
79 if (NS_FAILED(res) || cancel)
80 return res;
82 return mRules->DidDoAction(selection, &ruleInfo, res);
83 }
85 NS_IMETHODIMP
86 nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval)
87 {
88 nsCOMPtr<nsIDOMElement> element;
89 nsresult res = GetSelectionContainer(getter_AddRefs(element));
90 NS_ENSURE_SUCCESS(res, res);
92 nsAutoString positionStr;
93 nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
94 nsCOMPtr<nsIDOMNode> resultNode;
96 while (!resultNode && node && !nsEditor::NodeIsType(node, nsEditProperty::html)) {
97 res = mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition,
98 positionStr);
99 NS_ENSURE_SUCCESS(res, res);
100 if (positionStr.EqualsLiteral("absolute"))
101 resultNode = node;
102 else {
103 nsCOMPtr<nsIDOMNode> parentNode;
104 res = node->GetParentNode(getter_AddRefs(parentNode));
105 NS_ENSURE_SUCCESS(res, res);
106 node.swap(parentNode);
107 }
108 }
110 element = do_QueryInterface(resultNode );
111 *_retval = element;
112 NS_IF_ADDREF(*_retval);
113 return NS_OK;
114 }
116 NS_IMETHODIMP
117 nsHTMLEditor::GetSelectionContainerAbsolutelyPositioned(bool *aIsSelectionContainerAbsolutelyPositioned)
118 {
119 *aIsSelectionContainerAbsolutelyPositioned = (mAbsolutelyPositionedObject != nullptr);
120 return NS_OK;
121 }
123 NS_IMETHODIMP
124 nsHTMLEditor::GetAbsolutePositioningEnabled(bool * aIsEnabled)
125 {
126 *aIsEnabled = mIsAbsolutelyPositioningEnabled;
127 return NS_OK;
128 }
130 NS_IMETHODIMP
131 nsHTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled)
132 {
133 mIsAbsolutelyPositioningEnabled = aIsEnabled;
134 return NS_OK;
135 }
137 NS_IMETHODIMP
138 nsHTMLEditor::RelativeChangeElementZIndex(nsIDOMElement * aElement,
139 int32_t aChange,
140 int32_t * aReturn)
141 {
142 NS_ENSURE_ARG_POINTER(aElement);
143 NS_ENSURE_ARG_POINTER(aReturn);
144 if (!aChange) // early way out, no change
145 return NS_OK;
147 int32_t zIndex;
148 nsresult res = GetElementZIndex(aElement, &zIndex);
149 NS_ENSURE_SUCCESS(res, res);
151 zIndex = std::max(zIndex + aChange, 0);
152 SetElementZIndex(aElement, zIndex);
153 *aReturn = zIndex;
155 return NS_OK;
156 }
158 NS_IMETHODIMP
159 nsHTMLEditor::SetElementZIndex(nsIDOMElement * aElement,
160 int32_t aZindex)
161 {
162 NS_ENSURE_ARG_POINTER(aElement);
164 nsAutoString zIndexStr;
165 zIndexStr.AppendInt(aZindex);
167 mHTMLCSSUtils->SetCSSProperty(aElement,
168 nsEditProperty::cssZIndex,
169 zIndexStr,
170 false);
171 return NS_OK;
172 }
174 NS_IMETHODIMP
175 nsHTMLEditor::RelativeChangeZIndex(int32_t aChange)
176 {
177 nsAutoEditBatch beginBatching(this);
178 nsAutoRules beginRulesSniffing(this,
179 (aChange < 0) ? EditAction::decreaseZIndex :
180 EditAction::increaseZIndex,
181 nsIEditor::eNext);
183 // brade: can we get rid of this comment?
184 // Find out if the selection is collapsed:
185 nsRefPtr<Selection> selection = GetSelection();
186 NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
187 nsTextRulesInfo ruleInfo(aChange < 0 ? EditAction::decreaseZIndex :
188 EditAction::increaseZIndex);
189 bool cancel, handled;
190 // Protect the edit rules object from dying
191 nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
192 nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
193 if (cancel || NS_FAILED(res))
194 return res;
196 return mRules->DidDoAction(selection, &ruleInfo, res);
197 }
199 NS_IMETHODIMP
200 nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement,
201 int32_t * aZindex)
202 {
203 nsAutoString zIndexStr;
204 *aZindex = 0;
206 nsresult res = mHTMLCSSUtils->GetSpecifiedProperty(aElement,
207 nsEditProperty::cssZIndex,
208 zIndexStr);
209 NS_ENSURE_SUCCESS(res, res);
210 if (zIndexStr.EqualsLiteral("auto")) {
211 // we have to look at the positioned ancestors
212 // cf. CSS 2 spec section 9.9.1
213 nsCOMPtr<nsIDOMNode> parentNode;
214 res = aElement->GetParentNode(getter_AddRefs(parentNode));
215 NS_ENSURE_SUCCESS(res, res);
216 nsCOMPtr<nsIDOMNode> node = parentNode;
217 nsAutoString positionStr;
218 while (node &&
219 zIndexStr.EqualsLiteral("auto") &&
220 !nsTextEditUtils::IsBody(node)) {
221 res = mHTMLCSSUtils->GetComputedProperty(node,
222 nsEditProperty::cssPosition,
223 positionStr);
224 NS_ENSURE_SUCCESS(res, res);
225 if (positionStr.EqualsLiteral("absolute")) {
226 // ah, we found one, what's its z-index ? If its z-index is auto,
227 // we have to continue climbing the document's tree
228 res = mHTMLCSSUtils->GetComputedProperty(node,
229 nsEditProperty::cssZIndex,
230 zIndexStr);
231 NS_ENSURE_SUCCESS(res, res);
232 }
233 res = node->GetParentNode(getter_AddRefs(parentNode));
234 NS_ENSURE_SUCCESS(res, res);
235 node = parentNode;
236 }
237 }
239 if (!zIndexStr.EqualsLiteral("auto")) {
240 nsresult errorCode;
241 *aZindex = zIndexStr.ToInteger(&errorCode);
242 }
244 return NS_OK;
245 }
247 nsresult
248 nsHTMLEditor::CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn)
249 {
250 // let's create a grabber through the element factory
251 nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
252 aParentNode,
253 NS_LITERAL_STRING("mozGrabber"),
254 false,
255 aReturn);
257 NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE);
259 // add the mouse listener so we can detect a click on a resizer
260 nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn));
261 evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"),
262 mEventListener, false);
264 return res;
265 }
267 NS_IMETHODIMP
268 nsHTMLEditor::RefreshGrabber()
269 {
270 NS_ENSURE_TRUE(mAbsolutelyPositionedObject, NS_ERROR_NULL_POINTER);
272 nsresult res = GetPositionAndDimensions(mAbsolutelyPositionedObject,
273 mPositionedObjectX,
274 mPositionedObjectY,
275 mPositionedObjectWidth,
276 mPositionedObjectHeight,
277 mPositionedObjectBorderLeft,
278 mPositionedObjectBorderTop,
279 mPositionedObjectMarginLeft,
280 mPositionedObjectMarginTop);
282 NS_ENSURE_SUCCESS(res, res);
284 SetAnonymousElementPosition(mPositionedObjectX+12,
285 mPositionedObjectY-14,
286 mGrabber);
287 return NS_OK;
288 }
290 NS_IMETHODIMP
291 nsHTMLEditor::HideGrabber()
292 {
293 nsresult res =
294 mAbsolutelyPositionedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_abspos"));
295 NS_ENSURE_SUCCESS(res, res);
297 mAbsolutelyPositionedObject = nullptr;
298 NS_ENSURE_TRUE(mGrabber, NS_ERROR_NULL_POINTER);
300 // get the presshell's document observer interface.
301 nsCOMPtr<nsIPresShell> ps = GetPresShell();
302 // We allow the pres shell to be null; when it is, we presume there
303 // are no document observers to notify, but we still want to
304 // UnbindFromTree.
306 nsCOMPtr<nsIDOMNode> parentNode;
307 res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
308 NS_ENSURE_SUCCESS(res, res);
310 nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parentNode);
311 NS_ENSURE_TRUE(parentContent, NS_ERROR_NULL_POINTER);
313 DeleteRefToAnonymousNode(mGrabber, parentContent, ps);
314 mGrabber = nullptr;
315 DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
316 mPositioningShadow = nullptr;
318 return NS_OK;
319 }
321 NS_IMETHODIMP
322 nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement)
323 {
324 NS_ENSURE_ARG_POINTER(aElement);
326 if (mGrabber) {
327 NS_ERROR("call HideGrabber first");
328 return NS_ERROR_UNEXPECTED;
329 }
331 nsAutoString classValue;
332 nsresult res = CheckPositionedElementBGandFG(aElement, classValue);
333 NS_ENSURE_SUCCESS(res, res);
335 res = aElement->SetAttribute(NS_LITERAL_STRING("_moz_abspos"),
336 classValue);
337 NS_ENSURE_SUCCESS(res, res);
339 // first, let's keep track of that element...
340 mAbsolutelyPositionedObject = aElement;
342 nsCOMPtr<nsIDOMNode> parentNode;
343 res = aElement->GetParentNode(getter_AddRefs(parentNode));
344 NS_ENSURE_SUCCESS(res, res);
346 res = CreateGrabber(parentNode, getter_AddRefs(mGrabber));
347 NS_ENSURE_SUCCESS(res, res);
349 // and set its position
350 return RefreshGrabber();
351 }
353 nsresult
354 nsHTMLEditor::StartMoving(nsIDOMElement *aHandle)
355 {
356 nsCOMPtr<nsIDOMNode> parentNode;
357 nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
358 NS_ENSURE_SUCCESS(res, res);
360 // now, let's create the resizing shadow
361 res = CreateShadow(getter_AddRefs(mPositioningShadow),
362 parentNode, mAbsolutelyPositionedObject);
363 NS_ENSURE_SUCCESS(res,res);
364 res = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject,
365 mPositionedObjectX, mPositionedObjectY);
366 NS_ENSURE_SUCCESS(res,res);
368 // make the shadow appear
369 mPositioningShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
371 // position it
372 mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow,
373 NS_LITERAL_STRING("width"),
374 mPositionedObjectWidth);
375 mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow,
376 NS_LITERAL_STRING("height"),
377 mPositionedObjectHeight);
379 mIsMoving = true;
380 return res;
381 }
383 void
384 nsHTMLEditor::SnapToGrid(int32_t & newX, int32_t & newY)
385 {
386 if (mSnapToGridEnabled && mGridSize) {
387 newX = (int32_t) floor( ((float)newX / (float)mGridSize) + 0.5f ) * mGridSize;
388 newY = (int32_t) floor( ((float)newY / (float)mGridSize) + 0.5f ) * mGridSize;
389 }
390 }
392 nsresult
393 nsHTMLEditor::GrabberClicked()
394 {
395 // add a mouse move listener to the editor
396 nsresult res = NS_OK;
397 if (!mMouseMotionListenerP) {
398 mMouseMotionListenerP = new ResizerMouseMotionListener(this);
399 if (!mMouseMotionListenerP) {return NS_ERROR_NULL_POINTER;}
401 nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
402 NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);
404 res = piTarget->AddEventListener(NS_LITERAL_STRING("mousemove"),
405 mMouseMotionListenerP,
406 false, false);
407 NS_ASSERTION(NS_SUCCEEDED(res),
408 "failed to register mouse motion listener");
409 }
410 mGrabberClicked = true;
411 return res;
412 }
414 nsresult
415 nsHTMLEditor::EndMoving()
416 {
417 if (mPositioningShadow) {
418 nsCOMPtr<nsIPresShell> ps = GetPresShell();
419 NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
421 nsCOMPtr<nsIDOMNode> parentNode;
422 nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
423 NS_ENSURE_SUCCESS(res, res);
425 nsCOMPtr<nsIContent> parentContent( do_QueryInterface(parentNode) );
426 NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE);
428 DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
430 mPositioningShadow = nullptr;
431 }
432 nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
434 if (piTarget && mMouseMotionListenerP) {
435 #ifdef DEBUG
436 nsresult res =
437 #endif
438 piTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
439 mMouseMotionListenerP,
440 false);
441 NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener");
442 }
443 mMouseMotionListenerP = nullptr;
445 mGrabberClicked = false;
446 mIsMoving = false;
447 nsCOMPtr<nsISelection> selection;
448 GetSelection(getter_AddRefs(selection));
449 if (!selection) {
450 return NS_ERROR_NOT_INITIALIZED;
451 }
452 return CheckSelectionStateForAnonymousButtons(selection);
453 }
454 nsresult
455 nsHTMLEditor::SetFinalPosition(int32_t aX, int32_t aY)
456 {
457 nsresult res = EndMoving();
458 NS_ENSURE_SUCCESS(res, res);
460 // we have now to set the new width and height of the resized object
461 // we don't set the x and y position because we don't control that in
462 // a normal HTML layout
463 int32_t newX = mPositionedObjectX + aX - mOriginalX - (mPositionedObjectBorderLeft+mPositionedObjectMarginLeft);
464 int32_t newY = mPositionedObjectY + aY - mOriginalY - (mPositionedObjectBorderTop+mPositionedObjectMarginTop);
466 SnapToGrid(newX, newY);
468 nsAutoString x, y;
469 x.AppendInt(newX);
470 y.AppendInt(newY);
472 // we want one transaction only from a user's point of view
473 nsAutoEditBatch batchIt(this);
475 mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
476 nsEditProperty::cssTop,
477 newY,
478 false);
479 mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
480 nsEditProperty::cssLeft,
481 newX,
482 false);
483 // keep track of that size
484 mPositionedObjectX = newX;
485 mPositionedObjectY = newY;
487 return RefreshResizers();
488 }
490 void
491 nsHTMLEditor::AddPositioningOffset(int32_t & aX, int32_t & aY)
492 {
493 // Get the positioning offset
494 int32_t positioningOffset =
495 Preferences::GetInt("editor.positioning.offset", 0);
497 aX += positioningOffset;
498 aY += positioningOffset;
499 }
501 NS_IMETHODIMP
502 nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement,
503 bool aEnabled)
504 {
505 NS_ENSURE_ARG_POINTER(aElement);
507 nsAutoString positionStr;
508 mHTMLCSSUtils->GetComputedProperty(aElement, nsEditProperty::cssPosition,
509 positionStr);
510 bool isPositioned = (positionStr.EqualsLiteral("absolute"));
512 // nothing to do if the element is already in the state we want
513 if (isPositioned == aEnabled)
514 return NS_OK;
516 nsAutoEditBatch batchIt(this);
518 if (aEnabled) {
519 int32_t x, y;
520 GetElementOrigin(aElement, x, y);
522 mHTMLCSSUtils->SetCSSProperty(aElement,
523 nsEditProperty::cssPosition,
524 NS_LITERAL_STRING("absolute"),
525 false);
527 AddPositioningOffset(x, y);
528 SnapToGrid(x, y);
529 SetElementPosition(aElement, x, y);
531 // we may need to create a br if the positioned element is alone in its
532 // container
533 nsCOMPtr<nsINode> element = do_QueryInterface(aElement);
534 NS_ENSURE_STATE(element);
536 nsINode* parentNode = element->GetParentNode();
537 if (parentNode->GetChildCount() == 1) {
538 nsCOMPtr<nsIDOMNode> brNode;
539 nsresult res = CreateBR(parentNode->AsDOMNode(), 0, address_of(brNode));
540 NS_ENSURE_SUCCESS(res, res);
541 }
542 }
543 else {
544 mHTMLCSSUtils->RemoveCSSProperty(aElement,
545 nsEditProperty::cssPosition,
546 EmptyString(), false);
547 mHTMLCSSUtils->RemoveCSSProperty(aElement,
548 nsEditProperty::cssTop,
549 EmptyString(), false);
550 mHTMLCSSUtils->RemoveCSSProperty(aElement,
551 nsEditProperty::cssLeft,
552 EmptyString(), false);
553 mHTMLCSSUtils->RemoveCSSProperty(aElement,
554 nsEditProperty::cssZIndex,
555 EmptyString(), false);
557 if (!nsHTMLEditUtils::IsImage(aElement)) {
558 mHTMLCSSUtils->RemoveCSSProperty(aElement,
559 nsEditProperty::cssWidth,
560 EmptyString(), false);
561 mHTMLCSSUtils->RemoveCSSProperty(aElement,
562 nsEditProperty::cssHeight,
563 EmptyString(), false);
564 }
566 nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
567 if (element && element->IsHTML(nsGkAtoms::div) && !HasStyleOrIdOrClass(element)) {
568 nsRefPtr<nsHTMLEditRules> htmlRules = static_cast<nsHTMLEditRules*>(mRules.get());
569 NS_ENSURE_TRUE(htmlRules, NS_ERROR_FAILURE);
570 nsresult res = htmlRules->MakeSureElemStartsOrEndsOnCR(aElement);
571 NS_ENSURE_SUCCESS(res, res);
572 res = RemoveContainer(aElement);
573 NS_ENSURE_SUCCESS(res, res);
574 }
575 }
576 return NS_OK;
577 }
579 NS_IMETHODIMP
580 nsHTMLEditor::SetSnapToGridEnabled(bool aEnabled)
581 {
582 mSnapToGridEnabled = aEnabled;
583 return NS_OK;
584 }
586 NS_IMETHODIMP
587 nsHTMLEditor::GetSnapToGridEnabled(bool * aIsEnabled)
588 {
589 *aIsEnabled = mSnapToGridEnabled;
590 return NS_OK;
591 }
593 NS_IMETHODIMP
594 nsHTMLEditor::SetGridSize(uint32_t aSize)
595 {
596 mGridSize = aSize;
597 return NS_OK;
598 }
600 NS_IMETHODIMP
601 nsHTMLEditor::GetGridSize(uint32_t * aSize)
602 {
603 *aSize = mGridSize;
604 return NS_OK;
605 }
607 // self-explanatory
608 NS_IMETHODIMP
609 nsHTMLEditor::SetElementPosition(nsIDOMElement *aElement, int32_t aX, int32_t aY)
610 {
611 nsAutoEditBatch batchIt(this);
613 mHTMLCSSUtils->SetCSSPropertyPixels(aElement,
614 nsEditProperty::cssLeft,
615 aX,
616 false);
617 mHTMLCSSUtils->SetCSSPropertyPixels(aElement,
618 nsEditProperty::cssTop,
619 aY,
620 false);
621 return NS_OK;
622 }
624 // self-explanatory
625 NS_IMETHODIMP
626 nsHTMLEditor::GetPositionedElement(nsIDOMElement ** aReturn)
627 {
628 *aReturn = mAbsolutelyPositionedObject;
629 NS_IF_ADDREF(*aReturn);
630 return NS_OK;
631 }
633 nsresult
634 nsHTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement * aElement,
635 nsAString & aReturn)
636 {
637 // we are going to outline the positioned element and bring it to the
638 // front to overlap any other element intersecting with it. But
639 // first, let's see what's the background and foreground colors of the
640 // positioned element.
641 // if background-image computed value is 'none,
642 // If the background color is 'auto' and R G B values of the foreground are
643 // each above #d0, use a black background
644 // If the background color is 'auto' and at least one of R G B values of
645 // the foreground is below #d0, use a white background
646 // Otherwise don't change background/foreground
648 aReturn.Truncate();
650 nsAutoString bgImageStr;
651 nsresult res =
652 mHTMLCSSUtils->GetComputedProperty(aElement,
653 nsEditProperty::cssBackgroundImage,
654 bgImageStr);
655 NS_ENSURE_SUCCESS(res, res);
656 if (bgImageStr.EqualsLiteral("none")) {
657 nsAutoString bgColorStr;
658 res =
659 mHTMLCSSUtils->GetComputedProperty(aElement,
660 nsEditProperty::cssBackgroundColor,
661 bgColorStr);
662 NS_ENSURE_SUCCESS(res, res);
663 if (bgColorStr.EqualsLiteral("transparent")) {
664 nsRefPtr<nsComputedDOMStyle> cssDecl =
665 mHTMLCSSUtils->GetComputedStyle(aElement);
666 NS_ENSURE_STATE(cssDecl);
668 // from these declarations, get the one we want and that one only
669 ErrorResult error;
670 nsRefPtr<dom::CSSValue> cssVal = cssDecl->GetPropertyCSSValue(NS_LITERAL_STRING("color"), error);
671 NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode());
673 nsROCSSPrimitiveValue* val = cssVal->AsPrimitiveValue();
674 NS_ENSURE_TRUE(val, NS_ERROR_FAILURE);
676 if (nsIDOMCSSPrimitiveValue::CSS_RGBCOLOR == val->PrimitiveType()) {
677 nsDOMCSSRGBColor* rgbVal = val->GetRGBColorValue(error);
678 NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode());
679 float r = rgbVal->Red()->
680 GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error);
681 NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode());
682 float g = rgbVal->Green()->
683 GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error);
684 NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode());
685 float b = rgbVal->Blue()->
686 GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error);
687 NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode());
688 if (r >= BLACK_BG_RGB_TRIGGER &&
689 g >= BLACK_BG_RGB_TRIGGER &&
690 b >= BLACK_BG_RGB_TRIGGER)
691 aReturn.AssignLiteral("black");
692 else
693 aReturn.AssignLiteral("white");
694 return NS_OK;
695 }
696 }
697 }
699 return NS_OK;
700 }