1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@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@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@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 "PageRuleCollector.h" 31 32#include "CSSDefaultStyleSheets.h" 33#include "StylePropertySet.h" 34#include "StyleRule.h" 35 36namespace WebCore { 37 38static inline bool comparePageRules(const StyleRulePage* r1, const StyleRulePage* r2) 39{ 40 return r1->selector()->specificity() < r2->selector()->specificity(); 41} 42 43bool PageRuleCollector::isLeftPage(int pageIndex) const 44{ 45 bool isFirstPageLeft = false; 46 if (!m_state.rootElementStyle()->isLeftToRightDirection()) 47 isFirstPageLeft = true; 48 49 return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2; 50} 51 52bool 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 58String PageRuleCollector::pageName(int /* pageIndex */) const 59{ 60 // FIXME: Implement page index to page name mapping. 61 return ""; 62} 63 64void PageRuleCollector::matchAllPageRules(int pageIndex) 65{ 66 const bool isLeft = isLeftPage(pageIndex); 67 const bool isFirst = isFirstPage(pageIndex); 68 const String page = pageName(pageIndex); 69 70 matchPageRules(CSSDefaultStyleSheets::defaultPrintStyle, isLeft, isFirst, page); 71 matchPageRules(m_ruleSets.userStyle(), isLeft, isFirst, page); 72 // Only consider the global author RuleSet for @page rules, as per the HTML5 spec. 73 matchPageRules(m_ruleSets.authorStyle(), isLeft, isFirst, page); 74} 75 76void PageRuleCollector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName) 77{ 78 if (!rules) 79 return; 80 81 Vector<StyleRulePage*> matchedPageRules; 82 matchPageRulesForList(matchedPageRules, rules->pageRules(), isLeftPage, isFirstPage, pageName); 83 if (matchedPageRules.isEmpty()) 84 return; 85 86 std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules); 87 88 for (unsigned i = 0; i < matchedPageRules.size(); i++) 89 m_result.addMatchedProperties(matchedPageRules[i]->properties()); 90} 91 92static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeftPage, bool isFirstPage, const String& pageName) 93{ 94 for (const CSSSelector* component = selector; component; component = component->tagHistory()) { 95 if (component->m_match == CSSSelector::Tag) { 96 const AtomicString& localName = component->tagQName().localName(); 97 if (localName != starAtom && localName != pageName) 98 return false; 99 } 100 101 CSSSelector::PseudoType pseudoType = component->pseudoType(); 102 if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage) 103 || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage) 104 || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage)) 105 { 106 return false; 107 } 108 } 109 return true; 110} 111 112void PageRuleCollector::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName) 113{ 114 for (unsigned i = 0; i < rules.size(); ++i) { 115 StyleRulePage* rule = rules[i]; 116 117 if (!checkPageSelectorComponents(rule->selector(), isLeftPage, isFirstPage, pageName)) 118 continue; 119 120 // If the rule has no properties to apply, then ignore it. 121 const StylePropertySet* properties = rule->properties(); 122 if (!properties || properties->isEmpty()) 123 continue; 124 125 // Add this rule to our list of matched rules. 126 matchedRules.append(rule); 127 } 128} 129 130} // namespace WebCore 131