Changeset 30069 in webkit
- Timestamp:
- Feb 7, 2008 12:13:24 PM (16 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r30067 r30069 1 2008-02-07 David Hyatt <hyatt@apple.com> 2 3 Fix for bug 6248, implement the nth-* CSS3 selectors. Patch based on original KHTML work from Allan Jensen 4 and improved upon by Nick Shanks. 5 6 Reviewed by Eric 7 8 * css/CSSGrammar.y: 9 * css/CSSParser.cpp: 10 (WebCore::CSSParser::lex): 11 * css/CSSSelector.cpp: 12 (WebCore::CSSSelector::extractPseudoType): 13 * css/CSSSelector.h: 14 (WebCore::CSSSelector::): 15 * css/CSSStyleSelector.cpp: 16 (WebCore::parseNth): 17 (WebCore::matchNth): 18 (WebCore::CSSStyleSelector::checkOneSelector): 19 * css/tokenizer.flex: 20 * rendering/RenderStyle.cpp: 21 (WebCore::RenderStyle::RenderStyle): 22 * rendering/RenderStyle.h: 23 (WebCore::RenderStyle::childIndex): 24 (WebCore::RenderStyle::setChildIndex): 25 1 26 2008-02-07 Dan Bernstein <mitz@apple.com> 2 27 -
trunk/WebCore/css/CSSGrammar.y
r29976 r30069 166 166 167 167 %token <string> STRING 168 169 168 %right <string> IDENT 169 %token <string> NTH 170 170 171 171 %nonassoc <string> HEX … … 908 908 } 909 909 } 910 // used by :lang 910 // used by :nth-*(ax+b) 911 | ':' FUNCTION NTH ')' { 912 CSSParser *p = static_cast<CSSParser*>(parser); 913 $$ = p->createFloatingSelector(); 914 $$->m_match = CSSSelector::PseudoClass; 915 $$->m_argument = atomicString($3); 916 $$->m_value = atomicString($2); 917 CSSSelector::PseudoType type = $$->pseudoType(); 918 if (type == CSSSelector::PseudoUnknown) 919 $$ = 0; 920 else if (type == CSSSelector::PseudoNthChild || type == CSSSelector::PseudoNthOfType) { 921 if (p->document()) 922 p->document()->setUsesSiblingRules(true); 923 } 924 } 925 // used by :nth-* 926 | ':' FUNCTION INTEGER ')' { 927 CSSParser *p = static_cast<CSSParser*>(parser); 928 $$ = p->createFloatingSelector(); 929 $$->m_match = CSSSelector::PseudoClass; 930 $$->m_argument = String::number($3); 931 $$->m_value = atomicString($2); 932 CSSSelector::PseudoType type = $$->pseudoType(); 933 if (type == CSSSelector::PseudoUnknown) 934 $$ = 0; 935 else if (type == CSSSelector::PseudoNthChild || type == CSSSelector::PseudoNthOfType) { 936 if (p->document()) 937 p->document()->setUsesSiblingRules(true); 938 } 939 } 940 // used by :nth-*(odd/even) and :lang 911 941 | ':' FUNCTION IDENT ')' { 912 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector(); 942 CSSParser *p = static_cast<CSSParser*>(parser); 943 $$ = p->createFloatingSelector(); 913 944 $$->m_match = CSSSelector::PseudoClass; 914 945 $$->m_argument = atomicString($3); 915 946 $2.lower(); 916 947 $$->m_value = atomicString($2); 917 if ($$->pseudoType() == CSSSelector::PseudoUnknown) 948 CSSSelector::PseudoType type = $$->pseudoType(); 949 if (type == CSSSelector::PseudoUnknown) 918 950 $$ = 0; 951 else if (type == CSSSelector::PseudoNthChild || type == CSSSelector::PseudoNthOfType) { 952 if (p->document()) 953 p->document()->setUsesSiblingRules(true); 954 } 919 955 } 920 956 // used by :not -
trunk/WebCore/css/CSSParser.cpp
r29910 r30069 3562 3562 case STRING: 3563 3563 case IDENT: 3564 case NTH: 3564 3565 case HEX: 3565 3566 case IDSEL: -
trunk/WebCore/css/CSSSelector.cpp
r29944 r30069 85 85 static AtomicString firstLine("first-line"); 86 86 static AtomicString firstOfType("first-of-type"); 87 static AtomicString nthChild("nth-child("); 88 static AtomicString nthOfType("nth-of-type("); 89 static AtomicString nthLastChild("nth-last-child("); 90 static AtomicString nthLastOfType("nth-last-of-type("); 87 91 static AtomicString focus("focus"); 88 92 static AtomicString hover("hover"); … … 200 204 } else if (m_value == notStr) 201 205 m_pseudoType = PseudoNot; 206 else if (m_value == nthChild) 207 m_pseudoType = PseudoNthChild; 208 else if (m_value == nthOfType) 209 m_pseudoType = PseudoNthOfType; 210 else if (m_value == nthLastChild) 211 m_pseudoType = PseudoNthLastChild; 212 else if (m_value == nthLastOfType) 213 m_pseudoType = PseudoNthLastOfType; 202 214 else if (m_value == root) 203 215 m_pseudoType = PseudoRoot; -
trunk/WebCore/css/CSSSelector.h
r29944 r30069 128 128 PseudoFirstLine, 129 129 PseudoFirstLetter, 130 PseudoNthChild, 131 PseudoNthOfType, 132 PseudoNthLastChild, 133 PseudoNthLastOfType, 130 134 PseudoLink, 131 135 PseudoVisited, -
trunk/WebCore/css/CSSStyleSelector.cpp
r29944 r30069 713 713 ? PseudoVisited : PseudoLink; 714 714 } 715 716 // a helper function for parsing nth-arguments 717 static bool parseNth(const String& nth, int &a, int &b) 718 { 719 if (nth.isEmpty()) 720 return false; 721 a = 0; 722 b = 0; 723 if (nth == "odd") { 724 a = 2; 725 b = 1; 726 } else if (nth == "even") { 727 a = 2; 728 b = 0; 729 } else { 730 int n = nth.find('n'); 731 if (n != -1) { 732 if (nth[0] == '-') { 733 if (n == 1) 734 a = -1; // -n == -1n 735 else 736 a = nth.substring(1, n - 1).toInt(); 737 } else if (!n) 738 a = 1; // n == 1n 739 else 740 a = nth.substring(0, n).toInt(); 741 742 int p = nth.find('+', n); 743 if (p != -1) 744 b = nth.substring(p + 1, nth.length() - p - 1).toInt(); 745 else { 746 p = nth.find('-', n); 747 b = -nth.substring(p + 1, nth.length() - p - 1).toInt(); 748 } 749 } else 750 b = nth.toInt(); 751 } 752 return true; 753 } 754 755 // a helper function for checking nth-arguments 756 static bool matchNth(int count, int a, int b) 757 { 758 if (!a) 759 return count == b; 760 else if (a > 0) { 761 if (count < b) 762 return false; 763 return (count - b) % a == 0; 764 } else { 765 if (count > b) 766 return false; 767 return (b - count) % (-a) == 0; 768 } 769 } 770 715 771 716 772 #ifdef STYLE_SHARING_STATS … … 1722 1778 } 1723 1779 case CSSSelector::PseudoOnlyOfType: { 1780 // FIXME: This selector is very slow. 1724 1781 if (e->parentNode() && e->parentNode()->isElementNode()) { 1725 1782 bool firstChild = false; … … 1750 1807 } 1751 1808 return firstChild && lastChild; 1809 } 1810 break; 1811 } 1812 case CSSSelector::PseudoNthChild: { 1813 int a, b; 1814 // calculate a and b every time we run through checkOneSelector 1815 // this should probably be saved after we calculate it once, but currently 1816 // would require increasing the size of CSSSelector 1817 if (!parseNth(sel->m_argument, a, b)) 1818 break; 1819 if (e->parentNode() && e->parentNode()->isElementNode()) { 1820 int count = 1; 1821 Node* n = e->previousSibling(); 1822 while (n) { 1823 if (n->isElementNode()) { 1824 RenderStyle* s = n->renderStyle(); 1825 unsigned index = s ? s->childIndex() : 0; 1826 if (index) { 1827 count += index; 1828 break; 1829 } 1830 count++; 1831 } 1832 n = n->previousSibling(); 1833 } 1834 1835 if (!m_collectRulesOnly) { 1836 RenderStyle* childStyle = (m_element == e) ? m_style : e->renderStyle(); 1837 RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); 1838 if (childStyle) 1839 childStyle->setChildIndex(count); 1840 if (parentStyle) 1841 parentStyle->setChildrenAffectedByPositionalRules(); 1842 } 1843 1844 if (matchNth(count, a, b)) 1845 return true; 1846 } 1847 break; 1848 } 1849 case CSSSelector::PseudoNthOfType: { 1850 // FIXME: This selector is very slow. 1851 int a, b; 1852 // calculate a and b every time we run through checkOneSelector (see above) 1853 if (!parseNth(sel->m_argument, a, b)) 1854 break; 1855 if (e->parentNode() && e->parentNode()->isElementNode()) { 1856 int count = 1; 1857 const QualifiedName& type = e->tagQName(); 1858 Node* n = e->previousSibling(); 1859 while (n) { 1860 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) 1861 count++; 1862 n = n->previousSibling(); 1863 } 1864 1865 if (!m_collectRulesOnly) { 1866 RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); 1867 if (parentStyle) 1868 parentStyle->setChildrenAffectedByPositionalRules(); 1869 } 1870 1871 if (matchNth(count, a, b)) 1872 return true; 1873 } 1874 break; 1875 } 1876 case CSSSelector::PseudoNthLastChild: { 1877 int a, b; 1878 // calculate a and b every time we run through checkOneSelector 1879 // this should probably be saved after we calculate it once, but currently 1880 // would require increasing the size of CSSSelector 1881 if (!parseNth(sel->m_argument, a, b)) 1882 break; 1883 if (e->parentNode() && e->parentNode()->isElementNode()) { 1884 int count = 1; 1885 Node* n = e->nextSibling(); 1886 while (n) { 1887 if (n->isElementNode()) 1888 count++; 1889 n = n->nextSibling(); 1890 } 1891 1892 if (!m_collectRulesOnly) { 1893 RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); 1894 if (parentStyle) 1895 parentStyle->setChildrenAffectedByPositionalRules(); 1896 } 1897 1898 if (matchNth(count, a, b)) 1899 return true; 1900 } 1901 break; 1902 } 1903 case CSSSelector::PseudoNthLastOfType: { 1904 // FIXME: This selector is very slow. 1905 int a, b; 1906 // calculate a and b every time we run through checkOneSelector (see above) 1907 if (!parseNth(sel->m_argument, a, b)) 1908 break; 1909 if (e->parentNode() && e->parentNode()->isElementNode()) { 1910 int count = 1; 1911 const QualifiedName& type = e->tagQName(); 1912 Node* n = e->nextSibling(); 1913 while (n) { 1914 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) 1915 count++; 1916 n = n->nextSibling(); 1917 } 1918 1919 if (!m_collectRulesOnly) { 1920 RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); 1921 if (parentStyle) 1922 parentStyle->setChildrenAffectedByPositionalRules(); 1923 } 1924 1925 if (matchNth(count, a, b)) 1926 return true; 1752 1927 } 1753 1928 break; -
trunk/WebCore/css/tokenizer.flex
r25934 r30069 24 24 nl \n|\r\n|\r|\f 25 25 range \?{1,6}|{h}(\?{0,5}|{h}(\?{0,4}|{h}(\?{0,3}|{h}(\?{0,2}|{h}(\??|{h}))))) 26 nth (-?[0-9]*n[\+-][0-9]+)|(-?[0-9]*n) 26 27 27 28 %% … … 43 44 44 45 {string} {yyTok = STRING; return yyTok;} 45 46 46 {ident} {yyTok = IDENT; return yyTok;} 47 {nth} {yyTok = NTH; return yyTok;} 47 48 48 49 "#"{hexcolor} {yyTok = HEX; return yyTok;} -
trunk/WebCore/rendering/RenderStyle.cpp
r29932 r30069 938 938 , m_firstChildState(false) 939 939 , m_lastChildState(false) 940 , m_childIndex(0) 940 941 , m_ref(0) 941 942 #if ENABLE(SVG) … … 958 959 , m_firstChildState(false) 959 960 , m_lastChildState(false) 961 , m_childIndex(0) 960 962 , m_ref(1) 961 963 { … … 1000 1002 , m_firstChildState(false) 1001 1003 , m_lastChildState(false) 1004 , m_childIndex(0) 1002 1005 , m_ref(0) 1003 1006 #if ENABLE(SVG) -
trunk/WebCore/rendering/RenderStyle.h
r29932 r30069 1462 1462 // list of associated pseudo styles 1463 1463 RenderStyle* pseudoStyle; 1464 1464 1465 1465 unsigned m_pseudoState : 3; // PseudoState 1466 1466 bool m_affectedByAttributeSelectors : 1; … … 1478 1478 bool m_firstChildState : 1; 1479 1479 bool m_lastChildState : 1; 1480 unsigned m_childIndex : 20; // Plenty of bits to cache an index. 1480 1481 1481 1482 int m_ref; … … 2135 2136 bool lastChildState() const { return m_lastChildState; } 2136 2137 void setLastChildState() { m_lastChildState = true; } 2138 unsigned childIndex() const { return m_childIndex; } 2139 void setChildIndex(unsigned index) { m_childIndex = index; } 2137 2140 2138 2141 // Initial values for all the properties
Note: See TracChangeset
for help on using the changeset viewer.