| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |