| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) |
| 3 * 1999 Waldo Bastian (bastian@kde.org) | 3 * 1999 Waldo Bastian (bastian@kde.org) |
| 4 * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch) | 4 * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch) |
| 5 * 2001-2003 Dirk Mueller (mueller@kde.org) | 5 * 2001-2003 Dirk Mueller (mueller@kde.org) |
| 6 * Copyright (C) 2002, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv
ed. | 6 * Copyright (C) 2002, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv
ed. |
| 7 * Copyright (C) 2008 David Smith (catfish.man@gmail.com) | 7 * Copyright (C) 2008 David Smith (catfish.man@gmail.com) |
| 8 * Copyright (C) 2010 Google Inc. All rights reserved. | 8 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 9 * | 9 * |
| 10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 | 93 |
| 94 inline unsigned CSSSelector::specificityForOneSelector() const | 94 inline unsigned CSSSelector::specificityForOneSelector() const |
| 95 { | 95 { |
| 96 // FIXME: Pseudo-elements and pseudo-classes do not have the same specificit
y. This function | 96 // FIXME: Pseudo-elements and pseudo-classes do not have the same specificit
y. This function |
| 97 // isn't quite correct. | 97 // isn't quite correct. |
| 98 // http://www.w3.org/TR/selectors/#specificity | 98 // http://www.w3.org/TR/selectors/#specificity |
| 99 switch (m_match) { | 99 switch (m_match) { |
| 100 case Id: | 100 case Id: |
| 101 return 0x010000; | 101 return 0x010000; |
| 102 case PseudoClass: | 102 case PseudoClass: |
| 103 switch (pseudoType()) { | 103 switch (getPseudoType()) { |
| 104 case PseudoHost: | 104 case PseudoHost: |
| 105 case PseudoHostContext: | 105 case PseudoHostContext: |
| 106 // We dynamically compute the specificity of :host and :host-context | 106 // We dynamically compute the specificity of :host and :host-context |
| 107 // during matching. | 107 // during matching. |
| 108 return 0; | 108 return 0; |
| 109 case PseudoNot: | 109 case PseudoNot: |
| 110 ASSERT(selectorList()); | 110 ASSERT(selectorList()); |
| 111 return selectorList()->first()->specificityForOneSelector(); | 111 return selectorList()->first()->specificityForOneSelector(); |
| 112 // FIXME: PseudoAny should base the specificity on the sub-selectors. | 112 // FIXME: PseudoAny should base the specificity on the sub-selectors. |
| 113 // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0530.html | 113 // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0530.html |
| (...skipping 27 matching lines...) Expand all Loading... |
| 141 { | 141 { |
| 142 // See http://dev.w3.org/csswg/css3-page/#cascading-and-page-context | 142 // See http://dev.w3.org/csswg/css3-page/#cascading-and-page-context |
| 143 unsigned s = 0; | 143 unsigned s = 0; |
| 144 | 144 |
| 145 for (const CSSSelector* component = this; component; component = component->
tagHistory()) { | 145 for (const CSSSelector* component = this; component; component = component->
tagHistory()) { |
| 146 switch (component->m_match) { | 146 switch (component->m_match) { |
| 147 case Tag: | 147 case Tag: |
| 148 s += tagQName().localName() == starAtom ? 0 : 4; | 148 s += tagQName().localName() == starAtom ? 0 : 4; |
| 149 break; | 149 break; |
| 150 case PagePseudoClass: | 150 case PagePseudoClass: |
| 151 switch (component->pseudoType()) { | 151 switch (component->getPseudoType()) { |
| 152 case PseudoFirstPage: | 152 case PseudoFirstPage: |
| 153 s += 2; | 153 s += 2; |
| 154 break; | 154 break; |
| 155 case PseudoLeftPage: | 155 case PseudoLeftPage: |
| 156 case PseudoRightPage: | 156 case PseudoRightPage: |
| 157 s += 1; | 157 s += 1; |
| 158 break; | 158 break; |
| 159 default: | 159 default: |
| 160 ASSERT_NOT_REACHED(); | 160 ASSERT_NOT_REACHED(); |
| 161 } | 161 } |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 return static_cast<CSSSelector::PseudoType>(match->type); | 409 return static_cast<CSSSelector::PseudoType>(match->type); |
| 410 } | 410 } |
| 411 | 411 |
| 412 #ifndef NDEBUG | 412 #ifndef NDEBUG |
| 413 void CSSSelector::show(int indent) const | 413 void CSSSelector::show(int indent) const |
| 414 { | 414 { |
| 415 printf("%*sselectorText(): %s\n", indent, "", selectorText().ascii().data())
; | 415 printf("%*sselectorText(): %s\n", indent, "", selectorText().ascii().data())
; |
| 416 printf("%*sm_match: %d\n", indent, "", m_match); | 416 printf("%*sm_match: %d\n", indent, "", m_match); |
| 417 if (m_match != Tag) | 417 if (m_match != Tag) |
| 418 printf("%*svalue(): %s\n", indent, "", value().ascii().data()); | 418 printf("%*svalue(): %s\n", indent, "", value().ascii().data()); |
| 419 printf("%*spseudoType(): %d\n", indent, "", pseudoType()); | 419 printf("%*sgetPseudoType(): %d\n", indent, "", getPseudoType()); |
| 420 if (m_match == Tag) | 420 if (m_match == Tag) |
| 421 printf("%*stagQName().localName: %s\n", indent, "", tagQName().localName
().ascii().data()); | 421 printf("%*stagQName().localName: %s\n", indent, "", tagQName().localName
().ascii().data()); |
| 422 printf("%*sisAttributeSelector(): %d\n", indent, "", isAttributeSelector()); | 422 printf("%*sisAttributeSelector(): %d\n", indent, "", isAttributeSelector()); |
| 423 if (isAttributeSelector()) | 423 if (isAttributeSelector()) |
| 424 printf("%*sattribute(): %s\n", indent, "", attribute().localName().ascii
().data()); | 424 printf("%*sattribute(): %s\n", indent, "", attribute().localName().ascii
().data()); |
| 425 printf("%*sargument(): %s\n", indent, "", argument().ascii().data()); | 425 printf("%*sargument(): %s\n", indent, "", argument().ascii().data()); |
| 426 printf("%*sspecificity(): %u\n", indent, "", specificity()); | 426 printf("%*sspecificity(): %u\n", indent, "", specificity()); |
| 427 if (tagHistory()) { | 427 if (tagHistory()) { |
| 428 printf("\n%*s--> (relation == %d)\n", indent, "", relation()); | 428 printf("\n%*s--> (relation == %d)\n", indent, "", relation()); |
| 429 tagHistory()->show(indent + 2); | 429 tagHistory()->show(indent + 2); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 bool CSSSelector::operator==(const CSSSelector& other) const | 562 bool CSSSelector::operator==(const CSSSelector& other) const |
| 563 { | 563 { |
| 564 const CSSSelector* sel1 = this; | 564 const CSSSelector* sel1 = this; |
| 565 const CSSSelector* sel2 = &other; | 565 const CSSSelector* sel2 = &other; |
| 566 | 566 |
| 567 while (sel1 && sel2) { | 567 while (sel1 && sel2) { |
| 568 if (sel1->attribute() != sel2->attribute() | 568 if (sel1->attribute() != sel2->attribute() |
| 569 || sel1->relation() != sel2->relation() | 569 || sel1->relation() != sel2->relation() |
| 570 || sel1->m_match != sel2->m_match | 570 || sel1->m_match != sel2->m_match |
| 571 || sel1->value() != sel2->value() | 571 || sel1->value() != sel2->value() |
| 572 || sel1->pseudoType() != sel2->pseudoType() | 572 || sel1->getPseudoType() != sel2->getPseudoType() |
| 573 || sel1->argument() != sel2->argument()) { | 573 || sel1->argument() != sel2->argument()) { |
| 574 return false; | 574 return false; |
| 575 } | 575 } |
| 576 if (sel1->m_match == Tag) { | 576 if (sel1->m_match == Tag) { |
| 577 if (sel1->tagQName() != sel2->tagQName()) | 577 if (sel1->tagQName() != sel2->tagQName()) |
| 578 return false; | 578 return false; |
| 579 } | 579 } |
| 580 sel1 = sel1->tagHistory(); | 580 sel1 = sel1->tagHistory(); |
| 581 sel2 = sel2->tagHistory(); | 581 sel2 = sel2->tagHistory(); |
| 582 } | 582 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 606 if (cs->m_match == Id) { | 606 if (cs->m_match == Id) { |
| 607 str.append('#'); | 607 str.append('#'); |
| 608 serializeIdentifier(cs->serializingValue(), str); | 608 serializeIdentifier(cs->serializingValue(), str); |
| 609 } else if (cs->m_match == Class) { | 609 } else if (cs->m_match == Class) { |
| 610 str.append('.'); | 610 str.append('.'); |
| 611 serializeIdentifier(cs->serializingValue(), str); | 611 serializeIdentifier(cs->serializingValue(), str); |
| 612 } else if (cs->m_match == PseudoClass || cs->m_match == PagePseudoClass)
{ | 612 } else if (cs->m_match == PseudoClass || cs->m_match == PagePseudoClass)
{ |
| 613 str.append(':'); | 613 str.append(':'); |
| 614 str.append(cs->serializingValue()); | 614 str.append(cs->serializingValue()); |
| 615 | 615 |
| 616 switch (cs->pseudoType()) { | 616 switch (cs->getPseudoType()) { |
| 617 case PseudoNthChild: | 617 case PseudoNthChild: |
| 618 case PseudoNthLastChild: | 618 case PseudoNthLastChild: |
| 619 case PseudoNthOfType: | 619 case PseudoNthOfType: |
| 620 case PseudoNthLastOfType: { | 620 case PseudoNthLastOfType: { |
| 621 str.append('('); | 621 str.append('('); |
| 622 | 622 |
| 623 // http://dev.w3.org/csswg/css-syntax/#serializing-anb | 623 // http://dev.w3.org/csswg/css-syntax/#serializing-anb |
| 624 int a = cs->m_data.m_rareData->nthAValue(); | 624 int a = cs->m_data.m_rareData->nthAValue(); |
| 625 int b = cs->m_data.m_rareData->nthBValue(); | 625 int b = cs->m_data.m_rareData->nthBValue(); |
| 626 if (a == 0 && b == 0) | 626 if (a == 0 && b == 0) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 str.appendLiteral("$="); | 684 str.appendLiteral("$="); |
| 685 break; | 685 break; |
| 686 case AttributeContain: | 686 case AttributeContain: |
| 687 str.appendLiteral("*="); | 687 str.appendLiteral("*="); |
| 688 break; | 688 break; |
| 689 default: | 689 default: |
| 690 break; | 690 break; |
| 691 } | 691 } |
| 692 if (cs->m_match != AttributeSet) { | 692 if (cs->m_match != AttributeSet) { |
| 693 serializeString(cs->serializingValue(), str); | 693 serializeString(cs->serializingValue(), str); |
| 694 if (cs->attributeMatchType() == CaseInsensitive) | 694 if (cs->attributeMatch() == CaseInsensitive) |
| 695 str.appendLiteral(" i"); | 695 str.appendLiteral(" i"); |
| 696 str.append(']'); | 696 str.append(']'); |
| 697 } | 697 } |
| 698 } | 698 } |
| 699 | 699 |
| 700 if (cs->selectorList()) { | 700 if (cs->selectorList()) { |
| 701 str.append('('); | 701 str.append('('); |
| 702 const CSSSelector* firstSubSelector = cs->selectorList()->first(); | 702 const CSSSelector* firstSubSelector = cs->selectorList()->first(); |
| 703 for (const CSSSelector* subSelector = firstSubSelector; subSelector;
subSelector = CSSSelectorList::next(*subSelector)) { | 703 for (const CSSSelector* subSelector = firstSubSelector; subSelector;
subSelector = CSSSelectorList::next(*subSelector)) { |
| 704 if (subSelector != firstSubSelector) | 704 if (subSelector != firstSubSelector) |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 case CSSSelector::AttributeEnd: | 769 case CSSSelector::AttributeEnd: |
| 770 return true; | 770 return true; |
| 771 case CSSSelector::PseudoElement: | 771 case CSSSelector::PseudoElement: |
| 772 case CSSSelector::Unknown: | 772 case CSSSelector::Unknown: |
| 773 return false; | 773 return false; |
| 774 case CSSSelector::PagePseudoClass: | 774 case CSSSelector::PagePseudoClass: |
| 775 case CSSSelector::PseudoClass: | 775 case CSSSelector::PseudoClass: |
| 776 break; | 776 break; |
| 777 } | 777 } |
| 778 | 778 |
| 779 switch (selector->pseudoType()) { | 779 switch (selector->getPseudoType()) { |
| 780 case CSSSelector::PseudoEmpty: | 780 case CSSSelector::PseudoEmpty: |
| 781 case CSSSelector::PseudoLink: | 781 case CSSSelector::PseudoLink: |
| 782 case CSSSelector::PseudoVisited: | 782 case CSSSelector::PseudoVisited: |
| 783 case CSSSelector::PseudoTarget: | 783 case CSSSelector::PseudoTarget: |
| 784 case CSSSelector::PseudoEnabled: | 784 case CSSSelector::PseudoEnabled: |
| 785 case CSSSelector::PseudoDisabled: | 785 case CSSSelector::PseudoDisabled: |
| 786 case CSSSelector::PseudoChecked: | 786 case CSSSelector::PseudoChecked: |
| 787 case CSSSelector::PseudoIndeterminate: | 787 case CSSSelector::PseudoIndeterminate: |
| 788 case CSSSelector::PseudoNthChild: | 788 case CSSSelector::PseudoNthChild: |
| 789 case CSSSelector::PseudoNthLastChild: | 789 case CSSSelector::PseudoNthLastChild: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 return true; | 826 return true; |
| 827 } | 827 } |
| 828 | 828 |
| 829 unsigned CSSSelector::computeLinkMatchType() const | 829 unsigned CSSSelector::computeLinkMatchType() const |
| 830 { | 830 { |
| 831 unsigned linkMatchType = MatchAll; | 831 unsigned linkMatchType = MatchAll; |
| 832 | 832 |
| 833 // Determine if this selector will match a link in visited, unvisited or any
state, or never. | 833 // Determine if this selector will match a link in visited, unvisited or any
state, or never. |
| 834 // :visited never matches other elements than the innermost link element. | 834 // :visited never matches other elements than the innermost link element. |
| 835 for (const CSSSelector* current = this; current; current = current->tagHisto
ry()) { | 835 for (const CSSSelector* current = this; current; current = current->tagHisto
ry()) { |
| 836 switch (current->pseudoType()) { | 836 switch (current->getPseudoType()) { |
| 837 case PseudoNot: | 837 case PseudoNot: |
| 838 { | 838 { |
| 839 // :not(:visited) is equivalent to :link. Parser enforces that :
not can't nest. | 839 // :not(:visited) is equivalent to :link. Parser enforces that :
not can't nest. |
| 840 ASSERT(current->selectorList()); | 840 ASSERT(current->selectorList()); |
| 841 for (const CSSSelector* subSelector = current->selectorList()->f
irst(); subSelector; subSelector = subSelector->tagHistory()) { | 841 for (const CSSSelector* subSelector = current->selectorList()->f
irst(); subSelector; subSelector = subSelector->tagHistory()) { |
| 842 PseudoType subType = subSelector->pseudoType(); | 842 PseudoType subType = subSelector->getPseudoType(); |
| 843 if (subType == PseudoVisited) | 843 if (subType == PseudoVisited) |
| 844 linkMatchType &= ~MatchVisited; | 844 linkMatchType &= ~MatchVisited; |
| 845 else if (subType == PseudoLink) | 845 else if (subType == PseudoLink) |
| 846 linkMatchType &= ~MatchLink; | 846 linkMatchType &= ~MatchLink; |
| 847 } | 847 } |
| 848 } | 848 } |
| 849 break; | 849 break; |
| 850 case PseudoLink: | 850 case PseudoLink: |
| 851 linkMatchType &= ~MatchVisited; | 851 linkMatchType &= ~MatchVisited; |
| 852 break; | 852 break; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 if (count < nthBValue()) | 914 if (count < nthBValue()) |
| 915 return false; | 915 return false; |
| 916 return (count - nthBValue()) % nthAValue() == 0; | 916 return (count - nthBValue()) % nthAValue() == 0; |
| 917 } | 917 } |
| 918 if (count > nthBValue()) | 918 if (count > nthBValue()) |
| 919 return false; | 919 return false; |
| 920 return (nthBValue() - count) % (-nthAValue()) == 0; | 920 return (nthBValue() - count) % (-nthAValue()) == 0; |
| 921 } | 921 } |
| 922 | 922 |
| 923 } // namespace blink | 923 } // namespace blink |
| OLD | NEW |