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