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/CSSRuleList.h"
     31 #include "core/css/CSSStyleSheet.h"
     32 #include "core/css/parser/CSSParser.h"
     33 #include "core/frame/UseCounter.h"
     34 #include "wtf/text/StringBuilder.h"
     35 
     36 namespace blink {
     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     RefPtrWillBeRawPtr<StyleKeyframe> keyframe = CSSParser::parseKeyframeRule(context, styleSheet ? styleSheet->contents() : 0, ruleText);
    128     if (!keyframe)
    129         return;
    130 
    131     CSSStyleSheet::RuleMutationScope mutationScope(this);
    132 
    133     m_keyframesRule->wrapperAppendKeyframe(keyframe);
    134 
    135     m_childRuleCSSOMWrappers.grow(length());
    136 }
    137 
    138 void CSSKeyframesRule::deleteRule(const String& s)
    139 {
    140     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
    141 
    142     int i = m_keyframesRule->findKeyframeIndex(s);
    143     if (i < 0)
    144         return;
    145 
    146     CSSStyleSheet::RuleMutationScope mutationScope(this);
    147 
    148     m_keyframesRule->wrapperRemoveKeyframe(i);
    149 
    150     if (m_childRuleCSSOMWrappers[i])
    151         m_childRuleCSSOMWrappers[i]->setParentRule(0);
    152     m_childRuleCSSOMWrappers.remove(i);
    153 }
    154 
    155 CSSKeyframeRule* CSSKeyframesRule::findRule(const String& s)
    156 {
    157     int i = m_keyframesRule->findKeyframeIndex(s);
    158     return (i >= 0) ? item(i) : 0;
    159 }
    160 
    161 String CSSKeyframesRule::cssText() const
    162 {
    163     StringBuilder result;
    164     if (isVendorPrefixed())
    165         result.appendLiteral("@-webkit-keyframes ");
    166     else
    167         result.appendLiteral("@keyframes ");
    168     result.append(name());
    169     result.appendLiteral(" { \n");
    170 
    171     unsigned size = length();
    172     for (unsigned i = 0; i < size; ++i) {
    173         result.appendLiteral("  ");
    174         result.append(m_keyframesRule->keyframes()[i]->cssText());
    175         result.append('\n');
    176     }
    177     result.append('}');
    178     return result.toString();
    179 }
    180 
    181 unsigned CSSKeyframesRule::length() const
    182 {
    183     return m_keyframesRule->keyframes().size();
    184 }
    185 
    186 CSSKeyframeRule* CSSKeyframesRule::item(unsigned index) const
    187 {
    188     if (index >= length())
    189         return 0;
    190 
    191     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
    192     RefPtrWillBeMember<CSSKeyframeRule>& rule = m_childRuleCSSOMWrappers[index];
    193     if (!rule)
    194         rule = adoptRefWillBeNoop(new CSSKeyframeRule(m_keyframesRule->keyframes()[index].get(), const_cast<CSSKeyframesRule*>(this)));
    195 
    196     return rule.get();
    197 }
    198 
    199 CSSRuleList* CSSKeyframesRule::cssRules()
    200 {
    201     if (!m_ruleListCSSOMWrapper)
    202         m_ruleListCSSOMWrapper = LiveCSSRuleList<CSSKeyframesRule>::create(this);
    203     return m_ruleListCSSOMWrapper.get();
    204 }
    205 
    206 void CSSKeyframesRule::reattach(StyleRuleBase* rule)
    207 {
    208     ASSERT(rule);
    209     m_keyframesRule = toStyleRuleKeyframes(rule);
    210 }
    211 
    212 void CSSKeyframesRule::trace(Visitor* visitor)
    213 {
    214     CSSRule::trace(visitor);
    215 #if ENABLE(OILPAN)
    216     visitor->trace(m_childRuleCSSOMWrappers);
    217 #endif
    218     visitor->trace(m_keyframesRule);
    219     visitor->trace(m_ruleListCSSOMWrapper);
    220 }
    221 
    222 } // namespace blink
    223