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     , m_isPrefixed(o.m_isPrefixed)
     47 {
     48 }
     49 
     50 StyleRuleKeyframes::~StyleRuleKeyframes()
     51 {
     52 }
     53 
     54 void StyleRuleKeyframes::parserAppendKeyframe(PassRefPtr<StyleKeyframe> keyframe)
     55 {
     56     if (!keyframe)
     57         return;
     58     m_keyframes.append(keyframe);
     59 }
     60 
     61 void StyleRuleKeyframes::wrapperAppendKeyframe(PassRefPtr<StyleKeyframe> keyframe)
     62 {
     63     m_keyframes.append(keyframe);
     64 }
     65 
     66 void StyleRuleKeyframes::wrapperRemoveKeyframe(unsigned index)
     67 {
     68     m_keyframes.remove(index);
     69 }
     70 
     71 int StyleRuleKeyframes::findKeyframeIndex(const String& key) const
     72 {
     73     String percentageString;
     74     if (equalIgnoringCase(key, "from"))
     75         percentageString = "0%";
     76     else if (equalIgnoringCase(key, "to"))
     77         percentageString = "100%";
     78     else
     79         percentageString = key;
     80 
     81     for (unsigned i = 0; i < m_keyframes.size(); ++i) {
     82         if (m_keyframes[i]->keyText() == percentageString)
     83             return i;
     84     }
     85     return -1;
     86 }
     87 
     88 CSSKeyframesRule::CSSKeyframesRule(StyleRuleKeyframes* keyframesRule, CSSStyleSheet* parent)
     89     : CSSRule(parent)
     90     , m_keyframesRule(keyframesRule)
     91     , m_childRuleCSSOMWrappers(keyframesRule->keyframes().size())
     92     , m_isPrefixed(keyframesRule->isVendorPrefixed())
     93 {
     94 }
     95 
     96 CSSKeyframesRule::~CSSKeyframesRule()
     97 {
     98     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
     99 
    100     for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) {
    101         if (m_childRuleCSSOMWrappers[i])
    102             m_childRuleCSSOMWrappers[i]->setParentRule(0);
    103     }
    104 }
    105 
    106 void CSSKeyframesRule::setName(const String& name)
    107 {
    108     CSSStyleSheet::RuleMutationScope mutationScope(this);
    109 
    110     m_keyframesRule->setName(name);
    111 }
    112 
    113 void CSSKeyframesRule::insertRule(const String& ruleText)
    114 {
    115     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
    116 
    117     CSSStyleSheet* styleSheet = parentStyleSheet();
    118     CSSParser parser(parserContext(), UseCounter::getFrom(styleSheet));
    119     RefPtr<StyleKeyframe> keyframe = parser.parseKeyframeRule(styleSheet ? styleSheet->contents() : 0, ruleText);
    120     if (!keyframe)
    121         return;
    122 
    123     CSSStyleSheet::RuleMutationScope mutationScope(this);
    124 
    125     m_keyframesRule->wrapperAppendKeyframe(keyframe);
    126 
    127     m_childRuleCSSOMWrappers.grow(length());
    128 }
    129 
    130 void CSSKeyframesRule::deleteRule(const String& s)
    131 {
    132     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
    133 
    134     int i = m_keyframesRule->findKeyframeIndex(s);
    135     if (i < 0)
    136         return;
    137 
    138     CSSStyleSheet::RuleMutationScope mutationScope(this);
    139 
    140     m_keyframesRule->wrapperRemoveKeyframe(i);
    141 
    142     if (m_childRuleCSSOMWrappers[i])
    143         m_childRuleCSSOMWrappers[i]->setParentRule(0);
    144     m_childRuleCSSOMWrappers.remove(i);
    145 }
    146 
    147 CSSKeyframeRule* CSSKeyframesRule::findRule(const String& s)
    148 {
    149     int i = m_keyframesRule->findKeyframeIndex(s);
    150     return (i >= 0) ? item(i) : 0;
    151 }
    152 
    153 String CSSKeyframesRule::cssText() const
    154 {
    155     StringBuilder result;
    156     if (isVendorPrefixed())
    157         result.append("@-webkit-keyframes ");
    158     else
    159         result.append("@keyframes ");
    160     result.append(name());
    161     result.append(" { \n");
    162 
    163     unsigned size = length();
    164     for (unsigned i = 0; i < size; ++i) {
    165         result.append("  ");
    166         result.append(m_keyframesRule->keyframes()[i]->cssText());
    167         result.append("\n");
    168     }
    169     result.append("}");
    170     return result.toString();
    171 }
    172 
    173 unsigned CSSKeyframesRule::length() const
    174 {
    175     return m_keyframesRule->keyframes().size();
    176 }
    177 
    178 CSSKeyframeRule* CSSKeyframesRule::item(unsigned index) const
    179 {
    180     if (index >= length())
    181         return 0;
    182 
    183     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
    184     RefPtr<CSSKeyframeRule>& rule = m_childRuleCSSOMWrappers[index];
    185     if (!rule)
    186         rule = adoptRef(new CSSKeyframeRule(m_keyframesRule->keyframes()[index].get(), const_cast<CSSKeyframesRule*>(this)));
    187 
    188     return rule.get();
    189 }
    190 
    191 CSSRuleList* CSSKeyframesRule::cssRules()
    192 {
    193     if (!m_ruleListCSSOMWrapper)
    194         m_ruleListCSSOMWrapper = adoptPtr(new LiveCSSRuleList<CSSKeyframesRule>(this));
    195     return m_ruleListCSSOMWrapper.get();
    196 }
    197 
    198 void CSSKeyframesRule::reattach(StyleRuleBase* rule)
    199 {
    200     ASSERT(rule);
    201     m_keyframesRule = toStyleRuleKeyframes(rule);
    202 }
    203 
    204 } // namespace WebCore
    205