1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 6 * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org> 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 11 * Copyright (C) 2012 Google Inc. All rights reserved. 12 * 13 * This library is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU Library General Public 15 * License as published by the Free Software Foundation; either 16 * version 2 of the License, or (at your option) any later version. 17 * 18 * This library is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * Library General Public License for more details. 22 * 23 * You should have received a copy of the GNU Library General Public License 24 * along with this library; see the file COPYING.LIB. If not, write to 25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 26 * Boston, MA 02110-1301, USA. 27 */ 28 29 #include "config.h" 30 #include "core/css/PageRuleCollector.h" 31 32 #include "core/css/StylePropertySet.h" 33 #include "core/css/StyleRule.h" 34 #include "core/css/resolver/StyleResolverState.h" 35 36 namespace WebCore { 37 38 static inline bool comparePageRules(const StyleRulePage* r1, const StyleRulePage* r2) 39 { 40 return r1->selector()->specificity() < r2->selector()->specificity(); 41 } 42 43 bool PageRuleCollector::isLeftPage(int pageIndex) const 44 { 45 bool isFirstPageLeft = false; 46 if (!m_context.rootElementStyle()->isLeftToRightDirection()) 47 isFirstPageLeft = true; 48 49 return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2; 50 } 51 52 bool PageRuleCollector::isFirstPage(int pageIndex) const 53 { 54 // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page. 55 return (!pageIndex); 56 } 57 58 String PageRuleCollector::pageName(int /* pageIndex */) const 59 { 60 // FIXME: Implement page index to page name mapping. 61 return ""; 62 } 63 64 PageRuleCollector::PageRuleCollector(const ElementResolveContext& context, int pageIndex) 65 : m_context(context) 66 , m_isLeftPage(isLeftPage(pageIndex)) 67 , m_isFirstPage(isFirstPage(pageIndex)) 68 , m_pageName(pageName(pageIndex)) { } 69 70 void PageRuleCollector::matchPageRules(RuleSet* rules) 71 { 72 if (!rules) 73 return; 74 75 rules->compactRulesIfNeeded(); 76 Vector<StyleRulePage*> matchedPageRules; 77 matchPageRulesForList(matchedPageRules, rules->pageRules(), m_isLeftPage, m_isFirstPage, m_pageName); 78 if (matchedPageRules.isEmpty()) 79 return; 80 81 std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules); 82 83 for (unsigned i = 0; i < matchedPageRules.size(); i++) 84 m_result.addMatchedProperties(matchedPageRules[i]->properties()); 85 } 86 87 static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeftPage, bool isFirstPage, const String& pageName) 88 { 89 for (const CSSSelector* component = selector; component; component = component->tagHistory()) { 90 if (component->m_match == CSSSelector::Tag) { 91 const AtomicString& localName = component->tagQName().localName(); 92 if (localName != starAtom && localName != pageName) 93 return false; 94 } 95 96 CSSSelector::PseudoType pseudoType = component->pseudoType(); 97 if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage) 98 || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage) 99 || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage)) 100 { 101 return false; 102 } 103 } 104 return true; 105 } 106 107 void PageRuleCollector::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName) 108 { 109 for (unsigned i = 0; i < rules.size(); ++i) { 110 StyleRulePage* rule = rules[i]; 111 112 if (!checkPageSelectorComponents(rule->selector(), isLeftPage, isFirstPage, pageName)) 113 continue; 114 115 // If the rule has no properties to apply, then ignore it. 116 const StylePropertySet* properties = rule->properties(); 117 if (!properties || properties->isEmpty()) 118 continue; 119 120 // Add this rule to our list of matched rules. 121 matchedRules.append(rule); 122 } 123 } 124 125 } // namespace WebCore 126