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 |