2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
11 * Copyright (C) 2012 Google Inc. All rights reserved.
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Library General Public License for more details.
23 * You should have received a copy of the GNU Library General Public License
24 * along with this library; see the file COPYING.LIB. If not, write to
25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 * Boston, MA 02110-1301, USA.
30 #include "core/css/resolver/FilterOperationResolver.h"
32 #include "core/css/CSSFilterValue.h"
33 #include "core/css/parser/BisonCSSParser.h"
34 #include "core/css/CSSPrimitiveValueMappings.h"
35 #include "core/css/CSSShadowValue.h"
36 #include "core/css/resolver/TransformBuilder.h"
37 #include "core/rendering/svg/ReferenceFilterBuilder.h"
38 #include "core/svg/SVGURIReference.h"
42 static FilterOperation::OperationType filterOperationForType(CSSFilterValue::FilterOperationType type)
45 case CSSFilterValue::ReferenceFilterOperation:
46 return FilterOperation::REFERENCE;
47 case CSSFilterValue::GrayscaleFilterOperation:
48 return FilterOperation::GRAYSCALE;
49 case CSSFilterValue::SepiaFilterOperation:
50 return FilterOperation::SEPIA;
51 case CSSFilterValue::SaturateFilterOperation:
52 return FilterOperation::SATURATE;
53 case CSSFilterValue::HueRotateFilterOperation:
54 return FilterOperation::HUE_ROTATE;
55 case CSSFilterValue::InvertFilterOperation:
56 return FilterOperation::INVERT;
57 case CSSFilterValue::OpacityFilterOperation:
58 return FilterOperation::OPACITY;
59 case CSSFilterValue::BrightnessFilterOperation:
60 return FilterOperation::BRIGHTNESS;
61 case CSSFilterValue::ContrastFilterOperation:
62 return FilterOperation::CONTRAST;
63 case CSSFilterValue::BlurFilterOperation:
64 return FilterOperation::BLUR;
65 case CSSFilterValue::DropShadowFilterOperation:
66 return FilterOperation::DROP_SHADOW;
67 case CSSFilterValue::UnknownFilterOperation:
68 return FilterOperation::NONE;
70 return FilterOperation::NONE;
73 bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const CSSToLengthConversionData& unadjustedConversionData, FilterOperations& outOperations, StyleResolverState& state)
75 ASSERT(outOperations.isEmpty());
80 if (inValue->isPrimitiveValue()) {
81 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inValue);
82 if (primitiveValue->getValueID() == CSSValueNone)
86 if (!inValue->isValueList())
89 float zoomFactor = unadjustedConversionData.zoom();
90 const CSSToLengthConversionData& conversionData = unadjustedConversionData.copyWithAdjustedZoom(zoomFactor);
91 FilterOperations operations;
92 for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) {
93 CSSValue* currValue = i.value();
94 if (!currValue->isFilterValue())
97 CSSFilterValue* filterValue = toCSSFilterValue(i.value());
98 FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType());
100 if (operationType == FilterOperation::REFERENCE) {
101 if (filterValue->length() != 1)
103 CSSValue* argument = filterValue->item(0);
105 if (!argument->isSVGDocumentValue())
108 CSSSVGDocumentValue* svgDocumentValue = toCSSSVGDocumentValue(argument);
109 KURL url = state.document().completeURL(svgDocumentValue->url());
111 RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(svgDocumentValue->url(), AtomicString(url.fragmentIdentifier()));
112 if (SVGURIReference::isExternalURIReference(svgDocumentValue->url(), state.document())) {
113 if (!svgDocumentValue->loadRequested())
114 state.elementStyleResources().addPendingSVGDocument(operation.get(), svgDocumentValue);
115 else if (svgDocumentValue->cachedSVGDocument())
116 ReferenceFilterBuilder::setDocumentResourceReference(operation.get(), adoptPtr(new DocumentResourceReference(svgDocumentValue->cachedSVGDocument())));
118 operations.operations().append(operation);
122 // Check that all parameters are primitive values, with the
123 // exception of drop shadow which has a CSSShadowValue parameter.
124 if (operationType != FilterOperation::DROP_SHADOW) {
125 bool haveNonPrimitiveValue = false;
126 for (unsigned j = 0; j < filterValue->length(); ++j) {
127 if (!filterValue->item(j)->isPrimitiveValue()) {
128 haveNonPrimitiveValue = true;
132 if (haveNonPrimitiveValue)
136 CSSPrimitiveValue* firstValue = filterValue->length() && filterValue->item(0)->isPrimitiveValue() ? toCSSPrimitiveValue(filterValue->item(0)) : 0;
137 switch (filterValue->operationType()) {
138 case CSSFilterValue::GrayscaleFilterOperation:
139 case CSSFilterValue::SepiaFilterOperation:
140 case CSSFilterValue::SaturateFilterOperation: {
142 if (filterValue->length() == 1) {
143 amount = firstValue->getDoubleValue();
144 if (firstValue->isPercentage())
148 operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType));
151 case CSSFilterValue::HueRotateFilterOperation: {
153 if (filterValue->length() == 1)
154 angle = firstValue->computeDegrees();
156 operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType));
159 case CSSFilterValue::InvertFilterOperation:
160 case CSSFilterValue::BrightnessFilterOperation:
161 case CSSFilterValue::ContrastFilterOperation:
162 case CSSFilterValue::OpacityFilterOperation: {
163 double amount = (filterValue->operationType() == CSSFilterValue::BrightnessFilterOperation) ? 0 : 1;
164 if (filterValue->length() == 1) {
165 amount = firstValue->getDoubleValue();
166 if (firstValue->isPercentage())
170 operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType));
173 case CSSFilterValue::BlurFilterOperation: {
174 Length stdDeviation = Length(0, Fixed);
175 if (filterValue->length() >= 1)
176 stdDeviation = firstValue->convertToLength<FixedConversion | PercentConversion>(conversionData);
177 operations.operations().append(BlurFilterOperation::create(stdDeviation));
180 case CSSFilterValue::DropShadowFilterOperation: {
181 if (filterValue->length() != 1)
184 CSSValue* cssValue = filterValue->item(0);
185 if (!cssValue->isShadowValue())
188 CSSShadowValue* item = toCSSShadowValue(cssValue);
189 IntPoint location(item->x->computeLength<int>(conversionData), item->y->computeLength<int>(conversionData));
190 int blur = item->blur ? item->blur->computeLength<int>(conversionData) : 0;
191 Color shadowColor = Color::transparent;
193 shadowColor = state.document().textLinkColors().colorFromPrimitiveValue(item->color.get(), state.style()->color());
195 operations.operations().append(DropShadowFilterOperation::create(location, blur, shadowColor));
198 case CSSFilterValue::UnknownFilterOperation:
200 ASSERT_NOT_REACHED();
205 outOperations = operations;