Changeset 159030 in webkit
- Timestamp:
- Nov 10, 2013 2:17:32 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 10 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r159019 r159030 1 2013-11-10 Antti Koivisto <antti@apple.com> 2 3 Implement white-space property on simple line layout path 4 https://bugs.webkit.org/show_bug.cgi?id=124122 5 6 Reviewed by Andreas Kling. 7 8 The simple line layout produces slightly different runs in some pre-wrap cases compared 9 to the line box path (with less unnecessary boxes). To keep the test coverage this patch forces the 10 existing render tree dump based tests to use line boxes. It also adds new ref tests for 11 the same cases where the test uses the simple line path and the ref is forced on the line box path. 12 This ensures that the paths produce pixel-identical results. 13 14 * fast/forms/basic-textareas-simple-lines-expected.html: Added. 15 * fast/forms/basic-textareas-simple-lines.html: Added. 16 * fast/forms/basic-textareas.html: 17 * fast/text/embed-at-end-of-pre-wrap-line-simple-lines-expected.html: Added. 18 * fast/text/embed-at-end-of-pre-wrap-line-simple-lines.html: Added. 19 * fast/text/embed-at-end-of-pre-wrap-line.html: 20 * fast/text/whitespace/pre-wrap-line-test-simple-lines-expected.html: Added. 21 * fast/text/whitespace/pre-wrap-line-test-simple-lines.html: Added. 22 * fast/text/whitespace/pre-wrap-line-test.html: 23 * fast/text/whitespace/pre-wrap-long-word-simple-lines-expected.html: Added. 24 * fast/text/whitespace/pre-wrap-long-word-simple-lines.html: Added. New simple test for overflowing lines which was only covered by the very large basic-textareas.html. 25 * fast/text/whitespace/pre-wrap-spaces-after-newline-simple-lines-expected.html: Added. 26 * fast/text/whitespace/pre-wrap-spaces-after-newline-simple-lines.html: Added. 27 * fast/text/whitespace/pre-wrap-spaces-after-newline.html: 28 1 29 2013-11-10 Andreas Kling <akling@apple.com> 2 30 -
trunk/LayoutTests/fast/forms/basic-textareas.html
r48761 r159030 2 2 <body> 3 3 <script> 4 // Force line box path. 5 if (window.internals) 6 internals.settings.setSimpleLineLayoutEnabled(false); 4 7 var docToAppendTo; 5 8 function addTextarea(properties, opt_innerHTML) { -
trunk/LayoutTests/fast/text/embed-at-end-of-pre-wrap-line.html
r30664 r159030 1 <script> 2 // Force line box path. 3 if (window.internals) 4 internals.settings.setSimpleLineLayoutEnabled(false); 5 </script> 1 6 <style> 2 7 div { white-space: pre-wrap; border: 1px solid; padding: 4px; width: 70px; margin: 8px 0; } -
trunk/LayoutTests/fast/text/whitespace/pre-wrap-line-test.html
r21383 r159030 1 1 <script> 2 // Force line box path. 3 if (window.internals) 4 internals.settings.setSimpleLineLayoutEnabled(false); 5 </script> 2 6 <table><tr><td><div style="white-space:pre-wrap">Three cheers for OldVet and the letter he wrote to Senator Dodd (see above Comment). We all need to be proactive and contact our senators and representatives to let them know our strong feelings on this subject. I would lose what little faith I have left in our government if they engineered a tax payer bailout. -
trunk/LayoutTests/fast/text/whitespace/pre-wrap-spaces-after-newline.html
r48921 r159030 1 <script> 2 // Force line box path. 3 if (window.internals) 4 internals.settings.setSimpleLineLayoutEnabled(false); 5 </script> 1 6 <style> 2 7 pre { white-space: pre-wrap; background: silver; width: 7ex; } -
trunk/LayoutTests/platform/mac/compositing/repaint/invalidations-on-composited-layers-expected.txt
r146531 r159030 1 1 (repaint rects 2 (rect 8 13 784 15) 2 3 (rect 8 13 784 15) 3 4 (rect 8 413 784 28) -
trunk/Source/WebCore/ChangeLog
r159029 r159030 1 2013-11-10 Antti Koivisto <antti@apple.com> 2 3 Implement white-space property on simple line layout path 4 https://bugs.webkit.org/show_bug.cgi?id=124122 5 6 Reviewed by Andreas Kling. 7 8 Support all values of the white-space property and the tab-size property. 9 10 Tests: fast/forms/basic-textareas-simple-lines.html 11 fast/text/embed-at-end-of-pre-wrap-line-simple-lines.html 12 fast/text/whitespace/pre-wrap-line-test-simple-lines.html 13 fast/text/whitespace/pre-wrap-long-word-simple-lines.html 14 fast/text/whitespace/pre-wrap-spaces-after-newline-simple-lines.html 15 16 * rendering/SimpleLineLayout.cpp: 17 (WebCore::SimpleLineLayout::canUseFor): 18 (WebCore::SimpleLineLayout::isWhitespace): 19 (WebCore::SimpleLineLayout::skipWhitespaces): 20 (WebCore::SimpleLineLayout::textWidth): 21 (WebCore::SimpleLineLayout::measureWord): 22 (WebCore::SimpleLineLayout::createTextRuns): 23 * rendering/SimpleLineLayoutFunctions.cpp: 24 (WebCore::SimpleLineLayout::paintDebugBorders): 25 (WebCore::SimpleLineLayout::paintFlow): 26 1 27 2013-11-10 Sergio Correia <sergio.correia@openbossa.org> 2 28 -
trunk/Source/WebCore/rendering/SimpleLineLayout.cpp
r158918 r159030 131 131 if (style.overflowX() != OVISIBLE || style.overflowY() != OVISIBLE) 132 132 return false; 133 // Pre/no-wrap would be very helpful to support.134 if (style.whiteSpace() != NORMAL)135 return false;136 133 if (!style.textIndent().isZero()) 137 134 return false; … … 198 195 } 199 196 200 static inline bool isWhitespace(UChar character )201 { 202 return character == ' ' || character == '\t' || character == '\n';197 static inline bool isWhitespace(UChar character, bool preserveNewline) 198 { 199 return character == ' ' || character == '\t' || (!preserveNewline && character == '\n'); 203 200 } 204 201 205 202 template <typename CharacterType> 206 static inline unsigned skipWhitespaces(const CharacterType* text, unsigned offset, unsigned length )203 static inline unsigned skipWhitespaces(const CharacterType* text, unsigned offset, unsigned length, bool preserveNewline) 207 204 { 208 205 for (; offset < length; ++offset) { 209 if (!isWhitespace(text[offset] ))206 if (!isWhitespace(text[offset], preserveNewline)) 210 207 return offset; 211 208 } … … 214 211 215 212 template <typename CharacterType> 216 static float textWidth(const RenderText& renderText, const CharacterType* text, unsigned textLength, unsigned from, unsigned to, float xPosition, const RenderStyle& style)217 { 218 if ( style.font().isFixedPitch() || (!from && to == textLength))219 return renderText.width(from, to - from, style.font(), xPosition, nullptr, nullptr);220 // FIXME: Add templated UChar/LChar paths. 213 static float textWidth(const RenderText& renderText, const CharacterType* text, unsigned textLength, unsigned from, unsigned to, float xPosition, const Font& font, float tabWidth) 214 { 215 if (font.isFixedPitch() || (!from && to == textLength)) 216 return renderText.width(from, to - from, font, xPosition, nullptr, nullptr); 217 221 218 TextRun run(text + from, to - from); 222 219 run.setXPos(xPosition); 223 220 run.setCharactersLength(textLength - from); 221 run.setTabSize(!!tabWidth, tabWidth); 222 224 223 ASSERT(run.charactersLength() >= run.length()); 225 224 226 return style.font().width(run); 225 return font.width(run); 226 } 227 228 template <typename CharacterType> 229 static float measureWord(const RenderText& textRenderer, const CharacterType* text, unsigned textLength, unsigned start, unsigned end, float lineWidth, bool collapseWhitespace, const Font& font, float tabWidth, float spaceWidth) 230 { 231 if (text[start] == ' ' && end == start + 1) 232 return spaceWidth; 233 234 bool measureWithEndSpace = collapseWhitespace && end < textLength && text[end] == ' '; 235 if (measureWithEndSpace) 236 ++end; 237 float width = textWidth(textRenderer, text, textLength, start, end, lineWidth, font, collapseWhitespace ? 0 : tabWidth); 238 239 return measureWithEndSpace ? width - spaceWidth : width; 227 240 } 228 241 … … 262 275 const RenderStyle& style = flow.style(); 263 276 264 ETextAlign textAlign = style.textAlign(); 265 float wordTrailingSpaceWidth = style.font().width(TextRun(&space, 1)); 277 // These properties are supported. 278 const Font& font = style.font(); 279 unsigned tabWidth = style.tabSize(); 280 ETextAlign textAlign = style.textAlign(); // Not 'justify'. 281 bool collapseWhitespace = style.collapseWhiteSpace(); 282 bool preserveNewline = style.preserveNewline(); 283 bool wrapLines = style.autoWrap(); 266 284 267 285 const CharacterType* text = textRenderer.text()->getCharacters<CharacterType>(); 268 286 const unsigned textLength = textRenderer.textLength(); 269 287 288 float spaceWidth = font.width(TextRun(&space, 1)); 270 289 LazyLineBreakIterator lineBreakIterator(textRenderer.text(), style.locale()); 271 290 272 291 unsigned lineEnd = 0; 273 292 while (lineEnd < textLength) { 274 lineEnd = skipWhitespaces(text, lineEnd, textLength); 293 if (collapseWhitespace) 294 lineEnd = skipWhitespaces(text, lineEnd, textLength, preserveNewline); 275 295 unsigned lineStart = lineEnd; 276 296 unsigned wordEnd = lineEnd; … … 281 301 282 302 while (wordEnd < textLength) { 283 ASSERT(!isWhitespace(text[wordEnd])); 284 285 bool wordIsPrecededByWhitespace = wordEnd > lineStart && isWhitespace(text[wordEnd - 1]); 286 unsigned wordStart = wordIsPrecededByWhitespace ? wordEnd - 1 : wordEnd; 287 288 wordEnd = nextBreakablePosition<CharacterType, false>(lineBreakIterator, text, textLength, wordEnd + 1); 289 290 bool measureWithEndSpace = wordEnd < textLength && text[wordEnd] == ' '; 291 unsigned wordMeasureEnd = measureWithEndSpace ? wordEnd + 1 : wordEnd; 292 293 float wordWidth = textWidth(textRenderer, text, textLength, wordStart, wordMeasureEnd, lineWidth.committedWidth(), style); 294 295 if (measureWithEndSpace) 296 wordWidth -= wordTrailingSpaceWidth; 303 ASSERT(!collapseWhitespace || !isWhitespace(text[wordEnd], preserveNewline)); 304 305 unsigned wordStart = wordEnd; 306 307 if (preserveNewline && text[wordStart] == '\n') { 308 ++wordEnd; 309 // FIXME: This creates a dedicated run for newline. This is wasteful and unnecessary but it keeps test results unchanged. 310 if (wordStart > lineStart) 311 lineRuns.append(Run(lineEnd, lineRuns.last().right)); 312 lineRuns.last().right = lineRuns.last().left; 313 lineRuns.last().textLength = 1; 314 lineEnd = wordEnd; 315 break; 316 } 317 318 if (!collapseWhitespace && isWhitespace(text[wordStart], preserveNewline)) 319 wordEnd = wordStart + 1; 320 else 321 wordEnd = nextBreakablePosition<CharacterType, false>(lineBreakIterator, text, textLength, wordStart + 1); 322 323 bool wordIsPrecededByWhitespace = collapseWhitespace && wordStart > lineStart && isWhitespace(text[wordStart - 1], preserveNewline); 324 if (wordIsPrecededByWhitespace) 325 --wordStart; 326 327 float wordWidth = measureWord(textRenderer, text, textLength, wordStart, wordEnd, lineWidth.committedWidth(), collapseWhitespace, font, tabWidth, spaceWidth); 297 328 298 329 lineWidth.addUncommittedWidth(wordWidth); 299 330 300 // Move to the next line if the current one is full and we have something on it. 301 if (!lineWidth.fitsOnLine() && lineWidth.committedWidth()) 302 break; 331 if (wrapLines) { 332 // Move to the next line if the current one is full and we have something on it. 333 if (!lineWidth.fitsOnLine() && lineWidth.committedWidth()) 334 break; 335 336 // This is for white-space: pre-wrap which requires special handling for end line whitespace. 337 if (!collapseWhitespace && lineWidth.fitsOnLine() && wordEnd < textLength && isWhitespace(text[wordEnd], preserveNewline)) { 338 // Look ahead to see if the next whitespace would fit. 339 float whitespaceWidth = textWidth(textRenderer, text, textLength, wordEnd, wordEnd + 1, lineWidth.committedWidth(), font, tabWidth); 340 if (!lineWidth.fitsOnLineIncludingExtraWidth(whitespaceWidth)) { 341 // If not eat away the rest of the whitespace on the line. 342 unsigned whitespaceEnd = skipWhitespaces(text, wordEnd, textLength, preserveNewline); 343 // Include newline to this run too. 344 if (whitespaceEnd < textLength && text[whitespaceEnd] == '\n') 345 ++whitespaceEnd; 346 lineRuns.last().textLength = whitespaceEnd - lineRuns.last().textOffset; 347 lineRuns.last().right = lineWidth.availableWidth(); 348 lineEnd = whitespaceEnd; 349 break; 350 } 351 } 352 } 303 353 304 354 if (wordStart > lineEnd) { … … 307 357 // Include space to the end of the previous run. 308 358 lineRuns.last().textLength++; 309 lineRuns.last().right += wordTrailingSpaceWidth;359 lineRuns.last().right += spaceWidth; 310 360 // Start a new run on the same line. 311 361 lineRuns.append(Run(wordStart + 1, lineRuns.last().right)); … … 318 368 319 369 lineEnd = wordEnd; 320 wordEnd = skipWhitespaces(text, wordEnd, textLength); 321 322 if (!lineWidth.fitsOnLine()) { 370 if (collapseWhitespace) 371 wordEnd = skipWhitespaces(text, wordEnd, textLength, preserveNewline); 372 373 if (wrapLines && !lineWidth.fitsOnLine()) { 323 374 // The first run on the line overflows. 324 375 ASSERT(lineRuns.size() == 1); … … 329 380 continue; 330 381 382 lineRuns.last().isEndOfLine = true; 383 331 384 adjustRunOffsets(lineRuns, textAlign, lineWidth.committedWidth(), lineWidth.availableWidth()); 332 385 … … 334 387 runs.append(lineRuns[i]); 335 388 336 runs.last().isEndOfLine = true;337 389 ++lineCount; 338 390 } -
trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp
r158285 r159030 51 51 static void paintDebugBorders(GraphicsContext& context, const LayoutRect& borderRect, const LayoutPoint& paintOffset) 52 52 { 53 if (borderRect.isEmpty()) 54 return; 53 55 GraphicsContextStateSaver stateSaver(context); 54 56 context.setStrokeColor(Color(0, 255, 0), ColorSpaceDeviceRGB); … … 81 83 for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) { 82 84 auto run = *it; 83 context.drawText(font, TextRun(run.text()), run.baseline() + paintOffset); 85 TextRun textRun(run.text()); 86 textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize()); 87 context.drawText(font, textRun, run.baseline() + paintOffset); 84 88 if (debugBordersEnabled) 85 89 paintDebugBorders(context, run.rect(), paintOffset);
Note: See TracChangeset
for help on using the changeset viewer.