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 consoleMessage(Document* document, String message) |
| 185 { |
| 186 if (document && document->frame()) |
| 187 document->frame()->console().addMessage(ConsoleMessage::create(OtherMess
ageSource, ErrorMessageLevel, message)); |
| 188 } |
| 189 |
179 template<typename CharType> | 190 template<typename CharType> |
180 static bool parseDescriptors(const CharType* attribute, Vector<DescriptorToken>&
descriptors, DescriptorParsingResult& result) | 191 static bool parseDescriptors(const CharType* attribute, Vector<DescriptorToken>&
descriptors, DescriptorParsingResult& result, Document* document) |
181 { | 192 { |
182 for (Vector<DescriptorToken>::iterator it = descriptors.begin(); it != descr
iptors.end(); ++it) { | 193 for (Vector<DescriptorToken>::iterator it = descriptors.begin(); it != descr
iptors.end(); ++it) { |
183 if (it->length == 0) | 194 if (it->length == 0) |
184 continue; | 195 continue; |
185 CharType c = attribute[it->lastIndex()]; | 196 CharType c = attribute[it->lastIndex()]; |
186 bool isValid = false; | 197 bool isValid = false; |
187 if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'w') { | 198 if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'w') { |
188 if (result.hasDensity() || result.hasWidth()) | 199 if (result.hasDensity() || result.hasWidth()) { |
| 200 consoleMessage(document, "srcset has multiple 'w' descriptors or
a mix of 'x' and 'w' descriptors."); |
189 return false; | 201 return false; |
| 202 } |
190 int resourceWidth = it->toInt(attribute, isValid); | 203 int resourceWidth = it->toInt(attribute, isValid); |
191 if (!isValid || resourceWidth <= 0) | 204 if (!isValid || resourceWidth <= 0) { |
| 205 consoleMessage(document, "srcset 'w' descriptor is invalid."); |
192 return false; | 206 return false; |
| 207 } |
193 result.setResourceWidth(resourceWidth); | 208 result.setResourceWidth(resourceWidth); |
194 } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'h') { | 209 } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'h') { |
195 // This is here only for future compat purposes. | 210 // This is here only for future compat purposes. |
196 // The value of the 'h' descriptor is not used. | 211 // The value of the 'h' descriptor is not used. |
197 if (result.hasDensity() || result.hasHeight()) | 212 if (result.hasDensity() || result.hasHeight()) { |
| 213 consoleMessage(document, "srcset has multiple 'h' descriptors or
a mix of 'x' and 'h' descriptors."); |
198 return false; | 214 return false; |
| 215 } |
199 int resourceHeight = it->toInt(attribute, isValid); | 216 int resourceHeight = it->toInt(attribute, isValid); |
200 if (!isValid || resourceHeight <= 0) | 217 if (!isValid || resourceHeight <= 0) { |
| 218 consoleMessage(document, "srcset 'h' descriptor is invalid."); |
201 return false; | 219 return false; |
| 220 } |
202 result.setResourceHeight(resourceHeight); | 221 result.setResourceHeight(resourceHeight); |
203 } else if (c == 'x') { | 222 } else if (c == 'x') { |
204 if (result.hasDensity() || result.hasHeight() || result.hasWidth()) | 223 if (result.hasDensity() || result.hasHeight() || result.hasWidth())
{ |
| 224 consoleMessage(document, "srcset has multiple 'x' descriptors or
a mix of 'x' and 'w'/'h' descriptors."); |
205 return false; | 225 return false; |
| 226 } |
206 float density = it->toFloat(attribute, isValid); | 227 float density = it->toFloat(attribute, isValid); |
207 if (!isValid || density < 0) | 228 if (!isValid || density < 0) { |
| 229 consoleMessage(document, "srcset 'x' descriptor is invalid."); |
208 return false; | 230 return false; |
| 231 } |
209 result.setDensity(density); | 232 result.setDensity(density); |
210 } else { | 233 } else { |
| 234 consoleMessage(document, "srcset has an unknown descriptor."); |
211 return false; | 235 return false; |
212 } | 236 } |
213 } | 237 } |
214 return (!result.hasHeight() || result.hasWidth()); | 238 bool res = !result.hasHeight() || result.hasWidth(); |
| 239 if (!res) |
| 240 consoleMessage(document, "srcset has an 'h' descriptor and no 'w' descri
ptor."); |
| 241 return res; |
215 } | 242 } |
216 | 243 |
217 static bool parseDescriptors(const String& attribute, Vector<DescriptorToken>& d
escriptors, DescriptorParsingResult& result) | 244 static bool parseDescriptors(const String& attribute, Vector<DescriptorToken>& d
escriptors, DescriptorParsingResult& result, Document* document) |
218 { | 245 { |
219 // FIXME: See if StringView can't be extended to replace DescriptorToken her
e. | 246 // FIXME: See if StringView can't be extended to replace DescriptorToken her
e. |
220 if (attribute.is8Bit()) { | 247 if (attribute.is8Bit()) { |
221 return parseDescriptors(attribute.characters8(), descriptors, result); | 248 return parseDescriptors(attribute.characters8(), descriptors, result, do
cument); |
222 } | 249 } |
223 return parseDescriptors(attribute.characters16(), descriptors, result); | 250 return parseDescriptors(attribute.characters16(), descriptors, result, docum
ent); |
224 } | 251 } |
225 | 252 |
226 // http://picture.responsiveimages.org/#parse-srcset-attr | 253 // http://picture.responsiveimages.org/#parse-srcset-attr |
227 template<typename CharType> | 254 template<typename CharType> |
228 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con
st CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandi
dates) | 255 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con
st CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandi
dates, Document* document) |
229 { | 256 { |
230 const CharType* position = attributeStart; | 257 const CharType* position = attributeStart; |
231 const CharType* attributeEnd = position + length; | 258 const CharType* attributeEnd = position + length; |
232 | 259 |
233 while (position < attributeEnd) { | 260 while (position < attributeEnd) { |
234 // 4. Splitting loop: Collect a sequence of characters that are space ch
aracters or U+002C COMMA characters. | 261 // 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); | 262 skipWhile<CharType, isHTMLSpaceOrComma<CharType> >(position, attributeEn
d); |
236 if (position == attributeEnd) { | 263 if (position == attributeEnd) { |
237 // Contrary to spec language - descriptor parsing happens on each ca
ndidate, so when we reach the attributeEnd, we can exit. | 264 // Contrary to spec language - descriptor parsing happens on each ca
ndidate, so when we reach the attributeEnd, we can exit. |
238 break; | 265 break; |
239 } | 266 } |
240 const CharType* imageURLStart = position; | 267 const CharType* imageURLStart = position; |
| 268 |
241 // 6. Collect a sequence of characters that are not space characters, an
d let that be url. | 269 // 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); | 270 skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd); |
244 const CharType* imageURLEnd = position; | 271 const CharType* imageURLEnd = position; |
245 | 272 |
246 DescriptorParsingResult result; | 273 DescriptorParsingResult result; |
247 | 274 |
248 // 8. If url ends with a U+002C COMMA character (,) | 275 // 8. If url ends with a U+002C COMMA character (,) |
249 if (isComma(*(position - 1))) { | 276 if (isComma(*(position - 1))) { |
250 // Remove all trailing U+002C COMMA characters from url. | 277 // Remove all trailing U+002C COMMA characters from url. |
251 imageURLEnd = position - 1; | 278 imageURLEnd = position - 1; |
252 reverseSkipWhile<CharType, isComma>(imageURLEnd, imageURLStart); | 279 reverseSkipWhile<CharType, isComma>(imageURLEnd, imageURLStart); |
253 ++imageURLEnd; | 280 ++imageURLEnd; |
254 // If url is empty, then jump to the step labeled splitting loop. | 281 // If url is empty, then jump to the step labeled splitting loop. |
255 if (imageURLStart == imageURLEnd) | 282 if (imageURLStart == imageURLEnd) |
256 continue; | 283 continue; |
257 } else { | 284 } else { |
258 // Advancing position here (contrary to spec) to avoid an useless ex
tra state machine step. | 285 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; | 286 Vector<DescriptorToken> descriptorTokens; |
262 tokenizeDescriptors(attributeStart, position, attributeEnd, descript
orTokens); | 287 tokenizeDescriptors(attributeStart, position, attributeEnd, descript
orTokens); |
263 // Contrary to spec language - descriptor parsing happens on each ca
ndidate. | 288 // 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. | 289 // This is a black-box equivalent, to avoid storing descriptor lists
for each candidate. |
265 if (!parseDescriptors(attribute, descriptorTokens, result)) | 290 if (!parseDescriptors(attribute, descriptorTokens, result, document)
) { |
| 291 if (document) { |
| 292 UseCounter::count(document, UseCounter::SrcsetDroppedCandida
te); |
| 293 if (document->frame()) |
| 294 document->frame()->console().addMessage(ConsoleMessage::
create(OtherMessageSource, ErrorMessageLevel, String("Dropped srcset candidate "
) + String(imageURLStart, imageURLEnd - imageURLStart))); |
| 295 } |
266 continue; | 296 continue; |
| 297 } |
267 } | 298 } |
268 | 299 |
269 ASSERT(imageURLEnd > attributeStart); | 300 ASSERT(imageURLEnd > attributeStart); |
270 unsigned imageURLStartingPosition = imageURLStart - attributeStart; | 301 unsigned imageURLStartingPosition = imageURLStart - attributeStart; |
271 ASSERT(imageURLEnd > imageURLStart); | 302 ASSERT(imageURLEnd > imageURLStart); |
272 unsigned imageURLLength = imageURLEnd - imageURLStart; | 303 unsigned imageURLLength = imageURLEnd - imageURLStart; |
273 imageCandidates.append(ImageCandidate(attribute, imageURLStartingPositio
n, imageURLLength, result, ImageCandidate::SrcsetOrigin)); | 304 imageCandidates.append(ImageCandidate(attribute, imageURLStartingPositio
n, imageURLLength, result, ImageCandidate::SrcsetOrigin)); |
274 // 11. Return to the step labeled splitting loop. | 305 // 11. Return to the step labeled splitting loop. |
275 } | 306 } |
276 } | 307 } |
277 | 308 |
278 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec
tor<ImageCandidate>& imageCandidates) | 309 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec
tor<ImageCandidate>& imageCandidates, Document* document) |
279 { | 310 { |
280 if (attribute.isNull()) | 311 if (attribute.isNull()) |
281 return; | 312 return; |
282 | 313 |
283 if (attribute.is8Bit()) | 314 if (attribute.is8Bit()) |
284 parseImageCandidatesFromSrcsetAttribute<LChar>(attribute, attribute.char
acters8(), attribute.length(), imageCandidates); | 315 parseImageCandidatesFromSrcsetAttribute<LChar>(attribute, attribute.char
acters8(), attribute.length(), imageCandidates, document); |
285 else | 316 else |
286 parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.char
acters16(), attribute.length(), imageCandidates); | 317 parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.char
acters16(), attribute.length(), imageCandidates, document); |
287 } | 318 } |
288 | 319 |
289 static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, float sour
ceSize, Vector<ImageCandidate>& imageCandidates) | 320 static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, float sour
ceSize, Vector<ImageCandidate>& imageCandidates) |
290 { | 321 { |
291 const float defaultDensityValue = 1.0; | 322 const float defaultDensityValue = 1.0; |
292 bool ignoreSrc = false; | 323 bool ignoreSrc = false; |
293 if (imageCandidates.isEmpty()) | 324 if (imageCandidates.isEmpty()) |
294 return ImageCandidate(); | 325 return ImageCandidate(); |
295 | 326 |
296 // http://picture.responsiveimages.org/#normalize-source-densities | 327 // http://picture.responsiveimages.org/#normalize-source-densities |
(...skipping 22 matching lines...) Expand all Loading... |
319 | 350 |
320 unsigned winner = i; | 351 unsigned winner = i; |
321 // 16. If an entry b in candidates has the same associated ... pixel density
as an earlier entry a in candidates, | 352 // 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 | 353 // then remove entry b |
323 while ((i > 0) && (imageCandidates[--i].density() == winningDensity)) | 354 while ((i > 0) && (imageCandidates[--i].density() == winningDensity)) |
324 winner = i; | 355 winner = i; |
325 | 356 |
326 return imageCandidates[winner]; | 357 return imageCandidates[winner]; |
327 } | 358 } |
328 | 359 |
329 ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, float so
urceSize, const String& srcsetAttribute) | 360 ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, float so
urceSize, const String& srcsetAttribute, Document* document) |
330 { | 361 { |
331 Vector<ImageCandidate> imageCandidates; | 362 Vector<ImageCandidate> imageCandidates; |
332 | 363 |
333 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); | 364 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates, do
cument); |
334 | 365 |
335 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates
); | 366 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates
); |
336 } | 367 } |
337 | 368 |
338 ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, float so
urceSize, const String& srcAttribute, const String& srcsetAttribute) | 369 ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, float so
urceSize, const String& srcAttribute, const String& srcsetAttribute, Document* d
ocument) |
339 { | 370 { |
340 if (srcsetAttribute.isNull()) { | 371 if (srcsetAttribute.isNull()) { |
341 if (srcAttribute.isNull()) | 372 if (srcAttribute.isNull()) |
342 return ImageCandidate(); | 373 return ImageCandidate(); |
343 return ImageCandidate(srcAttribute, 0, srcAttribute.length(), Descriptor
ParsingResult(), ImageCandidate::SrcOrigin); | 374 return ImageCandidate(srcAttribute, 0, srcAttribute.length(), Descriptor
ParsingResult(), ImageCandidate::SrcOrigin); |
344 } | 375 } |
345 | 376 |
346 Vector<ImageCandidate> imageCandidates; | 377 Vector<ImageCandidate> imageCandidates; |
347 | 378 |
348 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); | 379 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates, do
cument); |
349 | 380 |
350 if (!srcAttribute.isEmpty()) | 381 if (!srcAttribute.isEmpty()) |
351 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng
th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); | 382 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng
th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); |
352 | 383 |
353 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates
); | 384 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates
); |
354 } | 385 } |
355 | 386 |
356 String bestFitSourceForImageAttributes(float deviceScaleFactor, float sourceSize
, const String& srcAttribute, ImageCandidate& srcsetImageCandidate) | 387 String bestFitSourceForImageAttributes(float deviceScaleFactor, float sourceSize
, const String& srcAttribute, ImageCandidate& srcsetImageCandidate) |
357 { | 388 { |
358 if (srcsetImageCandidate.isEmpty()) | 389 if (srcsetImageCandidate.isEmpty()) |
359 return srcAttribute; | 390 return srcAttribute; |
360 | 391 |
361 Vector<ImageCandidate> imageCandidates; | 392 Vector<ImageCandidate> imageCandidates; |
362 imageCandidates.append(srcsetImageCandidate); | 393 imageCandidates.append(srcsetImageCandidate); |
363 | 394 |
364 if (!srcAttribute.isEmpty()) | 395 if (!srcAttribute.isEmpty()) |
365 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng
th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); | 396 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng
th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); |
366 | 397 |
367 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates
).toString(); | 398 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates
).toString(); |
368 } | 399 } |
369 | 400 |
370 } | 401 } |
OLD | NEW |