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 "CSSValueKeywords.h"
34 #include "core/css/CSSToLengthConversionData.h"
35 #include "core/css/StylePropertySet.h"
36 #include "core/css/StyleRule.h"
37 #include "core/dom/Document.h"
38 #include "core/dom/NodeRenderStyle.h"
39 #include "core/dom/ViewportDescription.h"
40
41 namespace WebCore {
42
ViewportStyleResolver(Document * document)43 ViewportStyleResolver::ViewportStyleResolver(Document* document)
44 : m_document(document),
45 m_hasAuthorStyle(false)
46 {
47 ASSERT(m_document);
48 }
49
~ViewportStyleResolver()50 ViewportStyleResolver::~ViewportStyleResolver()
51 {
52 }
53
collectViewportRules(RuleSet * rules,Origin origin)54 void ViewportStyleResolver::collectViewportRules(RuleSet* rules, Origin origin)
55 {
56 rules->compactRulesIfNeeded();
57
58 const Vector<StyleRuleViewport*>& viewportRules = rules->viewportRules();
59 for (size_t i = 0; i < viewportRules.size(); ++i)
60 addViewportRule(viewportRules[i], origin);
61 }
62
addViewportRule(StyleRuleViewport * viewportRule,Origin origin)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
clearDocument()85 void ViewportStyleResolver::clearDocument()
86 {
87 m_document = 0;
88 }
89
resolve()90 void ViewportStyleResolver::resolve()
91 {
92 if (!m_document)
93 return;
94
95 if (!m_propertySet || (!m_hasAuthorStyle && m_document->hasLegacyViewportTag())) {
96 ASSERT(!m_hasAuthorStyle);
97 m_propertySet = 0;
98 m_document->setViewportDescription(ViewportDescription());
99 return;
100 }
101
102 ViewportDescription description(m_hasAuthorStyle ? ViewportDescription::AuthorStyleSheet : ViewportDescription::UserAgentStyleSheet);
103
104 description.userZoom = viewportArgumentValue(CSSPropertyUserZoom);
105 description.zoom = viewportArgumentValue(CSSPropertyZoom);
106 description.minZoom = viewportArgumentValue(CSSPropertyMinZoom);
107 description.maxZoom = viewportArgumentValue(CSSPropertyMaxZoom);
108 description.minWidth = viewportLengthValue(CSSPropertyMinWidth);
109 description.maxWidth = viewportLengthValue(CSSPropertyMaxWidth);
110 description.minHeight = viewportLengthValue(CSSPropertyMinHeight);
111 description.maxHeight = viewportLengthValue(CSSPropertyMaxHeight);
112 description.orientation = viewportArgumentValue(CSSPropertyOrientation);
113
114 m_document->setViewportDescription(description);
115
116 m_propertySet = 0;
117 m_hasAuthorStyle = false;
118 }
119
viewportArgumentValue(CSSPropertyID id) const120 float ViewportStyleResolver::viewportArgumentValue(CSSPropertyID id) const
121 {
122 float defaultValue = ViewportDescription::ValueAuto;
123
124 // UserZoom default value is CSSValueZoom, which maps to true, meaning that
125 // yes, it is user scalable. When the value is set to CSSValueFixed, we
126 // return false.
127 if (id == CSSPropertyUserZoom)
128 defaultValue = 1;
129
130 RefPtr<CSSValue> value = m_propertySet->getPropertyCSSValue(id);
131 if (!value || !value->isPrimitiveValue())
132 return defaultValue;
133
134 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value.get());
135
136 if (primitiveValue->isNumber() || primitiveValue->isPx())
137 return primitiveValue->getFloatValue();
138
139 if (primitiveValue->isFontRelativeLength())
140 return primitiveValue->getFloatValue() * m_document->renderStyle()->fontDescription().computedSize();
141
142 if (primitiveValue->isPercentage()) {
143 float percentValue = primitiveValue->getFloatValue() / 100.0f;
144 switch (id) {
145 case CSSPropertyMaxZoom:
146 case CSSPropertyMinZoom:
147 case CSSPropertyZoom:
148 return percentValue;
149 default:
150 ASSERT_NOT_REACHED();
151 break;
152 }
153 }
154
155 switch (primitiveValue->getValueID()) {
156 case CSSValueAuto:
157 return defaultValue;
158 case CSSValueLandscape:
159 return ViewportDescription::ValueLandscape;
160 case CSSValuePortrait:
161 return ViewportDescription::ValuePortrait;
162 case CSSValueZoom:
163 return defaultValue;
164 case CSSValueInternalExtendToZoom:
165 return ViewportDescription::ValueExtendToZoom;
166 case CSSValueFixed:
167 return 0;
168 default:
169 return defaultValue;
170 }
171 }
172
viewportLengthValue(CSSPropertyID id) const173 Length ViewportStyleResolver::viewportLengthValue(CSSPropertyID id) const
174 {
175 ASSERT(id == CSSPropertyMaxHeight
176 || id == CSSPropertyMinHeight
177 || id == CSSPropertyMaxWidth
178 || id == CSSPropertyMinWidth);
179
180 RefPtr<CSSValue> value = m_propertySet->getPropertyCSSValue(id);
181 if (!value || !value->isPrimitiveValue())
182 return Length(); // auto
183
184 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value.get());
185
186 if (primitiveValue->isLength())
187 return primitiveValue->computeLength<Length>(CSSToLengthConversionData(m_document->renderStyle(), m_document->renderStyle(), 1.0f));
188
189 if (primitiveValue->isViewportPercentageLength())
190 return primitiveValue->viewportPercentageLength();
191
192 if (primitiveValue->isPercentage())
193 return Length(primitiveValue->getFloatValue(), Percent);
194
195 switch (primitiveValue->getValueID()) {
196 case CSSValueInternalExtendToZoom:
197 return Length(ExtendToZoom);
198 case CSSValueAuto:
199 return Length();
200 default:
201 // Unrecognized keyword.
202 ASSERT_NOT_REACHED();
203 return Length(0, Fixed);
204 }
205 }
206
207 } // namespace WebCore
208