Home | History | Annotate | Download | only in resolver
      1 /*
      2  * Copyright (C) 2012-2013 Intel Corporation. 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  *
      8  * 1. Redistributions of source code must retain the above
      9  *    copyright notice, this list of conditions and the following
     10  *    disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above
     12  *    copyright notice, this list of conditions and the following
     13  *    disclaimer in the documentation and/or other materials
     14  *    provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AS IS AND ANY
     17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
     20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
     21  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
     25  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
     26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 #include "config.h"
     31 #include "core/css/resolver/ViewportStyleResolver.h"
     32 
     33 #include "core/CSSValueKeywords.h"
     34 #include "core/css/CSSPrimitiveValueMappings.h"
     35 #include "core/css/CSSToLengthConversionData.h"
     36 #include "core/css/StylePropertySet.h"
     37 #include "core/css/StyleRule.h"
     38 #include "core/dom/Document.h"
     39 #include "core/dom/NodeRenderStyle.h"
     40 #include "core/dom/ViewportDescription.h"
     41 #include "core/frame/FrameView.h"
     42 
     43 namespace WebCore {
     44 
     45 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ViewportStyleResolver);
     46 
     47 ViewportStyleResolver::ViewportStyleResolver(Document* document)
     48     : m_document(document)
     49     , m_hasAuthorStyle(false)
     50 {
     51     ASSERT(m_document);
     52 }
     53 
     54 void ViewportStyleResolver::collectViewportRules(RuleSet* rules, Origin origin)
     55 {
     56     rules->compactRulesIfNeeded();
     57 
     58     const WillBeHeapVector<RawPtrWillBeMember<StyleRuleViewport> >& viewportRules = rules->viewportRules();
     59     for (size_t i = 0; i < viewportRules.size(); ++i)
     60         addViewportRule(viewportRules[i], origin);
     61 }
     62 
     63 void ViewportStyleResolver::addViewportRule(StyleRuleViewport* viewportRule, Origin origin)
     64 {
     65     StylePropertySet& propertySet = viewportRule->mutableProperties();
     66 
     67     unsigned propertyCount = propertySet.propertyCount();
     68     if (!propertyCount)
     69         return;
     70 
     71     if (origin == AuthorOrigin)
     72         m_hasAuthorStyle = true;
     73 
     74     if (!m_propertySet) {
     75         m_propertySet = propertySet.mutableCopy();
     76         return;
     77     }
     78 
     79     // We cannot use mergeAndOverrideOnConflict() here because it doesn't
     80     // respect the !important declaration (but addParsedProperty() does).
     81     for (unsigned i = 0; i < propertyCount; ++i)
     82         m_propertySet->addParsedProperty(propertySet.propertyAt(i).toCSSProperty());
     83 }
     84 
     85 void ViewportStyleResolver::resolve()
     86 {
     87     if (!m_document)
     88         return;
     89 
     90     if (!m_propertySet) {
     91         m_document->setViewportDescription(ViewportDescription(ViewportDescription::UserAgentStyleSheet));
     92         return;
     93     }
     94 
     95     ViewportDescription description(m_hasAuthorStyle ? ViewportDescription::AuthorStyleSheet : ViewportDescription::UserAgentStyleSheet);
     96 
     97     description.userZoom = viewportArgumentValue(CSSPropertyUserZoom);
     98     description.zoom = viewportArgumentValue(CSSPropertyZoom);
     99     description.minZoom = viewportArgumentValue(CSSPropertyMinZoom);
    100     description.maxZoom = viewportArgumentValue(CSSPropertyMaxZoom);
    101     description.minWidth = viewportLengthValue(CSSPropertyMinWidth);
    102     description.maxWidth = viewportLengthValue(CSSPropertyMaxWidth);
    103     description.minHeight = viewportLengthValue(CSSPropertyMinHeight);
    104     description.maxHeight = viewportLengthValue(CSSPropertyMaxHeight);
    105     description.orientation = viewportArgumentValue(CSSPropertyOrientation);
    106 
    107     m_document->setViewportDescription(description);
    108 
    109     m_propertySet = nullptr;
    110     m_hasAuthorStyle = false;
    111 }
    112 
    113 float ViewportStyleResolver::viewportArgumentValue(CSSPropertyID id) const
    114 {
    115     float defaultValue = ViewportDescription::ValueAuto;
    116 
    117     // UserZoom default value is CSSValueZoom, which maps to true, meaning that
    118     // yes, it is user scalable. When the value is set to CSSValueFixed, we
    119     // return false.
    120     if (id == CSSPropertyUserZoom)
    121         defaultValue = 1;
    122 
    123     RefPtrWillBeRawPtr<CSSValue> value = m_propertySet->getPropertyCSSValue(id);
    124     if (!value || !value->isPrimitiveValue())
    125         return defaultValue;
    126 
    127     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value.get());
    128 
    129     if (primitiveValue->isNumber() || primitiveValue->isPx())
    130         return primitiveValue->getFloatValue();
    131 
    132     if (primitiveValue->isFontRelativeLength())
    133         return primitiveValue->getFloatValue() * m_document->renderStyle()->fontDescription().computedSize();
    134 
    135     if (primitiveValue->isPercentage()) {
    136         float percentValue = primitiveValue->getFloatValue() / 100.0f;
    137         switch (id) {
    138         case CSSPropertyMaxZoom:
    139         case CSSPropertyMinZoom:
    140         case CSSPropertyZoom:
    141             return percentValue;
    142         default:
    143             ASSERT_NOT_REACHED();
    144             break;
    145         }
    146     }
    147 
    148     switch (primitiveValue->getValueID()) {
    149     case CSSValueAuto:
    150         return defaultValue;
    151     case CSSValueLandscape:
    152         return ViewportDescription::ValueLandscape;
    153     case CSSValuePortrait:
    154         return ViewportDescription::ValuePortrait;
    155     case CSSValueZoom:
    156         return defaultValue;
    157     case CSSValueInternalExtendToZoom:
    158         return ViewportDescription::ValueExtendToZoom;
    159     case CSSValueFixed:
    160         return 0;
    161     default:
    162         return defaultValue;
    163     }
    164 }
    165 
    166 Length ViewportStyleResolver::viewportLengthValue(CSSPropertyID id) const
    167 {
    168     ASSERT(id == CSSPropertyMaxHeight
    169         || id == CSSPropertyMinHeight
    170         || id == CSSPropertyMaxWidth
    171         || id == CSSPropertyMinWidth);
    172 
    173     RefPtrWillBeRawPtr<CSSValue> value = m_propertySet->getPropertyCSSValue(id);
    174     if (!value || !value->isPrimitiveValue())
    175         return Length(); // auto
    176 
    177     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value.get());
    178 
    179     if (primitiveValue->getValueID() == CSSValueInternalExtendToZoom)
    180         return Length(ExtendToZoom);
    181 
    182     RenderStyle* documentStyle = m_document->renderStyle();
    183 
    184     // If we have viewport units the conversion will mark the document style as having viewport units.
    185     bool documentStyleHasViewportUnits = documentStyle->hasViewportUnits();
    186     documentStyle->setHasViewportUnits(false);
    187 
    188     FrameView* view = m_document->view();
    189     float width = view ? view->width() : 0;
    190     float height = view ? view->height() : 0;
    191 
    192     Length result = primitiveValue->convertToLength<AnyConversion>(CSSToLengthConversionData(documentStyle, documentStyle, width, height, 1.0f));
    193     if (documentStyle->hasViewportUnits())
    194         m_document->setHasViewportUnits();
    195     documentStyle->setHasViewportUnits(documentStyleHasViewportUnits);
    196 
    197     return result;
    198 }
    199 
    200 void ViewportStyleResolver::trace(Visitor* visitor)
    201 {
    202     visitor->trace(m_propertySet);
    203 }
    204 
    205 } // namespace WebCore
    206