Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Apple Inc. All rights reserved. | 2 * Copyright (C) 2013 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2013 Google Inc. All rights reserved. | 3 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 */ | 30 */ |
| 31 | 31 |
| 32 #include "config.h" | 32 #include "config.h" |
| 33 #include "core/html/parser/HTMLSrcsetParser.h" | 33 #include "core/html/parser/HTMLSrcsetParser.h" |
| 34 | 34 |
| 35 #include "core/dom/Document.h" | |
| 36 #include "core/frame/FrameConsole.h" | |
| 37 #include "core/frame/LocalFrame.h" | |
| 38 #include "core/frame/UseCounter.h" | |
| 35 #include "core/html/parser/HTMLParserIdioms.h" | 39 #include "core/html/parser/HTMLParserIdioms.h" |
| 40 #include "core/inspector/ConsoleMessage.h" | |
| 36 #include "platform/ParsingUtilities.h" | 41 #include "platform/ParsingUtilities.h" |
| 37 #include "platform/RuntimeEnabledFeatures.h" | 42 #include "platform/RuntimeEnabledFeatures.h" |
| 38 | 43 |
| 39 namespace blink { | 44 namespace blink { |
| 40 | 45 |
| 41 static bool compareByDensity(const ImageCandidate& first, const ImageCandidate& second) | 46 static bool compareByDensity(const ImageCandidate& first, const ImageCandidate& second) |
| 42 { | 47 { |
| 43 return first.density() < second.density(); | 48 return first.density() < second.density(); |
| 44 } | 49 } |
| 45 | 50 |
| 46 enum DescriptorTokenizerState { | 51 enum DescriptorTokenizerState { |
| 47 Start, | 52 TokenStart, |
| 48 InParenthesis, | 53 InParenthesis, |
| 49 AfterToken, | 54 AfterToken, |
| 50 }; | 55 }; |
| 51 | 56 |
| 52 struct DescriptorToken { | 57 struct DescriptorToken { |
| 53 unsigned start; | 58 unsigned start; |
| 54 unsigned length; | 59 unsigned length; |
| 55 | 60 |
| 56 DescriptorToken(unsigned start, unsigned length) | 61 DescriptorToken(unsigned start, unsigned length) |
| 57 : start(start) | 62 : start(start) |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 { | 122 { |
| 118 return position >= end; | 123 return position >= end; |
| 119 } | 124 } |
| 120 | 125 |
| 121 template<typename CharType> | 126 template<typename CharType> |
| 122 static void tokenizeDescriptors(const CharType* attributeStart, | 127 static void tokenizeDescriptors(const CharType* attributeStart, |
| 123 const CharType*& position, | 128 const CharType*& position, |
| 124 const CharType* attributeEnd, | 129 const CharType* attributeEnd, |
| 125 Vector<DescriptorToken>& descriptors) | 130 Vector<DescriptorToken>& descriptors) |
| 126 { | 131 { |
| 127 DescriptorTokenizerState state = Start; | 132 DescriptorTokenizerState state = TokenStart; |
| 128 const CharType* descriptorsStart = position; | 133 const CharType* descriptorsStart = position; |
| 129 const CharType* currentDescriptorStart = descriptorsStart; | 134 const CharType* currentDescriptorStart = descriptorsStart; |
| 130 while (true) { | 135 while (true) { |
| 131 switch (state) { | 136 switch (state) { |
| 132 case Start: | 137 case TokenStart: |
| 133 if (isEOF(position, attributeEnd)) { | 138 if (isEOF(position, attributeEnd)) { |
| 134 appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors); | 139 appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors); |
| 135 return; | 140 return; |
| 136 } | 141 } |
| 137 if (isComma(*position)) { | 142 if (isComma(*position)) { |
| 138 appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors); | 143 appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors); |
| 139 ++position; | 144 ++position; |
| 140 return; | 145 return; |
| 141 } | 146 } |
| 142 if (isHTMLSpace(*position)) { | 147 if (isHTMLSpace(*position)) { |
| 143 appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors); | 148 appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors); |
| 144 currentDescriptorStart = position + 1; | 149 currentDescriptorStart = position + 1; |
| 145 state = AfterToken; | 150 state = AfterToken; |
| 146 } else if (*position == '(') { | 151 } else if (*position == '(') { |
| 147 appendCharacter(currentDescriptorStart, position); | 152 appendCharacter(currentDescriptorStart, position); |
| 148 state = InParenthesis; | 153 state = InParenthesis; |
| 149 } else { | 154 } else { |
| 150 appendCharacter(currentDescriptorStart, position); | 155 appendCharacter(currentDescriptorStart, position); |
| 151 } | 156 } |
| 152 break; | 157 break; |
| 153 case InParenthesis: | 158 case InParenthesis: |
| 154 if (isEOF(position, attributeEnd)) { | 159 if (isEOF(position, attributeEnd)) { |
| 155 appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors); | 160 appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors); |
| 156 return; | 161 return; |
| 157 } | 162 } |
| 158 if (*position == ')') { | 163 if (*position == ')') { |
| 159 appendCharacter(currentDescriptorStart, position); | 164 appendCharacter(currentDescriptorStart, position); |
| 160 state = Start; | 165 state = TokenStart; |
| 161 } else { | 166 } else { |
| 162 appendCharacter(currentDescriptorStart, position); | 167 appendCharacter(currentDescriptorStart, position); |
| 163 } | 168 } |
| 164 break; | 169 break; |
| 165 case AfterToken: | 170 case AfterToken: |
| 166 if (isEOF(position, attributeEnd)) | 171 if (isEOF(position, attributeEnd)) |
| 167 return; | 172 return; |
| 168 if (!isHTMLSpace(*position)) { | 173 if (!isHTMLSpace(*position)) { |
| 169 state = Start; | 174 state = TokenStart; |
| 170 currentDescriptorStart = position; | 175 currentDescriptorStart = position; |
| 171 --position; | 176 --position; |
| 172 } | 177 } |
| 173 break; | 178 break; |
| 174 } | 179 } |
| 175 ++position; | 180 ++position; |
| 176 } | 181 } |
| 177 } | 182 } |
| 178 | 183 |
| 184 static void srcsetError(Document* document, String message) | |
| 185 { | |
| 186 if (document && document->frame()) { | |
| 187 StringBuilder errorMessage; | |
|
Mike West
2014/10/21 09:36:25
StringBuilder is probably overkill here. '+' would
| |
| 188 errorMessage.append("Failed parsing 'srcset' attribute value since "); | |
| 189 errorMessage.append(message); | |
| 190 document->frame()->console().addMessage(ConsoleMessage::create(OtherMess ageSource, ErrorMessageLevel, errorMessage.toString())); | |
| 191 } | |
| 192 } | |
| 193 | |
| 179 template<typename CharType> | 194 template<typename CharType> |
| 180 static bool parseDescriptors(const CharType* attribute, Vector<DescriptorToken>& descriptors, DescriptorParsingResult& result) | 195 static bool parseDescriptors(const CharType* attribute, Vector<DescriptorToken>& descriptors, DescriptorParsingResult& result, Document* document) |
| 181 { | 196 { |
| 182 for (Vector<DescriptorToken>::iterator it = descriptors.begin(); it != descr iptors.end(); ++it) { | 197 for (Vector<DescriptorToken>::iterator it = descriptors.begin(); it != descr iptors.end(); ++it) { |
| 183 if (it->length == 0) | 198 if (it->length == 0) |
| 184 continue; | 199 continue; |
| 185 CharType c = attribute[it->lastIndex()]; | 200 CharType c = attribute[it->lastIndex()]; |
| 186 bool isValid = false; | 201 bool isValid = false; |
| 187 if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'w') { | 202 if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'w') { |
| 188 if (result.hasDensity() || result.hasWidth()) | 203 if (result.hasDensity() || result.hasWidth()) { |
| 204 srcsetError(document, "it has multiple 'w' descriptors or a mix of 'x' and 'w' descriptors."); | |
| 189 return false; | 205 return false; |
| 206 } | |
| 190 int resourceWidth = it->toInt(attribute, isValid); | 207 int resourceWidth = it->toInt(attribute, isValid); |
| 191 if (!isValid || resourceWidth <= 0) | 208 if (!isValid || resourceWidth <= 0) { |
| 209 srcsetError(document, "its 'w' descriptor is invalid."); | |
| 192 return false; | 210 return false; |
| 211 } | |
| 193 result.setResourceWidth(resourceWidth); | 212 result.setResourceWidth(resourceWidth); |
| 194 } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'h') { | 213 } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'h') { |
| 195 // This is here only for future compat purposes. | 214 // This is here only for future compat purposes. |
| 196 // The value of the 'h' descriptor is not used. | 215 // The value of the 'h' descriptor is not used. |
| 197 if (result.hasDensity() || result.hasHeight()) | 216 if (result.hasDensity() || result.hasHeight()) { |
| 217 srcsetError(document, "it has multiple 'h' descriptors or a mix of 'x' and 'h' descriptors."); | |
| 198 return false; | 218 return false; |
| 219 } | |
| 199 int resourceHeight = it->toInt(attribute, isValid); | 220 int resourceHeight = it->toInt(attribute, isValid); |
| 200 if (!isValid || resourceHeight <= 0) | 221 if (!isValid || resourceHeight <= 0) { |
| 222 srcsetError(document, "its 'h' descriptor is invalid."); | |
| 201 return false; | 223 return false; |
| 224 } | |
| 202 result.setResourceHeight(resourceHeight); | 225 result.setResourceHeight(resourceHeight); |
| 203 } else if (c == 'x') { | 226 } else if (c == 'x') { |
| 204 if (result.hasDensity() || result.hasHeight() || result.hasWidth()) | 227 if (result.hasDensity() || result.hasHeight() || result.hasWidth()) { |
| 228 srcsetError(document, "it has multiple 'x' descriptors or a mix of 'x' and 'w'/'h' descriptors."); | |
| 205 return false; | 229 return false; |
| 230 } | |
| 206 float density = it->toFloat(attribute, isValid); | 231 float density = it->toFloat(attribute, isValid); |
| 207 if (!isValid || density < 0) | 232 if (!isValid || density < 0) { |
| 233 srcsetError(document, "its 'x' descriptor is invalid."); | |
| 208 return false; | 234 return false; |
| 235 } | |
| 209 result.setDensity(density); | 236 result.setDensity(density); |
| 210 } else { | 237 } else { |
| 238 srcsetError(document, "it has an unknown descriptor."); | |
| 211 return false; | 239 return false; |
| 212 } | 240 } |
| 213 } | 241 } |
| 214 return (!result.hasHeight() || result.hasWidth()); | 242 bool res = !result.hasHeight() || result.hasWidth(); |
| 243 if (!res) | |
| 244 srcsetError(document, "it has an 'h' descriptor and no 'w' descriptor.") ; | |
| 245 return res; | |
| 215 } | 246 } |
| 216 | 247 |
| 217 static bool parseDescriptors(const String& attribute, Vector<DescriptorToken>& d escriptors, DescriptorParsingResult& result) | 248 static bool parseDescriptors(const String& attribute, Vector<DescriptorToken>& d escriptors, DescriptorParsingResult& result, Document* document) |
| 218 { | 249 { |
| 219 // FIXME: See if StringView can't be extended to replace DescriptorToken her e. | 250 // FIXME: See if StringView can't be extended to replace DescriptorToken her e. |
| 220 if (attribute.is8Bit()) { | 251 if (attribute.is8Bit()) { |
| 221 return parseDescriptors(attribute.characters8(), descriptors, result); | 252 return parseDescriptors(attribute.characters8(), descriptors, result, do cument); |
| 222 } | 253 } |
| 223 return parseDescriptors(attribute.characters16(), descriptors, result); | 254 return parseDescriptors(attribute.characters16(), descriptors, result, docum ent); |
| 224 } | 255 } |
| 225 | 256 |
| 226 // http://picture.responsiveimages.org/#parse-srcset-attr | 257 // http://picture.responsiveimages.org/#parse-srcset-attr |
| 227 template<typename CharType> | 258 template<typename CharType> |
| 228 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con st CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandi dates) | 259 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con st CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandi dates, Document* document) |
| 229 { | 260 { |
| 230 const CharType* position = attributeStart; | 261 const CharType* position = attributeStart; |
| 231 const CharType* attributeEnd = position + length; | 262 const CharType* attributeEnd = position + length; |
| 232 | 263 |
| 233 while (position < attributeEnd) { | 264 while (position < attributeEnd) { |
| 234 // 4. Splitting loop: Collect a sequence of characters that are space ch aracters or U+002C COMMA characters. | 265 // 4. Splitting loop: Collect a sequence of characters that are space ch aracters or U+002C COMMA characters. |
| 235 skipWhile<CharType, isHTMLSpaceOrComma<CharType> >(position, attributeEn d); | 266 skipWhile<CharType, isHTMLSpaceOrComma<CharType> >(position, attributeEn d); |
| 236 if (position == attributeEnd) { | 267 if (position == attributeEnd) { |
| 237 // Contrary to spec language - descriptor parsing happens on each ca ndidate, so when we reach the attributeEnd, we can exit. | 268 // Contrary to spec language - descriptor parsing happens on each ca ndidate, so when we reach the attributeEnd, we can exit. |
| 238 break; | 269 break; |
| 239 } | 270 } |
| 240 const CharType* imageURLStart = position; | 271 const CharType* imageURLStart = position; |
| 272 | |
| 241 // 6. Collect a sequence of characters that are not space characters, an d let that be url. | 273 // 6. Collect a sequence of characters that are not space characters, an d let that be url. |
| 242 | |
| 243 skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd); | 274 skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd); |
| 244 const CharType* imageURLEnd = position; | 275 const CharType* imageURLEnd = position; |
| 245 | 276 |
| 246 DescriptorParsingResult result; | 277 DescriptorParsingResult result; |
| 247 | 278 |
| 248 // 8. If url ends with a U+002C COMMA character (,) | 279 // 8. If url ends with a U+002C COMMA character (,) |
| 249 if (isComma(*(position - 1))) { | 280 if (isComma(*(position - 1))) { |
| 250 // Remove all trailing U+002C COMMA characters from url. | 281 // Remove all trailing U+002C COMMA characters from url. |
| 251 imageURLEnd = position - 1; | 282 imageURLEnd = position - 1; |
| 252 reverseSkipWhile<CharType, isComma>(imageURLEnd, imageURLStart); | 283 reverseSkipWhile<CharType, isComma>(imageURLEnd, imageURLStart); |
| 253 ++imageURLEnd; | 284 ++imageURLEnd; |
| 254 // If url is empty, then jump to the step labeled splitting loop. | 285 // If url is empty, then jump to the step labeled splitting loop. |
| 255 if (imageURLStart == imageURLEnd) | 286 if (imageURLStart == imageURLEnd) |
| 256 continue; | 287 continue; |
| 257 } else { | 288 } else { |
| 258 // Advancing position here (contrary to spec) to avoid an useless ex tra state machine step. | 289 skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd); |
| 259 // Filed a spec bug: https://github.com/ResponsiveImagesCG/picture-e lement/issues/189 | |
| 260 ++position; | |
| 261 Vector<DescriptorToken> descriptorTokens; | 290 Vector<DescriptorToken> descriptorTokens; |
| 262 tokenizeDescriptors(attributeStart, position, attributeEnd, descript orTokens); | 291 tokenizeDescriptors(attributeStart, position, attributeEnd, descript orTokens); |
| 263 // Contrary to spec language - descriptor parsing happens on each ca ndidate. | 292 // Contrary to spec language - descriptor parsing happens on each ca ndidate. |
| 264 // This is a black-box equivalent, to avoid storing descriptor lists for each candidate. | 293 // This is a black-box equivalent, to avoid storing descriptor lists for each candidate. |
| 265 if (!parseDescriptors(attribute, descriptorTokens, result)) | 294 if (!parseDescriptors(attribute, descriptorTokens, result, document) ) { |
| 295 if (document) { | |
| 296 UseCounter::count(document, UseCounter::SrcsetDroppedCandida te); | |
| 297 if (document->frame()) | |
| 298 document->frame()->console().addMessage(ConsoleMessage:: create(OtherMessageSource, ErrorMessageLevel, String("Dropped srcset candidate " ) + String(imageURLStart, imageURLEnd - imageURLStart))); | |
| 299 } | |
| 266 continue; | 300 continue; |
| 301 } | |
| 267 } | 302 } |
| 268 | 303 |
| 269 ASSERT(imageURLEnd > attributeStart); | 304 ASSERT(imageURLEnd > attributeStart); |
| 270 unsigned imageURLStartingPosition = imageURLStart - attributeStart; | 305 unsigned imageURLStartingPosition = imageURLStart - attributeStart; |
| 271 ASSERT(imageURLEnd > imageURLStart); | 306 ASSERT(imageURLEnd > imageURLStart); |
| 272 unsigned imageURLLength = imageURLEnd - imageURLStart; | 307 unsigned imageURLLength = imageURLEnd - imageURLStart; |
| 273 imageCandidates.append(ImageCandidate(attribute, imageURLStartingPositio n, imageURLLength, result, ImageCandidate::SrcsetOrigin)); | 308 imageCandidates.append(ImageCandidate(attribute, imageURLStartingPositio n, imageURLLength, result, ImageCandidate::SrcsetOrigin)); |
| 274 // 11. Return to the step labeled splitting loop. | 309 // 11. Return to the step labeled splitting loop. |
| 275 } | 310 } |
| 276 } | 311 } |
| 277 | 312 |
| 278 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec tor<ImageCandidate>& imageCandidates) | 313 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec tor<ImageCandidate>& imageCandidates, Document* document) |
| 279 { | 314 { |
| 280 if (attribute.isNull()) | 315 if (attribute.isNull()) |
| 281 return; | 316 return; |
| 282 | 317 |
| 283 if (attribute.is8Bit()) | 318 if (attribute.is8Bit()) |
| 284 parseImageCandidatesFromSrcsetAttribute<LChar>(attribute, attribute.char acters8(), attribute.length(), imageCandidates); | 319 parseImageCandidatesFromSrcsetAttribute<LChar>(attribute, attribute.char acters8(), attribute.length(), imageCandidates, document); |
| 285 else | 320 else |
| 286 parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.char acters16(), attribute.length(), imageCandidates); | 321 parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.char acters16(), attribute.length(), imageCandidates, document); |
| 287 } | 322 } |
| 288 | 323 |
| 289 static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, float sour ceSize, Vector<ImageCandidate>& imageCandidates) | 324 static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, float sour ceSize, Vector<ImageCandidate>& imageCandidates) |
| 290 { | 325 { |
| 291 const float defaultDensityValue = 1.0; | 326 const float defaultDensityValue = 1.0; |
| 292 bool ignoreSrc = false; | 327 bool ignoreSrc = false; |
| 293 if (imageCandidates.isEmpty()) | 328 if (imageCandidates.isEmpty()) |
| 294 return ImageCandidate(); | 329 return ImageCandidate(); |
| 295 | 330 |
| 296 // http://picture.responsiveimages.org/#normalize-source-densities | 331 // http://picture.responsiveimages.org/#normalize-source-densities |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 319 | 354 |
| 320 unsigned winner = i; | 355 unsigned winner = i; |
| 321 // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates, | 356 // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates, |
| 322 // then remove entry b | 357 // then remove entry b |
| 323 while ((i > 0) && (imageCandidates[--i].density() == winningDensity)) | 358 while ((i > 0) && (imageCandidates[--i].density() == winningDensity)) |
| 324 winner = i; | 359 winner = i; |
| 325 | 360 |
| 326 return imageCandidates[winner]; | 361 return imageCandidates[winner]; |
| 327 } | 362 } |
| 328 | 363 |
| 329 ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, float so urceSize, const String& srcsetAttribute) | 364 ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, float so urceSize, const String& srcsetAttribute, Document* document) |
| 330 { | 365 { |
| 331 Vector<ImageCandidate> imageCandidates; | 366 Vector<ImageCandidate> imageCandidates; |
| 332 | 367 |
| 333 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); | 368 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates, do cument); |
| 334 | 369 |
| 335 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ); | 370 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ); |
| 336 } | 371 } |
| 337 | 372 |
| 338 ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, float so urceSize, const String& srcAttribute, const String& srcsetAttribute) | 373 ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, float so urceSize, const String& srcAttribute, const String& srcsetAttribute, Document* d ocument) |
| 339 { | 374 { |
| 340 if (srcsetAttribute.isNull()) { | 375 if (srcsetAttribute.isNull()) { |
| 341 if (srcAttribute.isNull()) | 376 if (srcAttribute.isNull()) |
| 342 return ImageCandidate(); | 377 return ImageCandidate(); |
| 343 return ImageCandidate(srcAttribute, 0, srcAttribute.length(), Descriptor ParsingResult(), ImageCandidate::SrcOrigin); | 378 return ImageCandidate(srcAttribute, 0, srcAttribute.length(), Descriptor ParsingResult(), ImageCandidate::SrcOrigin); |
| 344 } | 379 } |
| 345 | 380 |
| 346 Vector<ImageCandidate> imageCandidates; | 381 Vector<ImageCandidate> imageCandidates; |
| 347 | 382 |
| 348 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); | 383 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates, do cument); |
| 349 | 384 |
| 350 if (!srcAttribute.isEmpty()) | 385 if (!srcAttribute.isEmpty()) |
| 351 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); | 386 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); |
| 352 | 387 |
| 353 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ); | 388 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ); |
| 354 } | 389 } |
| 355 | 390 |
| 356 String bestFitSourceForImageAttributes(float deviceScaleFactor, float sourceSize , const String& srcAttribute, ImageCandidate& srcsetImageCandidate) | 391 String bestFitSourceForImageAttributes(float deviceScaleFactor, float sourceSize , const String& srcAttribute, ImageCandidate& srcsetImageCandidate) |
| 357 { | 392 { |
| 358 if (srcsetImageCandidate.isEmpty()) | 393 if (srcsetImageCandidate.isEmpty()) |
| 359 return srcAttribute; | 394 return srcAttribute; |
| 360 | 395 |
| 361 Vector<ImageCandidate> imageCandidates; | 396 Vector<ImageCandidate> imageCandidates; |
| 362 imageCandidates.append(srcsetImageCandidate); | 397 imageCandidates.append(srcsetImageCandidate); |
| 363 | 398 |
| 364 if (!srcAttribute.isEmpty()) | 399 if (!srcAttribute.isEmpty()) |
| 365 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); | 400 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); |
| 366 | 401 |
| 367 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ).toString(); | 402 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ).toString(); |
| 368 } | 403 } |
| 369 | 404 |
| 370 } | 405 } |
| OLD | NEW |