Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / resolver / StyleResourceLoader.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
4  * Copyright (C) 2013 Google Inc. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "core/css/resolver/StyleResourceLoader.h"
25
26 #include "core/CSSPropertyNames.h"
27 #include "core/css/CSSCursorImageValue.h"
28 #include "core/css/CSSImageValue.h"
29 #include "core/css/CSSSVGDocumentValue.h"
30 #include "core/css/resolver/ElementStyleResources.h"
31 #include "core/fetch/ResourceFetcher.h"
32 #include "core/rendering/style/ContentData.h"
33 #include "core/rendering/style/FillLayer.h"
34 #include "core/rendering/style/RenderStyle.h"
35 #include "core/rendering/style/StyleFetchedImage.h"
36 #include "core/rendering/style/StyleFetchedImageSet.h"
37 #include "core/rendering/style/StyleGeneratedImage.h"
38 #include "core/rendering/style/StylePendingImage.h"
39 #include "core/rendering/svg/ReferenceFilterBuilder.h"
40
41 namespace blink {
42
43 StyleResourceLoader::StyleResourceLoader(ResourceFetcher* fetcher)
44     : m_fetcher(fetcher)
45 {
46 }
47
48 void StyleResourceLoader::loadPendingSVGDocuments(RenderStyle* renderStyle, ElementStyleResources& elementStyleResources)
49 {
50     if (!renderStyle->hasFilter() || elementStyleResources.pendingSVGDocuments().isEmpty())
51         return;
52
53     Vector<RefPtr<FilterOperation> >& filterOperations = renderStyle->mutableFilter().operations();
54     for (unsigned i = 0; i < filterOperations.size(); ++i) {
55         RefPtr<FilterOperation> filterOperation = filterOperations.at(i);
56         if (filterOperation->type() == FilterOperation::REFERENCE) {
57             ReferenceFilterOperation* referenceFilter = toReferenceFilterOperation(filterOperation.get());
58
59             CSSSVGDocumentValue* value = elementStyleResources.pendingSVGDocuments().get(referenceFilter);
60             if (!value)
61                 continue;
62             DocumentResource* resource = value->load(m_fetcher);
63             if (!resource)
64                 continue;
65
66             // Stash the DocumentResource on the reference filter.
67             ReferenceFilterBuilder::setDocumentResourceReference(referenceFilter, adoptPtr(new DocumentResourceReference(resource)));
68         }
69     }
70
71     elementStyleResources.clearPendingSVGDocuments();
72 }
73
74 static PassRefPtr<StyleImage> doLoadPendingImage(ResourceFetcher* fetcher, StylePendingImage* pendingImage, float deviceScaleFactor, const ResourceLoaderOptions& options)
75 {
76     if (CSSImageValue* imageValue = pendingImage->cssImageValue())
77         return imageValue->cachedImage(fetcher, options);
78
79     if (CSSImageGeneratorValue* imageGeneratorValue
80         = pendingImage->cssImageGeneratorValue()) {
81         imageGeneratorValue->loadSubimages(fetcher);
82         return StyleGeneratedImage::create(imageGeneratorValue);
83     }
84
85     if (CSSCursorImageValue* cursorImageValue
86         = pendingImage->cssCursorImageValue())
87         return cursorImageValue->cachedImage(fetcher, deviceScaleFactor);
88
89     if (CSSImageSetValue* imageSetValue = pendingImage->cssImageSetValue())
90         return imageSetValue->cachedImageSet(fetcher, deviceScaleFactor, options);
91
92     return nullptr;
93 }
94
95 PassRefPtr<StyleImage> StyleResourceLoader::loadPendingImage(StylePendingImage* pendingImage, float deviceScaleFactor)
96 {
97     return doLoadPendingImage(m_fetcher, pendingImage, deviceScaleFactor, ResourceFetcher::defaultResourceOptions());
98 }
99
100 void StyleResourceLoader::loadPendingShapeImage(RenderStyle* renderStyle, ShapeValue* shapeValue, float deviceScaleFactor)
101 {
102     if (!shapeValue)
103         return;
104
105     StyleImage* image = shapeValue->image();
106     if (!image || !image->isPendingImage())
107         return;
108
109     ResourceLoaderOptions options = ResourceFetcher::defaultResourceOptions();
110     options.allowCredentials = DoNotAllowStoredCredentials;
111     options.credentialsRequested  = ClientDidNotRequestCredentials;
112     options.corsEnabled = IsCORSEnabled;
113
114     shapeValue->setImage(doLoadPendingImage(m_fetcher, toStylePendingImage(image), deviceScaleFactor, options));
115 }
116
117 void StyleResourceLoader::loadPendingImages(RenderStyle* style, ElementStyleResources& elementStyleResources)
118 {
119     if (elementStyleResources.pendingImageProperties().isEmpty())
120         return;
121
122     PendingImagePropertyMap::const_iterator::Keys end = elementStyleResources.pendingImageProperties().end().keys();
123     for (PendingImagePropertyMap::const_iterator::Keys it = elementStyleResources.pendingImageProperties().begin().keys(); it != end; ++it) {
124         CSSPropertyID currentProperty = *it;
125
126         switch (currentProperty) {
127         case CSSPropertyBackgroundImage: {
128             for (FillLayer* backgroundLayer = &style->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
129                 if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage())
130                     backgroundLayer->setImage(loadPendingImage(toStylePendingImage(backgroundLayer->image()), elementStyleResources.deviceScaleFactor()));
131             }
132             break;
133         }
134         case CSSPropertyContent: {
135             for (ContentData* contentData = const_cast<ContentData*>(style->contentData()); contentData; contentData = contentData->next()) {
136                 if (contentData->isImage()) {
137                     StyleImage* image = toImageContentData(contentData)->image();
138                     if (image->isPendingImage()) {
139                         RefPtr<StyleImage> loadedImage = loadPendingImage(toStylePendingImage(image), elementStyleResources.deviceScaleFactor());
140                         if (loadedImage)
141                             toImageContentData(contentData)->setImage(loadedImage.release());
142                     }
143                 }
144             }
145             break;
146         }
147         case CSSPropertyCursor: {
148             if (CursorList* cursorList = style->cursors()) {
149                 for (size_t i = 0; i < cursorList->size(); ++i) {
150                     CursorData& currentCursor = cursorList->at(i);
151                     if (StyleImage* image = currentCursor.image()) {
152                         if (image->isPendingImage())
153                             currentCursor.setImage(loadPendingImage(toStylePendingImage(image), elementStyleResources.deviceScaleFactor()));
154                     }
155                 }
156             }
157             break;
158         }
159         case CSSPropertyListStyleImage: {
160             if (style->listStyleImage() && style->listStyleImage()->isPendingImage())
161                 style->setListStyleImage(loadPendingImage(toStylePendingImage(style->listStyleImage()), elementStyleResources.deviceScaleFactor()));
162             break;
163         }
164         case CSSPropertyBorderImageSource: {
165             if (style->borderImageSource() && style->borderImageSource()->isPendingImage())
166                 style->setBorderImageSource(loadPendingImage(toStylePendingImage(style->borderImageSource()), elementStyleResources.deviceScaleFactor()));
167             break;
168         }
169         case CSSPropertyWebkitBoxReflect: {
170             if (StyleReflection* reflection = style->boxReflect()) {
171                 const NinePieceImage& maskImage = reflection->mask();
172                 if (maskImage.image() && maskImage.image()->isPendingImage()) {
173                     RefPtr<StyleImage> loadedImage = loadPendingImage(toStylePendingImage(maskImage.image()), elementStyleResources.deviceScaleFactor());
174                     reflection->setMask(NinePieceImage(loadedImage.release(), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
175                 }
176             }
177             break;
178         }
179         case CSSPropertyWebkitMaskBoxImageSource: {
180             if (style->maskBoxImageSource() && style->maskBoxImageSource()->isPendingImage())
181                 style->setMaskBoxImageSource(loadPendingImage(toStylePendingImage(style->maskBoxImageSource()), elementStyleResources.deviceScaleFactor()));
182             break;
183         }
184         case CSSPropertyWebkitMaskImage: {
185             for (FillLayer* maskLayer = &style->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
186                 if (maskLayer->image() && maskLayer->image()->isPendingImage())
187                     maskLayer->setImage(loadPendingImage(toStylePendingImage(maskLayer->image()), elementStyleResources.deviceScaleFactor()));
188             }
189             break;
190         }
191         case CSSPropertyShapeOutside:
192             loadPendingShapeImage(style, style->shapeOutside(), elementStyleResources.deviceScaleFactor());
193             break;
194         default:
195             ASSERT_NOT_REACHED();
196         }
197     }
198
199     elementStyleResources.clearPendingImageProperties();
200 }
201
202 void StyleResourceLoader::loadPendingResources(RenderStyle* renderStyle, ElementStyleResources& elementStyleResources)
203 {
204     // Start loading images referenced by this style.
205     loadPendingImages(renderStyle, elementStyleResources);
206
207     // Start loading the SVG Documents referenced by this style.
208     loadPendingSVGDocuments(renderStyle, elementStyleResources);
209 }
210
211 }