Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1340)

Side by Side Diff: Source/core/html/parser/HTMLSrcsetParser.cpp

Issue 233213003: Extend srcset's syntax to include 'w' descriptors (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Fixed nits and modified multiple descriptor layout test Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "core/html/parser/HTMLSrcsetParser.h" 32 #include "core/html/parser/HTMLSrcsetParser.h"
33 33
34 #include "RuntimeEnabledFeatures.h"
34 #include "core/html/parser/HTMLParserIdioms.h" 35 #include "core/html/parser/HTMLParserIdioms.h"
35 #include "platform/ParsingUtilities.h" 36 #include "platform/ParsingUtilities.h"
36 37
37 namespace WebCore { 38 namespace WebCore {
38 39
39 static bool compareByScaleFactor(const ImageCandidate& first, const ImageCandida te& second) 40 static bool compareByScaleFactor(const ImageCandidate& first, const ImageCandida te& second)
40 { 41 {
41 return first.scaleFactor() < second.scaleFactor(); 42 return first.scaleFactor() < second.scaleFactor();
42 } 43 }
43 44
44 template<typename CharType> 45 template<typename CharType>
45 inline bool isComma(CharType character) 46 inline bool isComma(CharType character)
46 { 47 {
47 return character == ','; 48 return character == ',';
48 } 49 }
49 50
50 template<typename CharType> 51 template<typename CharType>
51 static bool parseDescriptors(const CharType* descriptorsStart, const CharType* d escriptorsEnd, float& imgScaleFactor) 52 static bool parseDescriptors(const CharType* descriptorsStart, const CharType* d escriptorsEnd, DescriptorParsingResult& result)
52 { 53 {
53 const CharType* position = descriptorsStart; 54 const CharType* position = descriptorsStart;
54 bool isValid = false; 55 bool isValid = false;
55 bool isFoundScaleFactor = false;
56 bool isEmptyDescriptor = !(descriptorsEnd > descriptorsStart); 56 bool isEmptyDescriptor = !(descriptorsEnd > descriptorsStart);
57 while (position < descriptorsEnd) { 57 while (position < descriptorsEnd) {
58 // 13.1. Let descriptor list be the result of splitting unparsed descrip tors on spaces. 58 // 13.1. Let descriptor list be the result of splitting unparsed descrip tors on spaces.
59 skipWhile<CharType, isHTMLSpace<CharType> >(position, descriptorsEnd); 59 skipWhile<CharType, isHTMLSpace<CharType> >(position, descriptorsEnd);
60 const CharType* currentDescriptorStart = position; 60 const CharType* currentDescriptorStart = position;
61 skipWhile<CharType, isNotHTMLSpace<CharType> >(position, descriptorsEnd) ; 61 skipWhile<CharType, isNotHTMLSpace<CharType> >(position, descriptorsEnd) ;
62 const CharType* currentDescriptorEnd = position; 62 const CharType* currentDescriptorEnd = position;
63 63
64 ++position; 64 ++position;
65 ASSERT(currentDescriptorEnd > currentDescriptorStart); 65 ASSERT(currentDescriptorEnd > currentDescriptorStart);
66 --currentDescriptorEnd; 66 --currentDescriptorEnd;
67 unsigned descriptorLength = currentDescriptorEnd - currentDescriptorStar t; 67 unsigned descriptorLength = currentDescriptorEnd - currentDescriptorStar t;
68 if (*currentDescriptorEnd == 'x') { 68 if (*currentDescriptorEnd == 'x') {
69 if (isFoundScaleFactor) 69 if (result.foundDescriptor())
70 return false; 70 return false;
71 imgScaleFactor = charactersToFloat(currentDescriptorStart, descripto rLength, &isValid); 71 result.scaleFactor = charactersToFloat(currentDescriptorStart, descr iptorLength, &isValid);
72 isFoundScaleFactor = true; 72 if (!isValid || result.scaleFactor < 0)
73 } else { 73 return false;
74 continue; 74 } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && *currentDesc riptorEnd == 'w') {
75 if (result.foundDescriptor())
76 return false;
77 result.resourceWidth = charactersToInt(currentDescriptorStart, descr iptorLength, &isValid);
78 if (!isValid || result.resourceWidth < 0)
79 return false;
75 } 80 }
76 } 81 }
77 return isEmptyDescriptor || isValid; 82 if (isEmptyDescriptor)
83 result.scaleFactor = 1.0;
84 return result.foundDescriptor();
78 } 85 }
79 86
80 // http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content- 1.html#processing-the-image-candidates 87 // http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content- 1.html#processing-the-image-candidates
81 template<typename CharType> 88 template<typename CharType>
82 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con st CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandi dates) 89 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con st CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandi dates)
83 { 90 {
84 const CharType* position = attributeStart; 91 const CharType* position = attributeStart;
85 const CharType* attributeEnd = position + length; 92 const CharType* attributeEnd = position + length;
86 93
87 while (position < attributeEnd) { 94 while (position < attributeEnd) {
88 float imgScaleFactor = 1.0; 95 DescriptorParsingResult result;
89
90 // 4. Splitting loop: Skip whitespace. 96 // 4. Splitting loop: Skip whitespace.
91 skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd); 97 skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd);
92 if (position == attributeEnd) 98 if (position == attributeEnd)
93 break; 99 break;
94 const CharType* imageURLStart = position; 100 const CharType* imageURLStart = position;
95 101
96 // If The current candidate is either totally empty or only contains spa ce, skipping. 102 // If The current candidate is either totally empty or only contains spa ce, skipping.
97 if (*position == ',') { 103 if (*position == ',') {
98 ++position; 104 ++position;
99 continue; 105 continue;
100 } 106 }
101 107
102 // 5. Collect a sequence of characters that are not space characters, an d let that be url. 108 // 5. Collect a sequence of characters that are not space characters, an d let that be url.
103 skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd); 109 skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd);
104 const CharType* imageURLEnd = position; 110 const CharType* imageURLEnd = position;
105 111
106 if (position != attributeEnd && *(position - 1) == ',') { 112 if (position != attributeEnd && *(position - 1) == ',') {
107 --imageURLEnd; 113 --imageURLEnd;
114 result.scaleFactor = 1.0;
108 } else { 115 } else {
109 // 7. Collect a sequence of characters that are not "," (U+002C) cha racters, and let that be descriptors. 116 // 7. Collect a sequence of characters that are not "," (U+002C) cha racters, and let that be descriptors.
110 skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd); 117 skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd);
111 const CharType* descriptorsStart = position; 118 const CharType* descriptorsStart = position;
112 skipUntil<CharType, isComma<CharType> >(position, attributeEnd); 119 skipUntil<CharType, isComma<CharType> >(position, attributeEnd);
113 const CharType* descriptorsEnd = position; 120 const CharType* descriptorsEnd = position;
114 if (!parseDescriptors(descriptorsStart, descriptorsEnd, imgScaleFact or)) 121 if (!parseDescriptors(descriptorsStart, descriptorsEnd, result))
115 continue; 122 continue;
116 } 123 }
117 124
118 imageCandidates.append(ImageCandidate(attribute, imageURLStart - attribu teStart, imageURLEnd - imageURLStart, imgScaleFactor)); 125 imageCandidates.append(ImageCandidate(attribute, imageURLStart - attribu teStart, imageURLEnd - imageURLStart, result));
119 // 11. Return to the step labeled splitting loop. 126 // 11. Return to the step labeled splitting loop.
120 } 127 }
121 } 128 }
122 129
123 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec tor<ImageCandidate>& imageCandidates) 130 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec tor<ImageCandidate>& imageCandidates)
124 { 131 {
125 if (attribute.isNull()) 132 if (attribute.isNull())
126 return; 133 return;
127 134
128 if (attribute.is8Bit()) 135 if (attribute.is8Bit())
129 parseImageCandidatesFromSrcsetAttribute<LChar>(attribute, attribute.char acters8(), attribute.length(), imageCandidates); 136 parseImageCandidatesFromSrcsetAttribute<LChar>(attribute, attribute.char acters8(), attribute.length(), imageCandidates);
130 else 137 else
131 parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.char acters16(), attribute.length(), imageCandidates); 138 parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.char acters16(), attribute.length(), imageCandidates);
132 } 139 }
133 140
134 static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, Vector<Ima geCandidate>& imageCandidates) 141 static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, int effect iveSize, Vector<ImageCandidate>& imageCandidates)
135 { 142 {
136 if (imageCandidates.isEmpty()) 143 if (imageCandidates.isEmpty())
137 return ImageCandidate(); 144 return ImageCandidate();
138 145
146 // http://picture.responsiveimages.org/#normalize-source-densities
147 for (Vector<ImageCandidate>::iterator it = imageCandidates.begin(); it != im ageCandidates.end(); ++it) {
148 if (it->scaleFactor() < 0)
149 it->setScaleFactor((float)it->resourceWidth() / (float)effectiveSize );
150 }
151
139 std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareBySc aleFactor); 152 std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareBySc aleFactor);
140 153
141 unsigned i; 154 unsigned i;
142 for (i = 0; i < imageCandidates.size() - 1; ++i) 155 for (i = 0; i < imageCandidates.size() - 1; ++i) {
143 if (imageCandidates[i].scaleFactor() >= deviceScaleFactor) 156 if (imageCandidates[i].scaleFactor() >= deviceScaleFactor)
144 break; 157 break;
158 }
145 159
146 float winningScaleFactor = imageCandidates[i].scaleFactor(); 160 float winningScaleFactor = imageCandidates[i].scaleFactor();
147 unsigned winner = i; 161 unsigned winner = i;
148 // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates, 162 // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates,
149 // then remove entry b 163 // then remove entry b
150 while ((i > 0) && (imageCandidates[--i].scaleFactor() == winningScaleFactor) ) 164 while ((i > 0) && (imageCandidates[--i].scaleFactor() == winningScaleFactor) )
151 winner = i; 165 winner = i;
152 166
153 return imageCandidates[winner]; 167 return imageCandidates[winner];
154 } 168 }
155 169
156 ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, const St ring& srcsetAttribute) 170 ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, int effe ctiveSize, const String& srcsetAttribute)
157 { 171 {
158 Vector<ImageCandidate> imageCandidates; 172 Vector<ImageCandidate> imageCandidates;
159 173
160 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); 174 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates);
161 175
162 return pickBestImageCandidate(deviceScaleFactor, imageCandidates); 176 return pickBestImageCandidate(deviceScaleFactor, effectiveSize, imageCandida tes);
163 } 177 }
164 178
165 ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, const St ring& srcAttribute, const String& srcsetAttribute) 179 ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, int effe ctiveSize, const String& srcAttribute, const String& srcsetAttribute)
166 { 180 {
181 DescriptorParsingResult defaultResult;
182 defaultResult.scaleFactor = 1.0;
183
167 if (srcsetAttribute.isNull()) { 184 if (srcsetAttribute.isNull()) {
168 if (srcAttribute.isNull()) 185 if (srcAttribute.isNull())
169 return ImageCandidate(); 186 return ImageCandidate();
170 return ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1); 187 return ImageCandidate(srcAttribute, 0, srcAttribute.length(), defaultRes ult);
171 } 188 }
172 189
173 Vector<ImageCandidate> imageCandidates; 190 Vector<ImageCandidate> imageCandidates;
174 191
175 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); 192 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates);
176 193
177 if (!srcAttribute.isEmpty()) 194 if (!srcAttribute.isEmpty())
178 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), 1.0)); 195 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), defaultResult));
179 196
180 return pickBestImageCandidate(deviceScaleFactor, imageCandidates); 197 return pickBestImageCandidate(deviceScaleFactor, effectiveSize, imageCandida tes);
181 } 198 }
182 199
183 String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& sr cAttribute, ImageCandidate& srcsetImageCandidate) 200 String bestFitSourceForImageAttributes(float deviceScaleFactor, int effectiveSiz e, const String& srcAttribute, ImageCandidate& srcsetImageCandidate)
184 { 201 {
202 DescriptorParsingResult defaultResult;
203 defaultResult.scaleFactor = 1.0;
204
185 if (srcsetImageCandidate.isEmpty()) 205 if (srcsetImageCandidate.isEmpty())
186 return srcAttribute; 206 return srcAttribute;
187 207
188 Vector<ImageCandidate> imageCandidates; 208 Vector<ImageCandidate> imageCandidates;
189 imageCandidates.append(srcsetImageCandidate); 209 imageCandidates.append(srcsetImageCandidate);
190 210
191 if (!srcAttribute.isEmpty()) 211 if (!srcAttribute.isEmpty())
192 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), 1.0)); 212 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), defaultResult));
193 213
194 return pickBestImageCandidate(deviceScaleFactor, imageCandidates).toString() ; 214 return pickBestImageCandidate(deviceScaleFactor, effectiveSize, imageCandida tes).toString();
195 } 215 }
196 216
197 } 217 }
OLDNEW
« no previous file with comments | « Source/core/html/parser/HTMLSrcsetParser.h ('k') | Source/core/html/parser/HTMLSrcsetParserTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698