Home | History | Annotate | Download | only in resolver
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) 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 }
    212