Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 2007, 2008, 2012 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "core/css/CSSKeyframesRule.h"
     28 
     29 #include "core/css/CSSKeyframeRule.h"
     30 #include "core/css/CSSParser.h"
     31 #include "core/css/CSSRuleList.h"
     32 #include "core/css/CSSStyleSheet.h"
     33 #include "wtf/text/StringBuilder.h"
     34 
     35 namespace WebCore {
     36 
     37 StyleRuleKeyframes::StyleRuleKeyframes()
     38     : StyleRuleBase(Keyframes)
     39 {
     40 }
     41 
     42 StyleRuleKeyframes::StyleRuleKeyframes(const StyleRuleKeyframes& o)
     43     : StyleRuleBase(o)
     44     , m_keyframes(o.m_keyframes)
     45     , m_name(o.m_name)
     46 {
     47 }
     48 
     49 StyleRuleKeyframes::~StyleRuleKeyframes()
     50 {
     51 }
     52 
     53 void StyleRuleKeyframes::parserAppendKeyframe(PassRefPtr<StyleKeyframe> keyframe)
     54 {
     55     if (!keyframe)
     56         return;
     57     m_keyframes.append(keyframe);
     58 }
     59 
     60 void StyleRuleKeyframes::wrapperAppendKeyframe(PassRefPtr<StyleKeyframe> keyframe)
     61 {
     62     m_keyframes.append(keyframe);
     63 }
     64 
     65 void StyleRuleKeyframes::wrapperRemoveKeyframe(unsigned index)
     66 {
     67     m_keyframes.remove(index);
     68 }
     69 
     70 int StyleRuleKeyframes::findKeyframeIndex(const String& key) const
     71 {
     72     String percentageString;
     73     if (equalIgnoringCase(key, "from"))
     74         percentageString = "0%";
     75     else if (equalIgnoringCase(key, "to"))
     76         percentageString = "100%";
     77     else
     78         percentageString = key;
     79 
     80     for (unsigned i = 0; i < m_keyframes.size(); ++i) {
     81         if (m_keyframes[i]->keyText() == percentageString)
     82             return i;
     83     }
     84     return -1;
     85 }
     86 
     87 CSSKeyframesRule::CSSKeyframesRule(StyleRuleKeyframes* keyframesRule, CSSStyleSheet* parent)
     88     : CSSRule(parent)
     89     , m_keyframesRule(keyframesRule)
     90     , m_childRuleCSSOMWrappers(keyframesRule->keyframes().size())
     91 {
     92 }
     93 
     94 CSSKeyframesRule::~CSSKeyframesRule()
     95 {
     96     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
     97 
     98     for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) {
     99         if (m_childRuleCSSOMWrappers[i])
    100             m_childRuleCSSOMWrappers[i]->setParentRule(0);
    101     }
    102 }
    103 
    104 void CSSKeyframesRule::setName(const String& name)
    105 {
    106     CSSStyleSheet::RuleMutationScope mutationScope(this);
    107 
    108     m_keyframesRule->setName(name);
    109 }
    110 
    111 void CSSKeyframesRule::insertRule(const String& ruleText)
    112 {
    113     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
    114 
    115     CSSStyleSheet* styleSheet = parentStyleSheet();
    116     CSSParser parser(parserContext(), UseCounter::getFrom(styleSheet));
    117     RefPtr<StyleKeyframe> keyframe = parser.parseKeyframeRule(styleSheet ? styleSheet->contents() : 0, ruleText);
    118     if (!keyframe)
    119         return;
    120 
    121     CSSStyleSheet::RuleMutationScope mutationScope(this);
    122 
    123     m_keyframesRule->wrapperAppendKeyframe(keyframe);
    124 
    125     m_childRuleCSSOMWrappers.grow(length());
    126 }
    127 
    128 void CSSKeyframesRule::deleteRule(const String& s)
    129 {
    130     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
    131 
    132     int i = m_keyframesRule->findKeyframeIndex(s);
    133     if (i < 0)
    134         return;
    135 
    136     CSSStyleSheet::RuleMutationScope mutationScope(this);
    137 
    138     m_keyframesRule->wrapperRemoveKeyframe(i);
    139 
    140     if (m_childRuleCSSOMWrappers[i])
    141         m_childRuleCSSOMWrappers[i]->setParentRule(0);
    142     m_childRuleCSSOMWrappers.remove(i);
    143 }
    144 
    145 CSSKeyframeRule* CSSKeyframesRule::findRule(const String& s)
    146 {
    147     int i = m_keyframesRule->findKeyframeIndex(s);
    148     return (i >= 0) ? item(i) : 0;
    149 }
    150 
    151 String CSSKeyframesRule::cssText() const
    152 {
    153     StringBuilder result;
    154     result.append("@-webkit-keyframes ");
    155     result.append(name());
    156     result.append(" { \n");
    157 
    158     unsigned size = length();
    159     for (unsigned i = 0; i < size; ++i) {
    160         result.append("  ");
    161         result.append(m_keyframesRule->keyframes()[i]->cssText());
    162         result.append("\n");
    163     }
    164     result.append("}");
    165     return result.toString();
    166 }
    167 
    168 unsigned CSSKeyframesRule::length() const
    169 {
    170     return m_keyframesRule->keyframes().size();
    171 }
    172 
    173 CSSKeyframeRule* CSSKeyframesRule::item(unsigned index) const
    174 {
    175     if (index >= length())
    176         return 0;
    177 
    178     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
    179     RefPtr<CSSKeyframeRule>& rule = m_childRuleCSSOMWrappers[index];
    180     if (!rule)
    181         rule = adoptRef(new CSSKeyframeRule(m_keyframesRule->keyframes()[index].get(), const_cast<CSSKeyframesRule*>(this)));
    182 
    183     return rule.get();
    184 }
    185 
    186 CSSRuleList* CSSKeyframesRule::cssRules()
    187 {
    188     if (!m_ruleListCSSOMWrapper)
    189         m_ruleListCSSOMWrapper = adoptPtr(new LiveCSSRuleList<CSSKeyframesRule>(this));
    190     return m_ruleListCSSOMWrapper.get();
    191 }
    192 
    193 void CSSKeyframesRule::reattach(StyleRuleBase* rule)
    194 {
    195     ASSERT(rule);
    196     ASSERT_WITH_SECURITY_IMPLICATION(rule->isKeyframesRule());
    197     m_keyframesRule = static_cast<StyleRuleKeyframes*>(rule);
    198 }
    199 
    200 } // namespace WebCore
    201