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 blink {
44
45 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ViewportStyleResolver);
46
ViewportStyleResolver(Document * document)47 ViewportStyleResolver::ViewportStyleResolver(Document* document)
48 : m_document(document)
49 , m_hasAuthorStyle(false)
50 {
51 ASSERT(m_document);
52 }
53
collectViewportRules(RuleSet * rules,Origin origin)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
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
resolve()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
viewportArgumentValue(CSSPropertyID id) const113 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
viewportLengthValue(CSSPropertyID id) const166 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
trace(Visitor * visitor)200 void ViewportStyleResolver::trace(Visitor* visitor)
201 {
202 visitor->trace(m_propertySet);
203 visitor->trace(m_document);
204 }
205
206 } // namespace blink
207