Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: sky/engine/core/editing/EditingStyle.cpp

Issue 780443002: Remove dead code from EditingStyle. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: try again Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/engine/core/editing/EditingStyle.h ('k') | sky/engine/core/editing/Editor.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007, 2008, 2009 Apple Computer, Inc. 2 * Copyright (C) 2007, 2008, 2009 Apple Computer, Inc.
3 * Copyright (C) 2010, 2011 Google Inc. All rights reserved. 3 * Copyright (C) 2010, 2011 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 return allEditingProperties().contains(static_cast<CSSPropertyID>(id)); 135 return allEditingProperties().contains(static_cast<CSSPropertyID>(id));
136 } 136 }
137 137
138 static PassRefPtr<MutableStylePropertySet> editingStyleFromComputedStyle(PassRef Ptr<CSSComputedStyleDeclaration> style, EditingPropertiesType type = OnlyInherit ableEditingProperties) 138 static PassRefPtr<MutableStylePropertySet> editingStyleFromComputedStyle(PassRef Ptr<CSSComputedStyleDeclaration> style, EditingPropertiesType type = OnlyInherit ableEditingProperties)
139 { 139 {
140 if (!style) 140 if (!style)
141 return MutableStylePropertySet::create(); 141 return MutableStylePropertySet::create();
142 return copyEditingProperties(style.get(), type); 142 return copyEditingProperties(style.get(), type);
143 } 143 }
144 144
145 static PassRefPtr<MutableStylePropertySet> getPropertiesNotIn(StylePropertySet* styleWithRedundantProperties, CSSStyleDeclaration* baseStyle);
146 enum LegacyFontSizeMode { AlwaysUseLegacyFontSize, UseLegacyFontSizeOnlyIfPixelV aluesMatch }; 145 enum LegacyFontSizeMode { AlwaysUseLegacyFontSize, UseLegacyFontSizeOnlyIfPixelV aluesMatch };
147 static int legacyFontSizeFromCSSValue(Document*, CSSPrimitiveValue*, FixedPitchF ontType, LegacyFontSizeMode); 146
148 static bool isTransparentColorValue(CSSValue*); 147 static bool isTransparentColorValue(CSSValue*);
149 static bool hasTransparentBackgroundColor(CSSStyleDeclaration*); 148 static bool hasTransparentBackgroundColor(CSSStyleDeclaration*);
150 static bool hasTransparentBackgroundColor(StylePropertySet*); 149
151 static PassRefPtr<CSSValue> backgroundColorInEffect(Node*); 150 static PassRefPtr<CSSValue> backgroundColorInEffect(Node*);
152 151
153 class HTMLElementEquivalent { 152 class HTMLElementEquivalent {
154 WTF_MAKE_FAST_ALLOCATED; 153 WTF_MAKE_FAST_ALLOCATED;
155 DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(HTMLElementEquivalent); 154 DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(HTMLElementEquivalent);
156 public: 155 public:
157 static PassOwnPtr<HTMLElementEquivalent> create(CSSPropertyID propertyID, CS SValueID primitiveValue, const HTMLQualifiedName& tagName) 156 static PassOwnPtr<HTMLElementEquivalent> create(CSSPropertyID propertyID, CS SValueID primitiveValue, const HTMLQualifiedName& tagName)
158 { 157 {
159 return adoptPtr(new HTMLElementEquivalent(propertyID, primitiveValue, ta gName)); 158 return adoptPtr(new HTMLElementEquivalent(propertyID, primitiveValue, ta gName));
160 } 159 }
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 , m_fixedPitchFontType(NonFixedPitchFont) 337 , m_fixedPitchFontType(NonFixedPitchFont)
339 , m_fontSizeDelta(NoFontDelta) 338 , m_fontSizeDelta(NoFontDelta)
340 { 339 {
341 setProperty(propertyID, value); 340 setProperty(propertyID, value);
342 } 341 }
343 342
344 EditingStyle::~EditingStyle() 343 EditingStyle::~EditingStyle()
345 { 344 {
346 } 345 }
347 346
348 static RGBA32 cssValueToRGBA(CSSValue* colorValue)
349 {
350 if (!colorValue || !colorValue->isPrimitiveValue())
351 return Color::transparent;
352
353 CSSPrimitiveValue* primitiveColor = toCSSPrimitiveValue(colorValue);
354 if (primitiveColor->isRGBColor())
355 return primitiveColor->getRGBA32Value();
356
357 RGBA32 rgba = 0;
358 BisonCSSParser::parseColor(rgba, colorValue->cssText());
359 return rgba;
360 }
361
362 static inline RGBA32 getRGBAFontColor(CSSStyleDeclaration* style)
363 {
364 return cssValueToRGBA(style->getPropertyCSSValueInternal(CSSPropertyColor).g et());
365 }
366
367 static inline RGBA32 getRGBAFontColor(StylePropertySet* style)
368 {
369 return cssValueToRGBA(style->getPropertyCSSValue(CSSPropertyColor).get());
370 }
371
372 static inline RGBA32 getRGBABackgroundColor(CSSStyleDeclaration* style)
373 {
374 return cssValueToRGBA(style->getPropertyCSSValueInternal(CSSPropertyBackgrou ndColor).get());
375 }
376
377 static inline RGBA32 getRGBABackgroundColor(StylePropertySet* style)
378 {
379 return cssValueToRGBA(style->getPropertyCSSValue(CSSPropertyBackgroundColor) .get());
380 }
381
382 static int textAlignResolvingStartAndEnd(int textAlign, int direction)
383 {
384 switch (textAlign) {
385 case CSSValueCenter:
386 return CSSValueCenter;
387 case CSSValueJustify:
388 return CSSValueJustify;
389 case CSSValueLeft:
390 return CSSValueLeft;
391 case CSSValueRight:
392 return CSSValueRight;
393 case CSSValueStart:
394 return direction != CSSValueRtl ? CSSValueLeft : CSSValueRight;
395 case CSSValueEnd:
396 return direction == CSSValueRtl ? CSSValueRight : CSSValueLeft;
397 }
398 return CSSValueInvalid;
399 }
400
401 template<typename T>
402 static int textAlignResolvingStartAndEnd(T* style)
403 {
404 return textAlignResolvingStartAndEnd(getIdentifierValue(style, CSSPropertyTe xtAlign), getIdentifierValue(style, CSSPropertyDirection));
405 }
406
407 void EditingStyle::init(Node* node, PropertiesToInclude propertiesToInclude) 347 void EditingStyle::init(Node* node, PropertiesToInclude propertiesToInclude)
408 { 348 {
409 RefPtr<CSSComputedStyleDeclaration> computedStyleAtPosition = CSSComputedSty leDeclaration::create(node); 349 RefPtr<CSSComputedStyleDeclaration> computedStyleAtPosition = CSSComputedSty leDeclaration::create(node);
410 m_mutableStyle = propertiesToInclude == AllProperties && computedStyleAtPosi tion ? computedStyleAtPosition->copyProperties() : editingStyleFromComputedStyle (computedStyleAtPosition); 350 m_mutableStyle = propertiesToInclude == AllProperties && computedStyleAtPosi tion ? computedStyleAtPosition->copyProperties() : editingStyleFromComputedStyle (computedStyleAtPosition);
411 351
412 if (propertiesToInclude == EditingPropertiesInEffect) { 352 if (propertiesToInclude == EditingPropertiesInEffect) {
413 if (RefPtr<CSSValue> value = backgroundColorInEffect(node)) 353 if (RefPtr<CSSValue> value = backgroundColorInEffect(node))
414 m_mutableStyle->setProperty(CSSPropertyBackgroundColor, value->cssTe xt()); 354 m_mutableStyle->setProperty(CSSPropertyBackgroundColor, value->cssTe xt());
415 if (RefPtr<CSSValue> value = computedStyleAtPosition->getPropertyCSSValu e(CSSPropertyWebkitTextDecorationsInEffect)) 355 if (RefPtr<CSSValue> value = computedStyleAtPosition->getPropertyCSSValu e(CSSPropertyWebkitTextDecorationsInEffect))
416 m_mutableStyle->setProperty(CSSPropertyTextDecoration, value->cssTex t()); 356 m_mutableStyle->setProperty(CSSPropertyTextDecoration, value->cssTex t());
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 417
478 m_fontSizeDelta = primitiveValue->getFloatValue(); 418 m_fontSizeDelta = primitiveValue->getFloatValue();
479 m_mutableStyle->removeProperty(CSSPropertyWebkitFontSizeDelta); 419 m_mutableStyle->removeProperty(CSSPropertyWebkitFontSizeDelta);
480 } 420 }
481 421
482 bool EditingStyle::isEmpty() const 422 bool EditingStyle::isEmpty() const
483 { 423 {
484 return (!m_mutableStyle || m_mutableStyle->isEmpty()) && m_fontSizeDelta == NoFontDelta; 424 return (!m_mutableStyle || m_mutableStyle->isEmpty()) && m_fontSizeDelta == NoFontDelta;
485 } 425 }
486 426
487 bool EditingStyle::textDirection(WritingDirection& writingDirection) const
488 {
489 if (!m_mutableStyle)
490 return false;
491
492 RefPtr<CSSValue> unicodeBidi = m_mutableStyle->getPropertyCSSValue(CSSProper tyUnicodeBidi);
493 if (!unicodeBidi || !unicodeBidi->isPrimitiveValue())
494 return false;
495
496 CSSValueID unicodeBidiValue = toCSSPrimitiveValue(unicodeBidi.get())->getVal ueID();
497 if (unicodeBidiValue == CSSValueEmbed) {
498 RefPtr<CSSValue> direction = m_mutableStyle->getPropertyCSSValue(CSSProp ertyDirection);
499 if (!direction || !direction->isPrimitiveValue())
500 return false;
501
502 writingDirection = toCSSPrimitiveValue(direction.get())->getValueID() == CSSValueLtr ? LeftToRightWritingDirection : RightToLeftWritingDirection;
503
504 return true;
505 }
506
507 if (unicodeBidiValue == CSSValueNormal) {
508 writingDirection = NaturalWritingDirection;
509 return true;
510 }
511
512 return false;
513 }
514
515 void EditingStyle::overrideWithStyle(const StylePropertySet* style)
516 {
517 if (!style || style->isEmpty())
518 return;
519 if (!m_mutableStyle)
520 m_mutableStyle = MutableStylePropertySet::create();
521 m_mutableStyle->mergeAndOverrideOnConflict(style);
522 extractFontSizeDelta();
523 }
524
525 void EditingStyle::clear() 427 void EditingStyle::clear()
526 { 428 {
527 m_mutableStyle.clear(); 429 m_mutableStyle.clear();
528 m_fixedPitchFontType = NonFixedPitchFont; 430 m_fixedPitchFontType = NonFixedPitchFont;
529 m_fontSizeDelta = NoFontDelta; 431 m_fontSizeDelta = NoFontDelta;
530 } 432 }
531 433
532 PassRefPtr<EditingStyle> EditingStyle::copy() const 434 PassRefPtr<EditingStyle> EditingStyle::copy() const
533 { 435 {
534 RefPtr<EditingStyle> copy = EditingStyle::create(); 436 RefPtr<EditingStyle> copy = EditingStyle::create();
535 if (m_mutableStyle) 437 if (m_mutableStyle)
536 copy->m_mutableStyle = m_mutableStyle->mutableCopy(); 438 copy->m_mutableStyle = m_mutableStyle->mutableCopy();
537 copy->m_fixedPitchFontType = m_fixedPitchFontType; 439 copy->m_fixedPitchFontType = m_fixedPitchFontType;
538 copy->m_fontSizeDelta = m_fontSizeDelta; 440 copy->m_fontSizeDelta = m_fontSizeDelta;
539 return copy; 441 return copy;
540 } 442 }
541 443
542 PassRefPtr<EditingStyle> EditingStyle::extractAndRemoveBlockProperties()
543 {
544 RefPtr<EditingStyle> blockProperties = EditingStyle::create();
545 if (!m_mutableStyle)
546 return blockProperties;
547
548 blockProperties->m_mutableStyle = m_mutableStyle->copyBlockProperties();
549 m_mutableStyle->removeBlockProperties();
550
551 return blockProperties;
552 }
553
554 PassRefPtr<EditingStyle> EditingStyle::extractAndRemoveTextDirection()
555 {
556 RefPtr<EditingStyle> textDirection = EditingStyle::create();
557 textDirection->m_mutableStyle = MutableStylePropertySet::create();
558 textDirection->m_mutableStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueE mbed, m_mutableStyle->propertyIsImportant(CSSPropertyUnicodeBidi));
559 textDirection->m_mutableStyle->setProperty(CSSPropertyDirection, m_mutableSt yle->getPropertyValue(CSSPropertyDirection),
560 m_mutableStyle->propertyIsImportant(CSSPropertyDirection));
561
562 m_mutableStyle->removeProperty(CSSPropertyUnicodeBidi);
563 m_mutableStyle->removeProperty(CSSPropertyDirection);
564
565 return textDirection;
566 }
567
568 void EditingStyle::removeBlockProperties() 444 void EditingStyle::removeBlockProperties()
569 { 445 {
570 if (!m_mutableStyle) 446 if (!m_mutableStyle)
571 return; 447 return;
572 448
573 m_mutableStyle->removeBlockProperties(); 449 m_mutableStyle->removeBlockProperties();
574 } 450 }
575 451
576 void EditingStyle::removeStyleAddedByElement(Element* element)
577 {
578 if (!element || !element->parentNode())
579 return;
580 RefPtr<MutableStylePropertySet> parentStyle = editingStyleFromComputedStyle( CSSComputedStyleDeclaration::create(element->parentNode()), AllEditingProperties );
581 RefPtr<MutableStylePropertySet> nodeStyle = editingStyleFromComputedStyle(CS SComputedStyleDeclaration::create(element), AllEditingProperties);
582 nodeStyle->removeEquivalentProperties(parentStyle.get());
583 m_mutableStyle->removeEquivalentProperties(nodeStyle.get());
584 }
585
586 void EditingStyle::removeStyleConflictingWithStyleOfElement(Element* element)
587 {
588 if (!element || !element->parentNode() || !m_mutableStyle)
589 return;
590
591 RefPtr<MutableStylePropertySet> parentStyle = editingStyleFromComputedStyle( CSSComputedStyleDeclaration::create(element->parentNode()), AllEditingProperties );
592 RefPtr<MutableStylePropertySet> nodeStyle = editingStyleFromComputedStyle(CS SComputedStyleDeclaration::create(element), AllEditingProperties);
593 nodeStyle->removeEquivalentProperties(parentStyle.get());
594
595 unsigned propertyCount = nodeStyle->propertyCount();
596 for (unsigned i = 0; i < propertyCount; ++i)
597 m_mutableStyle->removeProperty(nodeStyle->propertyAt(i).id());
598 }
599
600 void EditingStyle::collapseTextDecorationProperties()
601 {
602 if (!m_mutableStyle)
603 return;
604
605 RefPtr<CSSValue> textDecorationsInEffect = m_mutableStyle->getPropertyCSSVal ue(CSSPropertyWebkitTextDecorationsInEffect);
606 if (!textDecorationsInEffect)
607 return;
608
609 if (textDecorationsInEffect->isValueList())
610 m_mutableStyle->setProperty(textDecorationPropertyForEditing(), textDeco rationsInEffect->cssText(), m_mutableStyle->propertyIsImportant(textDecorationPr opertyForEditing()));
611 else
612 m_mutableStyle->removeProperty(textDecorationPropertyForEditing());
613 m_mutableStyle->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
614 }
615
616 // CSS properties that create a visual difference only when applied to text.
617 static const CSSPropertyID textOnlyProperties[] = {
618 // FIXME: CSSPropertyTextDecoration needs to be removed when CSS3 Text
619 // Decoration feature is no longer experimental.
620 CSSPropertyTextDecoration,
621 CSSPropertyTextDecorationLine,
622 CSSPropertyWebkitTextDecorationsInEffect,
623 CSSPropertyFontStyle,
624 CSSPropertyFontWeight,
625 CSSPropertyColor,
626 };
627
628 TriState EditingStyle::triStateOfStyle(EditingStyle* style) const
629 {
630 if (!style || !style->m_mutableStyle)
631 return FalseTriState;
632 return triStateOfStyle(style->m_mutableStyle->ensureCSSStyleDeclaration(), D oNotIgnoreTextOnlyProperties);
633 }
634
635 TriState EditingStyle::triStateOfStyle(CSSStyleDeclaration* styleToCompare, Shou ldIgnoreTextOnlyProperties shouldIgnoreTextOnlyProperties) const
636 {
637 RefPtr<MutableStylePropertySet> difference = getPropertiesNotIn(m_mutableSty le.get(), styleToCompare);
638
639 if (shouldIgnoreTextOnlyProperties == IgnoreTextOnlyProperties)
640 difference->removePropertiesInSet(textOnlyProperties, WTF_ARRAY_LENGTH(t extOnlyProperties));
641
642 if (difference->isEmpty())
643 return TrueTriState;
644 if (difference->propertyCount() == m_mutableStyle->propertyCount())
645 return FalseTriState;
646
647 return MixedTriState;
648 }
649
650 TriState EditingStyle::triStateOfStyle(const VisibleSelection& selection) const
651 {
652 if (!selection.isCaretOrRange())
653 return FalseTriState;
654
655 if (selection.isCaret())
656 return triStateOfStyle(EditingStyle::styleAtSelectionStart(selection).ge t());
657
658 TriState state = FalseTriState;
659 bool nodeIsStart = true;
660 for (Node* node = selection.start().deprecatedNode(); node; node = NodeTrave rsal::next(*node)) {
661 if (node->renderer() && node->hasEditableStyle()) {
662 RefPtr<CSSComputedStyleDeclaration> nodeStyle = CSSComputedStyleDecl aration::create(node);
663 if (nodeStyle) {
664 TriState nodeState = triStateOfStyle(nodeStyle.get(), node->isTe xtNode() ? EditingStyle::DoNotIgnoreTextOnlyProperties : EditingStyle::IgnoreTex tOnlyProperties);
665 if (nodeIsStart) {
666 state = nodeState;
667 nodeIsStart = false;
668 } else if (state != nodeState && node->isTextNode()) {
669 state = MixedTriState;
670 break;
671 }
672 }
673 }
674 if (node == selection.end().deprecatedNode())
675 break;
676 }
677
678 return state;
679 }
680
681 bool EditingStyle::conflictsWithInlineStyleOfElement(HTMLElement* element, Editi ngStyle* extractedStyle, Vector<CSSPropertyID>* conflictingProperties) const
682 {
683 ASSERT(element);
684 ASSERT(!conflictingProperties || conflictingProperties->isEmpty());
685
686 const StylePropertySet* inlineStyle = element->inlineStyle();
687 if (!m_mutableStyle || !inlineStyle)
688 return false;
689
690 unsigned propertyCount = m_mutableStyle->propertyCount();
691 for (unsigned i = 0; i < propertyCount; ++i) {
692 CSSPropertyID propertyID = m_mutableStyle->propertyAt(i).id();
693
694 if (propertyID == CSSPropertyWebkitTextDecorationsInEffect && inlineStyl e->getPropertyCSSValue(textDecorationPropertyForEditing())) {
695 if (!conflictingProperties)
696 return true;
697 conflictingProperties->append(CSSPropertyTextDecoration);
698 // Because text-decoration expands to text-decoration-line when CSS3
699 // Text Decoration is enabled, we also state it as conflicting.
700 if (RuntimeEnabledFeatures::css3TextDecorationsEnabled())
701 conflictingProperties->append(CSSPropertyTextDecorationLine);
702 if (extractedStyle)
703 extractedStyle->setProperty(textDecorationPropertyForEditing(), inlineStyle->getPropertyValue(textDecorationPropertyForEditing()), inlineStyle-> propertyIsImportant(textDecorationPropertyForEditing()));
704 continue;
705 }
706
707 if (!inlineStyle->getPropertyCSSValue(propertyID))
708 continue;
709
710 if (propertyID == CSSPropertyUnicodeBidi && inlineStyle->getPropertyCSSV alue(CSSPropertyDirection)) {
711 if (!conflictingProperties)
712 return true;
713 conflictingProperties->append(CSSPropertyDirection);
714 if (extractedStyle)
715 extractedStyle->setProperty(propertyID, inlineStyle->getProperty Value(propertyID), inlineStyle->propertyIsImportant(propertyID));
716 }
717
718 if (!conflictingProperties)
719 return true;
720
721 conflictingProperties->append(propertyID);
722
723 if (extractedStyle)
724 extractedStyle->setProperty(propertyID, inlineStyle->getPropertyValu e(propertyID), inlineStyle->propertyIsImportant(propertyID));
725 }
726
727 return conflictingProperties && !conflictingProperties->isEmpty();
728 }
729
730 static const Vector<OwnPtr<HTMLElementEquivalent> >& htmlElementEquivalents() 452 static const Vector<OwnPtr<HTMLElementEquivalent> >& htmlElementEquivalents()
731 { 453 {
732 DEFINE_STATIC_LOCAL(Vector<OwnPtr<HTMLElementEquivalent> >, HTMLElementEquiv alents, ()); 454 DEFINE_STATIC_LOCAL(Vector<OwnPtr<HTMLElementEquivalent> >, HTMLElementEquiv alents, ());
733 return HTMLElementEquivalents; 455 return HTMLElementEquivalents;
734 } 456 }
735 457
736 bool EditingStyle::conflictsWithImplicitStyleOfElement(HTMLElement* element, Edi tingStyle* extractedStyle, ShouldExtractMatchingStyle shouldExtractMatchingStyle ) const
737 {
738 if (!m_mutableStyle)
739 return false;
740
741 const Vector<OwnPtr<HTMLElementEquivalent> >& HTMLElementEquivalents = htmlE lementEquivalents();
742 for (size_t i = 0; i < HTMLElementEquivalents.size(); ++i) {
743 const HTMLElementEquivalent* equivalent = HTMLElementEquivalents[i].get( );
744 if (equivalent->matches(element) && equivalent->propertyExistsInStyle(m_ mutableStyle.get())
745 && (shouldExtractMatchingStyle == ExtractMatchingStyle || !equivalen t->valueIsPresentInStyle(element, m_mutableStyle.get()))) {
746 if (extractedStyle)
747 equivalent->addToStyle(element, extractedStyle);
748 return true;
749 }
750 }
751 return false;
752 }
753
754 static const Vector<OwnPtr<HTMLAttributeEquivalent> >& htmlAttributeEquivalents( ) 458 static const Vector<OwnPtr<HTMLAttributeEquivalent> >& htmlAttributeEquivalents( )
755 { 459 {
756 DEFINE_STATIC_LOCAL(Vector<OwnPtr<HTMLAttributeEquivalent> >, HTMLAttributeE quivalents, ()); 460 DEFINE_STATIC_LOCAL(Vector<OwnPtr<HTMLAttributeEquivalent> >, HTMLAttributeE quivalents, ());
757 return HTMLAttributeEquivalents; 461 return HTMLAttributeEquivalents;
758 } 462 }
759 463
760 bool EditingStyle::conflictsWithImplicitStyleOfAttributes(HTMLElement* element) const
761 {
762 ASSERT(element);
763 if (!m_mutableStyle)
764 return false;
765
766 const Vector<OwnPtr<HTMLAttributeEquivalent> >& HTMLAttributeEquivalents = h tmlAttributeEquivalents();
767 for (size_t i = 0; i < HTMLAttributeEquivalents.size(); ++i) {
768 if (HTMLAttributeEquivalents[i]->matches(element) && HTMLAttributeEquiva lents[i]->propertyExistsInStyle(m_mutableStyle.get())
769 && !HTMLAttributeEquivalents[i]->valueIsPresentInStyle(element, m_mu tableStyle.get()))
770 return true;
771 }
772
773 return false;
774 }
775
776 bool EditingStyle::extractConflictingImplicitStyleOfAttributes(HTMLElement* elem ent, ShouldPreserveWritingDirection shouldPreserveWritingDirection,
777 EditingStyle* extractedStyle, Vector<QualifiedName>& conflictingAttributes, ShouldExtractMatchingStyle shouldExtractMatchingStyle) const
778 {
779 ASSERT(element);
780 // HTMLAttributeEquivalent::addToStyle doesn't support unicode-bidi and dire ction properties
781 ASSERT(!extractedStyle || shouldPreserveWritingDirection == PreserveWritingD irection);
782 if (!m_mutableStyle)
783 return false;
784
785 const Vector<OwnPtr<HTMLAttributeEquivalent> >& HTMLAttributeEquivalents = h tmlAttributeEquivalents();
786 bool removed = false;
787 for (size_t i = 0; i < HTMLAttributeEquivalents.size(); ++i) {
788 const HTMLAttributeEquivalent* equivalent = HTMLAttributeEquivalents[i]. get();
789
790 // unicode-bidi and direction are pushed down separately so don't push d own with other styles.
791 if (shouldPreserveWritingDirection == PreserveWritingDirection && equiva lent->attributeName() == HTMLNames::dirAttr)
792 continue;
793
794 if (!equivalent->matches(element) || !equivalent->propertyExistsInStyle( m_mutableStyle.get())
795 || (shouldExtractMatchingStyle == DoNotExtractMatchingStyle && equiv alent->valueIsPresentInStyle(element, m_mutableStyle.get())))
796 continue;
797
798 if (extractedStyle)
799 equivalent->addToStyle(element, extractedStyle);
800 conflictingAttributes.append(equivalent->attributeName());
801 removed = true;
802 }
803
804 return removed;
805 }
806
807 bool EditingStyle::styleIsPresentInComputedStyleOfNode(Node* node) const
808 {
809 return !m_mutableStyle || getPropertiesNotIn(m_mutableStyle.get(), CSSComput edStyleDeclaration::create(node).get())->isEmpty();
810 }
811
812 bool EditingStyle::elementIsStyledSpanOrHTMLEquivalent(const HTMLElement* elemen t) 464 bool EditingStyle::elementIsStyledSpanOrHTMLEquivalent(const HTMLElement* elemen t)
813 { 465 {
814 ASSERT(element); 466 ASSERT(element);
815 bool elementIsSpanOrElementEquivalent = false; 467 bool elementIsSpanOrElementEquivalent = false;
816 const Vector<OwnPtr<HTMLElementEquivalent> >& HTMLElementEquivalents = htmlE lementEquivalents(); 468 const Vector<OwnPtr<HTMLElementEquivalent> >& HTMLElementEquivalents = htmlE lementEquivalents();
817 size_t i; 469 size_t i;
818 for (i = 0; i < HTMLElementEquivalents.size(); ++i) { 470 for (i = 0; i < HTMLElementEquivalents.size(); ++i) {
819 if (HTMLElementEquivalents[i]->matches(element)) { 471 if (HTMLElementEquivalents[i]->matches(element)) {
820 elementIsSpanOrElementEquivalent = true; 472 elementIsSpanOrElementEquivalent = true;
821 break; 473 break;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 { 511 {
860 ASSERT(document); 512 ASSERT(document);
861 513
862 RefPtr<EditingStyle> typingStyle = document->frame()->selection().typingStyl e(); 514 RefPtr<EditingStyle> typingStyle = document->frame()->selection().typingStyl e();
863 if (!typingStyle || typingStyle == this) 515 if (!typingStyle || typingStyle == this)
864 return; 516 return;
865 517
866 mergeStyle(typingStyle->style(), OverrideValues); 518 mergeStyle(typingStyle->style(), OverrideValues);
867 } 519 }
868 520
869 void EditingStyle::mergeInlineStyleOfElement(HTMLElement* element, CSSPropertyOv errideMode mode, PropertiesToInclude propertiesToInclude)
870 {
871 ASSERT(element);
872 if (!element->inlineStyle())
873 return;
874
875 switch (propertiesToInclude) {
876 case AllProperties:
877 mergeStyle(element->inlineStyle(), mode);
878 return;
879 case OnlyEditingInheritableProperties:
880 mergeStyle(copyEditingProperties(element->inlineStyle(), OnlyInheritable EditingProperties).get(), mode);
881 return;
882 case EditingPropertiesInEffect:
883 mergeStyle(copyEditingProperties(element->inlineStyle(), AllEditingPrope rties).get(), mode);
884 return;
885 }
886 }
887
888 static inline bool elementMatchesAndPropertyIsNotInInlineStyleDecl(const HTMLEle mentEquivalent* equivalent, const Element* element,
889 EditingStyle::CSSPropertyOverrideMode mode, StylePropertySet* style)
890 {
891 return equivalent->matches(element) && (!element->inlineStyle() || !equivale nt->propertyExistsInStyle(element->inlineStyle()))
892 && (mode == EditingStyle::OverrideValues || !equivalent->propertyExistsI nStyle(style));
893 }
894
895 static PassRefPtr<MutableStylePropertySet> extractEditingProperties(const StyleP ropertySet* style, EditingStyle::PropertiesToInclude propertiesToInclude)
896 {
897 if (!style)
898 return nullptr;
899
900 switch (propertiesToInclude) {
901 case EditingStyle::AllProperties:
902 case EditingStyle::EditingPropertiesInEffect:
903 return copyEditingProperties(style, AllEditingProperties);
904 case EditingStyle::OnlyEditingInheritableProperties:
905 return copyEditingProperties(style, OnlyInheritableEditingProperties);
906 }
907
908 ASSERT_NOT_REACHED();
909 return nullptr;
910 }
911
912 void EditingStyle::mergeInlineAndImplicitStyleOfElement(Element* element, CSSPro pertyOverrideMode mode, PropertiesToInclude propertiesToInclude)
913 {
914 RefPtr<EditingStyle> styleFromRules = EditingStyle::create();
915 styleFromRules->mergeStyleFromRulesForSerialization(element);
916
917 if (element->inlineStyle())
918 styleFromRules->m_mutableStyle->mergeAndOverrideOnConflict(element->inli neStyle());
919
920 styleFromRules->m_mutableStyle = extractEditingProperties(styleFromRules->m_ mutableStyle.get(), propertiesToInclude);
921 mergeStyle(styleFromRules->m_mutableStyle.get(), mode);
922
923 const Vector<OwnPtr<HTMLElementEquivalent> >& elementEquivalents = htmlEleme ntEquivalents();
924 for (size_t i = 0; i < elementEquivalents.size(); ++i) {
925 if (elementMatchesAndPropertyIsNotInInlineStyleDecl(elementEquivalents[i ].get(), element, mode, m_mutableStyle.get()))
926 elementEquivalents[i]->addToStyle(element, this);
927 }
928
929 const Vector<OwnPtr<HTMLAttributeEquivalent> >& attributeEquivalents = htmlA ttributeEquivalents();
930 for (size_t i = 0; i < attributeEquivalents.size(); ++i) {
931 if (attributeEquivalents[i]->attributeName() == HTMLNames::dirAttr)
932 continue; // We don't want to include directionality
933 if (elementMatchesAndPropertyIsNotInInlineStyleDecl(attributeEquivalents [i].get(), element, mode, m_mutableStyle.get()))
934 attributeEquivalents[i]->addToStyle(element, this);
935 }
936 }
937
938 PassRefPtr<EditingStyle> EditingStyle::wrappingStyleForSerialization(ContainerNo de* context, bool shouldAnnotate)
939 {
940 RefPtr<EditingStyle> wrappingStyle = nullptr;
941 if (shouldAnnotate) {
942 wrappingStyle = EditingStyle::create(context, EditingStyle::EditingPrope rtiesInEffect);
943
944 // Styles that Mail blockquotes contribute should only be placed on the Mail blockquote,
945 // to help us differentiate those styles from ones that the user has app lied.
946 // This helps us get the color of content pasted into blockquotes right.
947 wrappingStyle->removeStyleAddedByElement(toHTMLElement(enclosingNodeOfTy pe(firstPositionInOrBeforeNode(context), isMailHTMLBlockquoteElement, CanCrossEd itingBoundary)));
948
949 // Call collapseTextDecorationProperties first or otherwise it'll copy t he value over from in-effect to text-decorations.
950 wrappingStyle->collapseTextDecorationProperties();
951
952 return wrappingStyle.release();
953 }
954
955 wrappingStyle = EditingStyle::create();
956
957 // When not annotating for interchange, we only preserve inline style declar ations.
958 for (ContainerNode* node = context; node && !node->isDocumentNode(); node = node->parentNode()) {
959 if (node->isStyledElement() && !isMailHTMLBlockquoteElement(node)) {
960 wrappingStyle->mergeInlineAndImplicitStyleOfElement(toElement(node), EditingStyle::DoNotOverrideValues,
961 EditingStyle::EditingPropertiesInEffect);
962 }
963 }
964
965 return wrappingStyle.release();
966 }
967
968
969 static void mergeTextDecorationValues(CSSValueList* mergedValue, const CSSValueL ist* valueToMerge) 521 static void mergeTextDecorationValues(CSSValueList* mergedValue, const CSSValueL ist* valueToMerge)
970 { 522 {
971 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(CSSPrimitiveValue, underline, (CSSPrimi tiveValue::createIdentifier(CSSValueUnderline))); 523 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(CSSPrimitiveValue, underline, (CSSPrimi tiveValue::createIdentifier(CSSValueUnderline)));
972 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(CSSPrimitiveValue, lineThrough, (CSSPri mitiveValue::createIdentifier(CSSValueLineThrough))); 524 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(CSSPrimitiveValue, lineThrough, (CSSPri mitiveValue::createIdentifier(CSSValueLineThrough)));
973 if (valueToMerge->hasValue(underline) && !mergedValue->hasValue(underline)) 525 if (valueToMerge->hasValue(underline) && !mergedValue->hasValue(underline))
974 mergedValue->append(underline); 526 mergedValue->append(underline);
975 527
976 if (valueToMerge->hasValue(lineThrough) && !mergedValue->hasValue(lineThroug h)) 528 if (valueToMerge->hasValue(lineThrough) && !mergedValue->hasValue(lineThroug h))
977 mergedValue->append(lineThrough); 529 mergedValue->append(lineThrough);
978 } 530 }
(...skipping 20 matching lines...) Expand all
999 continue; 551 continue;
1000 } 552 }
1001 value = nullptr; // text-decoration: none is equivalent to not havin g the property 553 value = nullptr; // text-decoration: none is equivalent to not havin g the property
1002 } 554 }
1003 555
1004 if (mode == OverrideValues || (mode == DoNotOverrideValues && !value)) 556 if (mode == OverrideValues || (mode == DoNotOverrideValues && !value))
1005 m_mutableStyle->setProperty(property.id(), property.value()->cssText (), property.isImportant()); 557 m_mutableStyle->setProperty(property.id(), property.value()->cssText (), property.isImportant());
1006 } 558 }
1007 } 559 }
1008 560
1009 static PassRefPtr<MutableStylePropertySet> styleFromMatchedRulesForElement(Eleme nt* element, unsigned rulesToInclude)
1010 {
1011 RefPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
1012 RefPtr<StyleRuleList> matchedRules = element->document().ensureStyleResolver ().styleRulesForElement(element, rulesToInclude);
1013 if (matchedRules) {
1014 for (unsigned i = 0; i < matchedRules->m_list.size(); ++i)
1015 style->mergeAndOverrideOnConflict(&matchedRules->m_list[i]->properti es());
1016 }
1017 return style.release();
1018 }
1019
1020 void EditingStyle::mergeStyleFromRules(Element* element)
1021 {
1022 RefPtr<MutableStylePropertySet> styleFromMatchedRules = styleFromMatchedRule sForElement(element,
1023 StyleResolver::AuthorCSSRules | StyleResolver::CrossOriginCSSRules);
1024 // Styles from the inline style declaration, held in the variable "style", t ake precedence
1025 // over those from matched rules.
1026 if (m_mutableStyle)
1027 styleFromMatchedRules->mergeAndOverrideOnConflict(m_mutableStyle.get());
1028
1029 clear();
1030 m_mutableStyle = styleFromMatchedRules;
1031 }
1032
1033 void EditingStyle::mergeStyleFromRulesForSerialization(Element* element)
1034 {
1035 mergeStyleFromRules(element);
1036
1037 // The property value, if it's a percentage, may not reflect the actual comp uted value.
1038 // For example: style="height: 1%; overflow: visible;" in quirksmode
1039 // FIXME: There are others like this, see <rdar://problem/5195123> Slashdot copy/paste fidelity problem
1040 RefPtr<CSSComputedStyleDeclaration> computedStyleForElement = CSSComputedSty leDeclaration::create(element);
1041 RefPtr<MutableStylePropertySet> fromComputedStyle = MutableStylePropertySet: :create();
1042 {
1043 unsigned propertyCount = m_mutableStyle->propertyCount();
1044 for (unsigned i = 0; i < propertyCount; ++i) {
1045 StylePropertySet::PropertyReference property = m_mutableStyle->prope rtyAt(i);
1046 CSSValue* value = property.value();
1047 if (!value->isPrimitiveValue())
1048 continue;
1049 if (toCSSPrimitiveValue(value)->isPercentage()) {
1050 if (RefPtr<CSSValue> computedPropertyValue = computedStyleForEle ment->getPropertyCSSValue(property.id()))
1051 fromComputedStyle->addParsedProperty(CSSProperty(property.id (), computedPropertyValue));
1052 }
1053 }
1054 }
1055 m_mutableStyle->mergeAndOverrideOnConflict(fromComputedStyle.get());
1056 }
1057
1058 static void removePropertiesInStyle(MutableStylePropertySet* styleToRemoveProper tiesFrom, StylePropertySet* style)
1059 {
1060 unsigned propertyCount = style->propertyCount();
1061 Vector<CSSPropertyID> propertiesToRemove(propertyCount);
1062 for (unsigned i = 0; i < propertyCount; ++i)
1063 propertiesToRemove[i] = style->propertyAt(i).id();
1064
1065 styleToRemovePropertiesFrom->removePropertiesInSet(propertiesToRemove.data() , propertiesToRemove.size());
1066 }
1067
1068 void EditingStyle::removeStyleFromRulesAndContext(Element* element, ContainerNod e* context)
1069 {
1070 ASSERT(element);
1071 if (!m_mutableStyle)
1072 return;
1073
1074 // 1. Remove style from matched rules because style remain without repeating it in inline style declaration
1075 RefPtr<MutableStylePropertySet> styleFromMatchedRules = styleFromMatchedRule sForElement(element, StyleResolver::AllButEmptyCSSRules);
1076 if (styleFromMatchedRules && !styleFromMatchedRules->isEmpty())
1077 m_mutableStyle = getPropertiesNotIn(m_mutableStyle.get(), styleFromMatch edRules->ensureCSSStyleDeclaration());
1078
1079 // 2. Remove style present in context and not overriden by matched rules.
1080 RefPtr<EditingStyle> computedStyle = EditingStyle::create(context, EditingPr opertiesInEffect);
1081 if (computedStyle->m_mutableStyle) {
1082 if (!computedStyle->m_mutableStyle->getPropertyCSSValue(CSSPropertyBackg roundColor))
1083 computedStyle->m_mutableStyle->setProperty(CSSPropertyBackgroundColo r, "transparent");
1084
1085 removePropertiesInStyle(computedStyle->m_mutableStyle.get(), styleFromMa tchedRules.get());
1086 m_mutableStyle = getPropertiesNotIn(m_mutableStyle.get(), computedStyle- >m_mutableStyle->ensureCSSStyleDeclaration());
1087 }
1088 }
1089
1090 void EditingStyle::removePropertiesInElementDefaultStyle(Element* element)
1091 {
1092 if (!m_mutableStyle || m_mutableStyle->isEmpty())
1093 return;
1094
1095 RefPtr<StylePropertySet> defaultStyle = styleFromMatchedRulesForElement(elem ent, StyleResolver::UAAndUserCSSRules);
1096
1097 removePropertiesInStyle(m_mutableStyle.get(), defaultStyle.get());
1098 }
1099
1100 void EditingStyle::addAbsolutePositioningFromElement(const Element& element)
1101 {
1102 LayoutRect rect = element.boundingBox();
1103 RenderObject* renderer = element.renderer();
1104
1105 LayoutUnit x = rect.x();
1106 LayoutUnit y = rect.y();
1107 LayoutUnit width = rect.width();
1108 LayoutUnit height = rect.height();
1109 if (renderer && renderer->isBox()) {
1110 RenderBox* renderBox = toRenderBox(renderer);
1111
1112 x -= renderBox->marginLeft();
1113 y -= renderBox->marginTop();
1114
1115 m_mutableStyle->setProperty(CSSPropertyBoxSizing, CSSValueBorderBox);
1116 }
1117
1118 m_mutableStyle->setProperty(CSSPropertyPosition, CSSValueAbsolute);
1119 m_mutableStyle->setProperty(CSSPropertyLeft, cssValuePool().createValue(x, C SSPrimitiveValue::CSS_PX));
1120 m_mutableStyle->setProperty(CSSPropertyTop, cssValuePool().createValue(y, CS SPrimitiveValue::CSS_PX));
1121 m_mutableStyle->setProperty(CSSPropertyWidth, cssValuePool().createValue(wid th, CSSPrimitiveValue::CSS_PX));
1122 m_mutableStyle->setProperty(CSSPropertyHeight, cssValuePool().createValue(he ight, CSSPrimitiveValue::CSS_PX));
1123 }
1124
1125 void EditingStyle::forceInline()
1126 {
1127 if (!m_mutableStyle)
1128 m_mutableStyle = MutableStylePropertySet::create();
1129 const bool propertyIsImportant = true;
1130 m_mutableStyle->setProperty(CSSPropertyDisplay, CSSValueInline, propertyIsIm portant);
1131 }
1132
1133 int EditingStyle::legacyFontSize(Document* document) const
1134 {
1135 RefPtr<CSSValue> cssValue = m_mutableStyle->getPropertyCSSValue(CSSPropertyF ontSize);
1136 if (!cssValue || !cssValue->isPrimitiveValue())
1137 return 0;
1138 return legacyFontSizeFromCSSValue(document, toCSSPrimitiveValue(cssValue.get ()),
1139 m_fixedPitchFontType, AlwaysUseLegacyFontSize);
1140 }
1141
1142 PassRefPtr<EditingStyle> EditingStyle::styleAtSelectionStart(const VisibleSelect ion& selection, bool shouldUseBackgroundColorInEffect)
1143 {
1144 if (selection.isNone())
1145 return nullptr;
1146
1147 Position position = adjustedSelectionStartForStyleComputation(selection);
1148
1149 // If the pos is at the end of a text node, then this node is not fully sele cted.
1150 // Move it to the next deep equivalent position to avoid removing the style from this node.
1151 // e.g. if pos was at Position("hello", 5) in <b>hello<div>world</div></b>, we want Position("world", 0) instead.
1152 // We only do this for range because caret at Position("hello", 5) in <b>hel lo</b>world should give you font-weight: bold.
1153 Node* positionNode = position.containerNode();
1154 if (selection.isRange() && positionNode && positionNode->isTextNode() && pos ition.computeOffsetInContainerNode() == positionNode->maxCharacterOffset())
1155 position = nextVisuallyDistinctCandidate(position);
1156
1157 Element* element = position.element();
1158 if (!element)
1159 return nullptr;
1160
1161 RefPtr<EditingStyle> style = EditingStyle::create(element, EditingStyle::All Properties);
1162 style->mergeTypingStyle(&element->document());
1163
1164 // If background color is transparent, traverse parent nodes until we hit a different value or document root
1165 // Also, if the selection is a range, ignore the background color at the sta rt of selection,
1166 // and find the background color of the common ancestor.
1167 if (shouldUseBackgroundColorInEffect && (selection.isRange() || hasTranspare ntBackgroundColor(style->m_mutableStyle.get()))) {
1168 RefPtr<Range> range(selection.toNormalizedRange());
1169 if (PassRefPtr<CSSValue> value = backgroundColorInEffect(range->commonAn cestorContainer()))
1170 style->setProperty(CSSPropertyBackgroundColor, value->cssText());
1171 }
1172
1173 return style;
1174 }
1175
1176 WritingDirection EditingStyle::textDirectionForSelection(const VisibleSelection& selection, EditingStyle* typingStyle, bool& hasNestedOrMultipleEmbeddings)
1177 {
1178 hasNestedOrMultipleEmbeddings = true;
1179
1180 if (selection.isNone())
1181 return NaturalWritingDirection;
1182
1183 Position position = selection.start().downstream();
1184
1185 Node* node = position.deprecatedNode();
1186 if (!node)
1187 return NaturalWritingDirection;
1188
1189 Position end;
1190 if (selection.isRange()) {
1191 end = selection.end().upstream();
1192
1193 ASSERT(end.document());
1194 Node* pastLast = Range::create(*end.document(), position.parentAnchoredE quivalent(), end.parentAnchoredEquivalent())->pastLastNode();
1195 for (Node* n = node; n && n != pastLast; n = NodeTraversal::next(*n)) {
1196 if (!n->isStyledElement())
1197 continue;
1198
1199 RefPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclarat ion::create(n);
1200 RefPtr<CSSValue> unicodeBidi = style->getPropertyCSSValue(CSSPropert yUnicodeBidi);
1201 if (!unicodeBidi || !unicodeBidi->isPrimitiveValue())
1202 continue;
1203
1204 CSSValueID unicodeBidiValue = toCSSPrimitiveValue(unicodeBidi.get()) ->getValueID();
1205 if (unicodeBidiValue == CSSValueEmbed || unicodeBidiValue == CSSValu eBidiOverride)
1206 return NaturalWritingDirection;
1207 }
1208 }
1209
1210 if (selection.isCaret()) {
1211 WritingDirection direction;
1212 if (typingStyle && typingStyle->textDirection(direction)) {
1213 hasNestedOrMultipleEmbeddings = false;
1214 return direction;
1215 }
1216 node = selection.visibleStart().deepEquivalent().deprecatedNode();
1217 }
1218
1219 // The selection is either a caret with no typing attributes or a range in w hich no embedding is added, so just use the start position
1220 // to decide.
1221 Node* block = enclosingBlock(node);
1222 WritingDirection foundDirection = NaturalWritingDirection;
1223
1224 for (; node != block; node = node->parentNode()) {
1225 if (!node->isStyledElement())
1226 continue;
1227
1228 Element* element = toElement(node);
1229 RefPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclaration: :create(element);
1230 RefPtr<CSSValue> unicodeBidi = style->getPropertyCSSValue(CSSPropertyUni codeBidi);
1231 if (!unicodeBidi || !unicodeBidi->isPrimitiveValue())
1232 continue;
1233
1234 CSSValueID unicodeBidiValue = toCSSPrimitiveValue(unicodeBidi.get())->ge tValueID();
1235 if (unicodeBidiValue == CSSValueNormal)
1236 continue;
1237
1238 if (unicodeBidiValue == CSSValueBidiOverride)
1239 return NaturalWritingDirection;
1240
1241 ASSERT(unicodeBidiValue == CSSValueEmbed);
1242 RefPtr<CSSValue> direction = style->getPropertyCSSValue(CSSPropertyDirec tion);
1243 if (!direction || !direction->isPrimitiveValue())
1244 continue;
1245
1246 int directionValue = toCSSPrimitiveValue(direction.get())->getValueID();
1247 if (directionValue != CSSValueLtr && directionValue != CSSValueRtl)
1248 continue;
1249
1250 if (foundDirection != NaturalWritingDirection)
1251 return NaturalWritingDirection;
1252
1253 // In the range case, make sure that the embedding element persists unti l the end of the range.
1254 if (selection.isRange() && !end.deprecatedNode()->isDescendantOf(element ))
1255 return NaturalWritingDirection;
1256
1257 foundDirection = directionValue == CSSValueLtr ? LeftToRightWritingDirec tion : RightToLeftWritingDirection;
1258 }
1259 hasNestedOrMultipleEmbeddings = false;
1260 return foundDirection;
1261 }
1262
1263 static void reconcileTextDecorationProperties(MutableStylePropertySet* style)
1264 {
1265 RefPtr<CSSValue> textDecorationsInEffect = style->getPropertyCSSValue(CSSPro pertyWebkitTextDecorationsInEffect);
1266 RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(textDecorationP ropertyForEditing());
1267 // We shouldn't have both text-decoration and -webkit-text-decorations-in-ef fect because that wouldn't make sense.
1268 ASSERT(!textDecorationsInEffect || !textDecoration);
1269 if (textDecorationsInEffect) {
1270 style->setProperty(textDecorationPropertyForEditing(), textDecorationsIn Effect->cssText());
1271 style->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
1272 textDecoration = textDecorationsInEffect;
1273 }
1274
1275 // If text-decoration is set to "none", remove the property because we don't want to add redundant "text-decoration: none".
1276 if (textDecoration && !textDecoration->isValueList())
1277 style->removeProperty(textDecorationPropertyForEditing());
1278 }
1279
1280 StyleChange::StyleChange(EditingStyle* style, const Position& position)
1281 : m_applyBold(false)
1282 , m_applyItalic(false)
1283 , m_applyUnderline(false)
1284 , m_applyLineThrough(false)
1285 , m_applySubscript(false)
1286 , m_applySuperscript(false)
1287 {
1288 Document* document = position.document();
1289 if (!style || !style->style() || !document || !document->frame())
1290 return;
1291
1292 RefPtr<CSSComputedStyleDeclaration> computedStyle = position.computedStyle() ;
1293 // FIXME: take care of background-color in effect
1294 RefPtr<MutableStylePropertySet> mutableStyle = getPropertiesNotIn(style->sty le(), computedStyle.get());
1295
1296 reconcileTextDecorationProperties(mutableStyle.get());
1297 if (!document->frame()->editor().shouldStyleWithCSS())
1298 extractTextStyles(document, mutableStyle.get(), computedStyle->fixedPitc hFontType());
1299
1300 // If unicode-bidi is present in mutableStyle and direction is not, then add direction to mutableStyle.
1301 // FIXME: Shouldn't this be done in getPropertiesNotIn?
1302 if (mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi) && !style->sty le()->getPropertyCSSValue(CSSPropertyDirection))
1303 mutableStyle->setProperty(CSSPropertyDirection, style->style()->getPrope rtyValue(CSSPropertyDirection));
1304
1305 // Save the result for later
1306 m_cssStyle = mutableStyle->asText().stripWhiteSpace();
1307 }
1308
1309 static void setTextDecorationProperty(MutableStylePropertySet* style, const CSSV alueList* newTextDecoration, CSSPropertyID propertyID)
1310 {
1311 if (newTextDecoration->length())
1312 style->setProperty(propertyID, newTextDecoration->cssText(), style->prop ertyIsImportant(propertyID));
1313 else {
1314 // text-decoration: none is redundant since it does not remove any text decorations.
1315 style->removeProperty(propertyID);
1316 }
1317 }
1318
1319 void StyleChange::extractTextStyles(Document* document, MutableStylePropertySet* style, FixedPitchFontType fixedPitchFontType)
1320 {
1321 ASSERT(style);
1322
1323 if (getIdentifierValue(style, CSSPropertyFontWeight) == CSSValueBold) {
1324 style->removeProperty(CSSPropertyFontWeight);
1325 m_applyBold = true;
1326 }
1327
1328 int fontStyle = getIdentifierValue(style, CSSPropertyFontStyle);
1329 if (fontStyle == CSSValueItalic || fontStyle == CSSValueOblique) {
1330 style->removeProperty(CSSPropertyFontStyle);
1331 m_applyItalic = true;
1332 }
1333
1334 // Assuming reconcileTextDecorationProperties has been called, there should not be -webkit-text-decorations-in-effect
1335 // Furthermore, text-decoration: none has been trimmed so that text-decorati on property is always a CSSValueList.
1336 RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(textDecorationP ropertyForEditing());
1337 if (textDecoration && textDecoration->isValueList()) {
1338 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(CSSPrimitiveValue, underline, (CSSP rimitiveValue::createIdentifier(CSSValueUnderline)));
1339 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(CSSPrimitiveValue, lineThrough, (CS SPrimitiveValue::createIdentifier(CSSValueLineThrough)));
1340 RefPtr<CSSValueList> newTextDecoration = toCSSValueList(textDecoration.g et())->copy();
1341 if (newTextDecoration->removeAll(underline))
1342 m_applyUnderline = true;
1343 if (newTextDecoration->removeAll(lineThrough))
1344 m_applyLineThrough = true;
1345
1346 // If trimTextDecorations, delete underline and line-through
1347 setTextDecorationProperty(style, newTextDecoration.get(), textDecoration PropertyForEditing());
1348 }
1349
1350 int verticalAlign = getIdentifierValue(style, CSSPropertyVerticalAlign);
1351 switch (verticalAlign) {
1352 case CSSValueSub:
1353 style->removeProperty(CSSPropertyVerticalAlign);
1354 m_applySubscript = true;
1355 break;
1356 case CSSValueSuper:
1357 style->removeProperty(CSSPropertyVerticalAlign);
1358 m_applySuperscript = true;
1359 break;
1360 }
1361
1362 if (style->getPropertyCSSValue(CSSPropertyColor)) {
1363 m_applyFontColor = Color(getRGBAFontColor(style)).serialized();
1364 style->removeProperty(CSSPropertyColor);
1365 }
1366
1367 m_applyFontFace = style->getPropertyValue(CSSPropertyFontFamily);
1368 // Remove single quotes for Outlook 2007 compatibility. See https://bugs.web kit.org/show_bug.cgi?id=79448
1369 m_applyFontFace.replaceWithLiteral('\'', "");
1370 style->removeProperty(CSSPropertyFontFamily);
1371
1372 if (RefPtr<CSSValue> fontSize = style->getPropertyCSSValue(CSSPropertyFontSi ze)) {
1373 if (!fontSize->isPrimitiveValue()) {
1374 style->removeProperty(CSSPropertyFontSize); // Can't make sense of t he number. Put no font size.
1375 } else if (int legacyFontSize = legacyFontSizeFromCSSValue(document, toC SSPrimitiveValue(fontSize.get()), fixedPitchFontType, UseLegacyFontSizeOnlyIfPix elValuesMatch)) {
1376 m_applyFontSize = String::number(legacyFontSize);
1377 style->removeProperty(CSSPropertyFontSize);
1378 }
1379 }
1380 }
1381
1382 static void diffTextDecorations(MutableStylePropertySet* style, CSSPropertyID pr opertID, CSSValue* refTextDecoration)
1383 {
1384 RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(propertID);
1385 if (!textDecoration || !textDecoration->isValueList() || !refTextDecoration || !refTextDecoration->isValueList())
1386 return;
1387
1388 RefPtr<CSSValueList> newTextDecoration = toCSSValueList(textDecoration.get() )->copy();
1389 CSSValueList* valuesInRefTextDecoration = toCSSValueList(refTextDecoration);
1390
1391 for (size_t i = 0; i < valuesInRefTextDecoration->length(); i++)
1392 newTextDecoration->removeAll(valuesInRefTextDecoration->item(i));
1393
1394 setTextDecorationProperty(style, newTextDecoration.get(), propertID);
1395 }
1396
1397 static bool fontWeightIsBold(CSSValue* fontWeight)
1398 {
1399 if (!fontWeight->isPrimitiveValue())
1400 return false;
1401
1402 // Because b tag can only bold text, there are only two states in plain html : bold and not bold.
1403 // Collapse all other values to either one of these two states for editing p urposes.
1404 switch (toCSSPrimitiveValue(fontWeight)->getValueID()) {
1405 case CSSValue100:
1406 case CSSValue200:
1407 case CSSValue300:
1408 case CSSValue400:
1409 case CSSValue500:
1410 case CSSValueNormal:
1411 return false;
1412 case CSSValueBold:
1413 case CSSValue600:
1414 case CSSValue700:
1415 case CSSValue800:
1416 case CSSValue900:
1417 return true;
1418 default:
1419 break;
1420 }
1421
1422 ASSERT_NOT_REACHED(); // For CSSValueBolder and CSSValueLighter
1423 return false;
1424 }
1425
1426 static bool fontWeightNeedsResolving(CSSValue* fontWeight)
1427 {
1428 if (!fontWeight->isPrimitiveValue())
1429 return true;
1430
1431 CSSValueID value = toCSSPrimitiveValue(fontWeight)->getValueID();
1432 return value == CSSValueLighter || value == CSSValueBolder;
1433 }
1434
1435 PassRefPtr<MutableStylePropertySet> getPropertiesNotIn(StylePropertySet* styleWi thRedundantProperties, CSSStyleDeclaration* baseStyle)
1436 {
1437 ASSERT(styleWithRedundantProperties);
1438 ASSERT(baseStyle);
1439 RefPtr<MutableStylePropertySet> result = styleWithRedundantProperties->mutab leCopy();
1440
1441 result->removeEquivalentProperties(baseStyle);
1442
1443 RefPtr<CSSValue> baseTextDecorationsInEffect = baseStyle->getPropertyCSSValu eInternal(CSSPropertyWebkitTextDecorationsInEffect);
1444 diffTextDecorations(result.get(), textDecorationPropertyForEditing(), baseTe xtDecorationsInEffect.get());
1445 diffTextDecorations(result.get(), CSSPropertyWebkitTextDecorationsInEffect, baseTextDecorationsInEffect.get());
1446
1447 if (RefPtr<CSSValue> baseFontWeight = baseStyle->getPropertyCSSValueInternal (CSSPropertyFontWeight)) {
1448 if (RefPtr<CSSValue> fontWeight = result->getPropertyCSSValue(CSSPropert yFontWeight)) {
1449 if (!fontWeightNeedsResolving(fontWeight.get()) && (fontWeightIsBold (fontWeight.get()) == fontWeightIsBold(baseFontWeight.get())))
1450 result->removeProperty(CSSPropertyFontWeight);
1451 }
1452 }
1453
1454 if (baseStyle->getPropertyCSSValueInternal(CSSPropertyColor) && getRGBAFontC olor(result.get()) == getRGBAFontColor(baseStyle))
1455 result->removeProperty(CSSPropertyColor);
1456
1457 if (baseStyle->getPropertyCSSValueInternal(CSSPropertyTextAlign)
1458 && textAlignResolvingStartAndEnd(result.get()) == textAlignResolvingStar tAndEnd(baseStyle))
1459 result->removeProperty(CSSPropertyTextAlign);
1460
1461 if (baseStyle->getPropertyCSSValueInternal(CSSPropertyBackgroundColor) && ge tRGBABackgroundColor(result.get()) == getRGBABackgroundColor(baseStyle))
1462 result->removeProperty(CSSPropertyBackgroundColor);
1463
1464 return result.release();
1465 }
1466
1467 CSSValueID getIdentifierValue(StylePropertySet* style, CSSPropertyID propertyID)
1468 {
1469 if (!style)
1470 return CSSValueInvalid;
1471 RefPtr<CSSValue> value = style->getPropertyCSSValue(propertyID);
1472 if (!value || !value->isPrimitiveValue())
1473 return CSSValueInvalid;
1474 return toCSSPrimitiveValue(value.get())->getValueID();
1475 }
1476
1477 CSSValueID getIdentifierValue(CSSStyleDeclaration* style, CSSPropertyID property ID)
1478 {
1479 if (!style)
1480 return CSSValueInvalid;
1481 RefPtr<CSSValue> value = style->getPropertyCSSValueInternal(propertyID);
1482 if (!value || !value->isPrimitiveValue())
1483 return CSSValueInvalid;
1484 return toCSSPrimitiveValue(value.get())->getValueID();
1485 }
1486
1487 static bool isCSSValueLength(CSSPrimitiveValue* value)
1488 {
1489 return value->isFontIndependentLength();
1490 }
1491
1492 int legacyFontSizeFromCSSValue(Document* document, CSSPrimitiveValue* value, Fix edPitchFontType fixedPitchFontType, LegacyFontSizeMode mode)
1493 {
1494 if (isCSSValueLength(value)) {
1495 int pixelFontSize = value->getIntValue(CSSPrimitiveValue::CSS_PX);
1496 int legacyFontSize = FontSize::legacyFontSize(document, pixelFontSize, f ixedPitchFontType);
1497 // Use legacy font size only if pixel value matches exactly to that of l egacy font size.
1498 CSSValueID cssPrimitiveEquivalent = static_cast<CSSValueID>(legacyFontSi ze - 1 + CSSValueXSmall);
1499 if (mode == AlwaysUseLegacyFontSize || FontSize::fontSizeForKeyword(docu ment, cssPrimitiveEquivalent, fixedPitchFontType) == pixelFontSize)
1500 return legacyFontSize;
1501
1502 return 0;
1503 }
1504
1505 if (CSSValueXSmall <= value->getValueID() && value->getValueID() <= CSSValue WebkitXxxLarge)
1506 return value->getValueID() - CSSValueXSmall + 1;
1507
1508 return 0;
1509 }
1510
1511 bool isTransparentColorValue(CSSValue* cssValue) 561 bool isTransparentColorValue(CSSValue* cssValue)
1512 { 562 {
1513 if (!cssValue) 563 if (!cssValue)
1514 return true; 564 return true;
1515 if (!cssValue->isPrimitiveValue()) 565 if (!cssValue->isPrimitiveValue())
1516 return false; 566 return false;
1517 CSSPrimitiveValue* value = toCSSPrimitiveValue(cssValue); 567 CSSPrimitiveValue* value = toCSSPrimitiveValue(cssValue);
1518 if (value->isRGBColor()) 568 if (value->isRGBColor())
1519 return !alphaChannel(value->getRGBA32Value()); 569 return !alphaChannel(value->getRGBA32Value());
1520 return false; 570 return false;
1521 } 571 }
1522 572
1523 bool hasTransparentBackgroundColor(CSSStyleDeclaration* style) 573 bool hasTransparentBackgroundColor(CSSStyleDeclaration* style)
1524 { 574 {
1525 RefPtr<CSSValue> cssValue = style->getPropertyCSSValueInternal(CSSPropertyBa ckgroundColor); 575 RefPtr<CSSValue> cssValue = style->getPropertyCSSValueInternal(CSSPropertyBa ckgroundColor);
1526 return isTransparentColorValue(cssValue.get()); 576 return isTransparentColorValue(cssValue.get());
1527 } 577 }
1528 578
1529 bool hasTransparentBackgroundColor(StylePropertySet* style)
1530 {
1531 RefPtr<CSSValue> cssValue = style->getPropertyCSSValue(CSSPropertyBackground Color);
1532 return isTransparentColorValue(cssValue.get());
1533 }
1534
1535 PassRefPtr<CSSValue> backgroundColorInEffect(Node* node) 579 PassRefPtr<CSSValue> backgroundColorInEffect(Node* node)
1536 { 580 {
1537 for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) { 581 for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) {
1538 RefPtr<CSSComputedStyleDeclaration> ancestorStyle = CSSComputedStyleDecl aration::create(ancestor); 582 RefPtr<CSSComputedStyleDeclaration> ancestorStyle = CSSComputedStyleDecl aration::create(ancestor);
1539 if (!hasTransparentBackgroundColor(ancestorStyle.get())) 583 if (!hasTransparentBackgroundColor(ancestorStyle.get()))
1540 return ancestorStyle->getPropertyCSSValue(CSSPropertyBackgroundColor ); 584 return ancestorStyle->getPropertyCSSValue(CSSPropertyBackgroundColor );
1541 } 585 }
1542 return nullptr; 586 return nullptr;
1543 } 587 }
1544 588
1545 } 589 }
OLDNEW
« no previous file with comments | « sky/engine/core/editing/EditingStyle.h ('k') | sky/engine/core/editing/Editor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698