blob: 012ac3b9796ebc271198f9571e7d5e1d9bf9c4b3 [file] [log] [blame]
/*
* Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "core/css/resolver/ViewportStyleResolver.h"
#include "core/CSSValueKeywords.h"
#include "core/css/CSSDefaultStyleSheets.h"
#include "core/css/CSSPrimitiveValueMappings.h"
#include "core/css/CSSToLengthConversionData.h"
#include "core/css/StylePropertySet.h"
#include "core/css/StyleRule.h"
#include "core/css/resolver/ScopedStyleResolver.h"
#include "core/dom/Document.h"
#include "core/dom/NodeComputedStyle.h"
#include "core/dom/ViewportDescription.h"
#include "core/frame/Settings.h"
#include "core/layout/api/LayoutViewItem.h"
namespace blink {
ViewportStyleResolver::ViewportStyleResolver(Document* document)
: m_document(document), m_hasAuthorStyle(false) {
ASSERT(m_document);
}
void ViewportStyleResolver::collectViewportRules() {
CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
collectViewportRules(defaultStyleSheets.defaultStyle(), UserAgentOrigin);
WebViewportStyle viewportStyle = m_document->settings()
? m_document->settings()->viewportStyle()
: WebViewportStyle::Default;
RuleSet* viewportRules = nullptr;
switch (viewportStyle) {
case WebViewportStyle::Default:
break;
case WebViewportStyle::Mobile:
viewportRules = defaultStyleSheets.defaultMobileViewportStyle();
break;
case WebViewportStyle::Television:
viewportRules = defaultStyleSheets.defaultTelevisionViewportStyle();
break;
}
if (viewportRules)
collectViewportRules(viewportRules, UserAgentOrigin);
if (m_document->isMobileDocument())
collectViewportRules(defaultStyleSheets.defaultXHTMLMobileProfileStyle(),
UserAgentOrigin);
if (ScopedStyleResolver* scopedResolver = m_document->scopedStyleResolver())
scopedResolver->collectViewportRulesTo(this);
resolve();
}
void ViewportStyleResolver::collectViewportRules(RuleSet* rules,
Origin origin) {
rules->compactRulesIfNeeded();
const HeapVector<Member<StyleRuleViewport>>& viewportRules =
rules->viewportRules();
for (size_t i = 0; i < viewportRules.size(); ++i)
addViewportRule(viewportRules[i], origin);
}
void ViewportStyleResolver::addViewportRule(StyleRuleViewport* viewportRule,
Origin origin) {
StylePropertySet& propertySet = viewportRule->mutableProperties();
unsigned propertyCount = propertySet.propertyCount();
if (!propertyCount)
return;
if (origin == AuthorOrigin)
m_hasAuthorStyle = true;
if (!m_propertySet) {
m_propertySet = propertySet.mutableCopy();
return;
}
// We cannot use mergeAndOverrideOnConflict() here because it doesn't
// respect the !important declaration (but addRespectingCascade() does).
for (unsigned i = 0; i < propertyCount; ++i)
m_propertySet->addRespectingCascade(
propertySet.propertyAt(i).toCSSProperty());
}
void ViewportStyleResolver::resolve() {
if (!m_propertySet) {
m_document->setViewportDescription(
ViewportDescription(ViewportDescription::UserAgentStyleSheet));
return;
}
ViewportDescription description(
m_hasAuthorStyle ? ViewportDescription::AuthorStyleSheet
: ViewportDescription::UserAgentStyleSheet);
description.userZoom = viewportArgumentValue(CSSPropertyUserZoom);
description.zoom = viewportArgumentValue(CSSPropertyZoom);
description.minZoom = viewportArgumentValue(CSSPropertyMinZoom);
description.maxZoom = viewportArgumentValue(CSSPropertyMaxZoom);
description.minWidth = viewportLengthValue(CSSPropertyMinWidth);
description.maxWidth = viewportLengthValue(CSSPropertyMaxWidth);
description.minHeight = viewportLengthValue(CSSPropertyMinHeight);
description.maxHeight = viewportLengthValue(CSSPropertyMaxHeight);
description.orientation = viewportArgumentValue(CSSPropertyOrientation);
m_document->setViewportDescription(description);
m_propertySet = nullptr;
m_hasAuthorStyle = false;
}
float ViewportStyleResolver::viewportArgumentValue(CSSPropertyID id) const {
float defaultValue = ViewportDescription::ValueAuto;
// UserZoom default value is CSSValueZoom, which maps to true, meaning that
// yes, it is user scalable. When the value is set to CSSValueFixed, we
// return false.
if (id == CSSPropertyUserZoom)
defaultValue = 1;
const CSSValue* value = m_propertySet->getPropertyCSSValue(id);
if (!value || !(value->isPrimitiveValue() || value->isIdentifierValue()))
return defaultValue;
if (value->isIdentifierValue()) {
switch (toCSSIdentifierValue(value)->getValueID()) {
case CSSValueAuto:
return defaultValue;
case CSSValueLandscape:
return ViewportDescription::ValueLandscape;
case CSSValuePortrait:
return ViewportDescription::ValuePortrait;
case CSSValueZoom:
return defaultValue;
case CSSValueInternalExtendToZoom:
return ViewportDescription::ValueExtendToZoom;
case CSSValueFixed:
return 0;
default:
return defaultValue;
}
}
const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
if (primitiveValue->isNumber() || primitiveValue->isPx())
return primitiveValue->getFloatValue();
if (primitiveValue->isFontRelativeLength())
return primitiveValue->getFloatValue() *
m_document->computedStyle()->getFontDescription().computedSize();
if (primitiveValue->isPercentage()) {
float percentValue = primitiveValue->getFloatValue() / 100.0f;
switch (id) {
case CSSPropertyMaxZoom:
case CSSPropertyMinZoom:
case CSSPropertyZoom:
return percentValue;
default:
NOTREACHED();
break;
}
}
NOTREACHED();
return defaultValue;
}
Length ViewportStyleResolver::viewportLengthValue(CSSPropertyID id) const {
ASSERT(id == CSSPropertyMaxHeight || id == CSSPropertyMinHeight ||
id == CSSPropertyMaxWidth || id == CSSPropertyMinWidth);
const CSSValue* value = m_propertySet->getPropertyCSSValue(id);
if (!value || !(value->isPrimitiveValue() || value->isIdentifierValue()))
return Length(); // auto
if (value->isIdentifierValue()) {
CSSValueID valueID = toCSSIdentifierValue(value)->getValueID();
if (valueID == CSSValueInternalExtendToZoom)
return Length(ExtendToZoom);
if (valueID == CSSValueAuto)
return Length(Auto);
}
const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
ComputedStyle* documentStyle = m_document->mutableComputedStyle();
// If we have viewport units the conversion will mark the document style as
// having viewport units.
bool documentStyleHasViewportUnits = documentStyle->hasViewportUnits();
documentStyle->setHasViewportUnits(false);
CSSToLengthConversionData::FontSizes fontSizes(documentStyle, documentStyle);
CSSToLengthConversionData::ViewportSize viewportSize(
m_document->layoutViewItem());
Length result = primitiveValue->convertToLength(
CSSToLengthConversionData(documentStyle, fontSizes, viewportSize, 1.0f));
if (documentStyle->hasViewportUnits())
m_document->setHasViewportUnits();
documentStyle->setHasViewportUnits(documentStyleHasViewportUnits);
return result;
}
DEFINE_TRACE(ViewportStyleResolver) {
visitor->trace(m_propertySet);
visitor->trace(m_document);
}
} // namespace blink