OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ight reserved. | 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. |
| 4 * All right reserved. |
4 * Copyright (C) 2010 Google Inc. All rights reserved. | 5 * Copyright (C) 2010 Google Inc. All rights reserved. |
5 * Copyright (C) 2013 Adobe Systems Incorporated. | 6 * Copyright (C) 2013 Adobe Systems Incorporated. |
6 * | 7 * |
7 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 11 * version 2 of the License, or (at your option) any later version. |
11 * | 12 * |
12 * This library is distributed in the hope that it will be useful, | 13 * This library is distributed in the hope that it will be useful, |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 bool m_collapseWhiteSpace; | 213 bool m_collapseWhiteSpace; |
213 bool m_startingNewParagraph; | 214 bool m_startingNewParagraph; |
214 bool m_allowImagesToBreak; | 215 bool m_allowImagesToBreak; |
215 bool m_atEnd; | 216 bool m_atEnd; |
216 | 217 |
217 LineMidpointState& m_lineMidpointState; | 218 LineMidpointState& m_lineMidpointState; |
218 | 219 |
219 TrailingObjects m_trailingObjects; | 220 TrailingObjects m_trailingObjects; |
220 }; | 221 }; |
221 | 222 |
222 // When ignoring spaces, this needs to be called for objects that need line boxe
s such as LayoutInlines or | 223 // When ignoring spaces, this needs to be called for objects that need line |
223 // hard line breaks to ensure that they're not ignored. | 224 // boxes such as LayoutInlines or hard line breaks to ensure that they're not |
| 225 // ignored. |
224 inline void ensureLineBoxInsideIgnoredSpaces(LineMidpointState* midpointState, | 226 inline void ensureLineBoxInsideIgnoredSpaces(LineMidpointState* midpointState, |
225 LineLayoutItem item) { | 227 LineLayoutItem item) { |
226 InlineIterator midpoint(0, item, 0); | 228 InlineIterator midpoint(0, item, 0); |
227 midpointState->stopIgnoringSpaces(midpoint); | 229 midpointState->stopIgnoringSpaces(midpoint); |
228 midpointState->startIgnoringSpaces(midpoint); | 230 midpointState->startIgnoringSpaces(midpoint); |
229 } | 231 } |
230 | 232 |
231 inline bool shouldCollapseWhiteSpace(const ComputedStyle& style, | 233 inline bool shouldCollapseWhiteSpace(const ComputedStyle& style, |
232 const LineInfo& lineInfo, | 234 const LineInfo& lineInfo, |
233 WhitespacePosition whitespacePosition) { | 235 WhitespacePosition whitespacePosition) { |
234 // CSS2 16.6.1 | 236 // CSS2 16.6.1 |
235 // If a space (U+0020) at the beginning of a line has 'white-space' set to 'no
rmal', 'nowrap', or 'pre-line', it is removed. | 237 // If a space (U+0020) at the beginning of a line has 'white-space' set to |
236 // If a space (U+0020) at the end of a line has 'white-space' set to 'normal',
'nowrap', or 'pre-line', it is also removed. | 238 // 'normal', 'nowrap', or 'pre-line', it is removed. |
237 // If spaces (U+0020) or tabs (U+0009) at the end of a line have 'white-space'
set to 'pre-wrap', UAs may visually collapse them. | 239 // If a space (U+0020) at the end of a line has 'white-space' set to 'normal', |
| 240 // 'nowrap', or 'pre-line', it is also removed. |
| 241 // If spaces (U+0020) or tabs (U+0009) at the end of a line have 'white-space' |
| 242 // set to 'pre-wrap', UAs may visually collapse them. |
238 return style.collapseWhiteSpace() || | 243 return style.collapseWhiteSpace() || |
239 (whitespacePosition == TrailingWhitespace && | 244 (whitespacePosition == TrailingWhitespace && |
240 style.whiteSpace() == PRE_WRAP && | 245 style.whiteSpace() == PRE_WRAP && |
241 (!lineInfo.isEmpty() || !lineInfo.previousLineBrokeCleanly())); | 246 (!lineInfo.isEmpty() || !lineInfo.previousLineBrokeCleanly())); |
242 } | 247 } |
243 | 248 |
244 inline bool requiresLineBoxForContent(LineLayoutInline flow, | 249 inline bool requiresLineBoxForContent(LineLayoutInline flow, |
245 const LineInfo& lineInfo) { | 250 const LineInfo& lineInfo) { |
246 LineLayoutItem parent = flow.parent(); | 251 LineLayoutItem parent = flow.parent(); |
247 if (flow.document().inNoQuirksMode() && | 252 if (flow.document().inNoQuirksMode() && |
248 (flow.style(lineInfo.isFirstLine())->lineHeight() != | 253 (flow.style(lineInfo.isFirstLine())->lineHeight() != |
249 parent.style(lineInfo.isFirstLine())->lineHeight() || | 254 parent.style(lineInfo.isFirstLine())->lineHeight() || |
250 flow.style()->verticalAlign() != parent.style()->verticalAlign() || | 255 flow.style()->verticalAlign() != parent.style()->verticalAlign() || |
251 !parent.style() | 256 !parent.style() |
252 ->font() | 257 ->font() |
253 .getFontMetrics() | 258 .getFontMetrics() |
254 .hasIdenticalAscentDescentAndLineGap( | 259 .hasIdenticalAscentDescentAndLineGap( |
255 flow.style()->font().getFontMetrics()))) | 260 flow.style()->font().getFontMetrics()))) |
256 return true; | 261 return true; |
257 return false; | 262 return false; |
258 } | 263 } |
259 | 264 |
260 inline bool alwaysRequiresLineBox(LineLayoutItem flow) { | 265 inline bool alwaysRequiresLineBox(LineLayoutItem flow) { |
261 // FIXME: Right now, we only allow line boxes for inlines that are truly empty
. | 266 // FIXME: Right now, we only allow line boxes for inlines that are truly |
262 // We need to fix this, though, because at the very least, inlines containing
only | 267 // empty. We need to fix this, though, because at the very least, inlines |
263 // ignorable whitespace should should also have line boxes. | 268 // containing only ignorable whitespace should should also have line boxes. |
264 return isEmptyInline(flow) && | 269 return isEmptyInline(flow) && |
265 LineLayoutInline(flow).hasInlineDirectionBordersPaddingOrMargin(); | 270 LineLayoutInline(flow).hasInlineDirectionBordersPaddingOrMargin(); |
266 } | 271 } |
267 | 272 |
268 inline bool requiresLineBox( | 273 inline bool requiresLineBox( |
269 const InlineIterator& it, | 274 const InlineIterator& it, |
270 const LineInfo& lineInfo = LineInfo(), | 275 const LineInfo& lineInfo = LineInfo(), |
271 WhitespacePosition whitespacePosition = LeadingWhitespace) { | 276 WhitespacePosition whitespacePosition = LeadingWhitespace) { |
272 if (it.getLineLayoutItem().isEmptyText()) | 277 if (it.getLineLayoutItem().isEmptyText()) |
273 return false; | 278 return false; |
(...skipping 18 matching lines...) Expand all Loading... |
292 current != softHyphenCharacter && | 297 current != softHyphenCharacter && |
293 (current != newlineCharacter || | 298 (current != newlineCharacter || |
294 it.getLineLayoutItem().preservesNewline()); | 299 it.getLineLayoutItem().preservesNewline()); |
295 return notJustWhitespace || isEmptyInline(it.getLineLayoutItem()); | 300 return notJustWhitespace || isEmptyInline(it.getLineLayoutItem()); |
296 } | 301 } |
297 | 302 |
298 inline void setStaticPositions(LineLayoutBlockFlow block, | 303 inline void setStaticPositions(LineLayoutBlockFlow block, |
299 LineLayoutBox child, | 304 LineLayoutBox child, |
300 IndentTextOrNot indentText) { | 305 IndentTextOrNot indentText) { |
301 ASSERT(child.isOutOfFlowPositioned()); | 306 ASSERT(child.isOutOfFlowPositioned()); |
302 // FIXME: The math here is actually not really right. It's a best-guess approx
imation that | 307 // FIXME: The math here is actually not really right. It's a best-guess |
303 // will work for the common cases | 308 // approximation that will work for the common cases |
304 LineLayoutItem containerBlock = child.container(); | 309 LineLayoutItem containerBlock = child.container(); |
305 LayoutUnit blockHeight = block.logicalHeight(); | 310 LayoutUnit blockHeight = block.logicalHeight(); |
306 if (containerBlock.isLayoutInline()) { | 311 if (containerBlock.isLayoutInline()) { |
307 // A relative positioned inline encloses us. In this case, we also have to d
etermine our | 312 // A relative positioned inline encloses us. In this case, we also have to |
308 // position as though we were an inline. Set |staticInlinePosition| and |sta
ticBlockPosition| on the relative positioned | 313 // determine our position as though we were an inline. |
309 // inline so that we can obtain the value later. | 314 // Set |staticInlinePosition| and |staticBlockPosition| on the relative |
| 315 // positioned inline so that we can obtain the value later. |
310 LineLayoutInline(containerBlock) | 316 LineLayoutInline(containerBlock) |
311 .layer() | 317 .layer() |
312 ->setStaticInlinePosition( | 318 ->setStaticInlinePosition( |
313 block.startAlignedOffsetForLine(blockHeight, indentText)); | 319 block.startAlignedOffsetForLine(blockHeight, indentText)); |
314 LineLayoutInline(containerBlock) | 320 LineLayoutInline(containerBlock) |
315 .layer() | 321 .layer() |
316 ->setStaticBlockPosition(blockHeight); | 322 ->setStaticBlockPosition(blockHeight); |
317 | 323 |
318 // If |child| is a leading or trailing positioned object this is its only op
portunity to ensure it moves with an inline | 324 // If |child| is a leading or trailing positioned object this is its only |
319 // container changing width. | 325 // opportunity to ensure it moves with an inline container changing width. |
320 child.moveWithEdgeOfInlineContainerIfNecessary( | 326 child.moveWithEdgeOfInlineContainerIfNecessary( |
321 child.isHorizontalWritingMode()); | 327 child.isHorizontalWritingMode()); |
322 } | 328 } |
323 block.updateStaticInlinePositionForChild(child, blockHeight, indentText); | 329 block.updateStaticInlinePositionForChild(child, blockHeight, indentText); |
324 child.layer()->setStaticBlockPosition(blockHeight); | 330 child.layer()->setStaticBlockPosition(blockHeight); |
325 } | 331 } |
326 | 332 |
327 // FIXME: The entire concept of the skipTrailingWhitespace function is flawed, s
ince we really need to be building | 333 // FIXME: The entire concept of the skipTrailingWhitespace function is flawed, |
328 // line boxes even for containers that may ultimately collapse away. Otherwise w
e'll never get positioned | 334 // since we really need to be building line boxes even for containers that may |
329 // elements quite right. In other words, we need to build this function's work i
nto the normal line | 335 // ultimately collapse away. Otherwise we'll never get positioned elements quite |
330 // object iteration process. | 336 // right. In other words, we need to build this function's work into the normal |
331 // NB. this function will insert any floating elements that would otherwise | 337 // line object iteration process. NB. this function will insert any floating |
332 // be skipped but it will not position them. | 338 // elements that would otherwise be skipped but it will not position them. |
333 inline void BreakingContext::skipTrailingWhitespace(InlineIterator& iterator, | 339 inline void BreakingContext::skipTrailingWhitespace(InlineIterator& iterator, |
334 const LineInfo& lineInfo) { | 340 const LineInfo& lineInfo) { |
335 while (!iterator.atEnd() && | 341 while (!iterator.atEnd() && |
336 !requiresLineBox(iterator, lineInfo, TrailingWhitespace)) { | 342 !requiresLineBox(iterator, lineInfo, TrailingWhitespace)) { |
337 LineLayoutItem item = iterator.getLineLayoutItem(); | 343 LineLayoutItem item = iterator.getLineLayoutItem(); |
338 if (item.isOutOfFlowPositioned()) | 344 if (item.isOutOfFlowPositioned()) |
339 setStaticPositions(m_block, LineLayoutBox(item), DoNotIndentText); | 345 setStaticPositions(m_block, LineLayoutBox(item), DoNotIndentText); |
340 else if (item.isFloating()) | 346 else if (item.isFloating()) |
341 m_block.insertFloatingObject(LineLayoutBox(item)); | 347 m_block.insertFloatingObject(LineLayoutBox(item)); |
342 iterator.increment(); | 348 iterator.increment(); |
(...skipping 17 matching lines...) Expand all Loading... |
360 : m_lastObject.parent().style()->whiteSpace(); | 366 : m_lastObject.parent().style()->whiteSpace(); |
361 | 367 |
362 bool isSVGText = m_current.getLineLayoutItem().isSVGInlineText(); | 368 bool isSVGText = m_current.getLineLayoutItem().isSVGInlineText(); |
363 m_autoWrap = !isSVGText && ComputedStyle::autoWrap(m_currWS); | 369 m_autoWrap = !isSVGText && ComputedStyle::autoWrap(m_currWS); |
364 m_autoWrapWasEverTrueOnLine = m_autoWrapWasEverTrueOnLine || m_autoWrap; | 370 m_autoWrapWasEverTrueOnLine = m_autoWrapWasEverTrueOnLine || m_autoWrap; |
365 | 371 |
366 m_preservesNewline = !isSVGText && ComputedStyle::preserveNewline(m_currWS); | 372 m_preservesNewline = !isSVGText && ComputedStyle::preserveNewline(m_currWS); |
367 | 373 |
368 m_collapseWhiteSpace = ComputedStyle::collapseWhiteSpace(m_currWS); | 374 m_collapseWhiteSpace = ComputedStyle::collapseWhiteSpace(m_currWS); |
369 | 375 |
370 // Ensure the whitespace in constructions like '<span style="white-space: pre-
wrap">text <span><span> text</span>' | 376 // Ensure the whitespace in constructions like '<span style="white-space: |
371 // does not collapse. | 377 // pre-wrap">text <span><span> text</span>' does not collapse. |
372 if (m_collapseWhiteSpace && !ComputedStyle::collapseWhiteSpace(m_lastWS)) | 378 if (m_collapseWhiteSpace && !ComputedStyle::collapseWhiteSpace(m_lastWS)) |
373 m_currentCharacterIsSpace = false; | 379 m_currentCharacterIsSpace = false; |
374 } | 380 } |
375 | 381 |
376 inline void BreakingContext::increment() { | 382 inline void BreakingContext::increment() { |
377 m_current.moveToStartOf(m_nextObject); | 383 m_current.moveToStartOf(m_nextObject); |
378 | 384 |
379 // When the line box tree is created, this position in the line will be snappe
d to | 385 // When the line box tree is created, this position in the line will be |
380 // LayoutUnit's, and those measurements will be used by the paint code. Do th
e | 386 // snapped to LayoutUnit's, and those measurements will be used by the paint |
381 // equivalent snapping here, to get consistent line measurements. | 387 // code. Do the equivalent snapping here, to get consistent line measurements. |
382 m_width.snapUncommittedWidth(); | 388 m_width.snapUncommittedWidth(); |
383 | 389 |
384 m_atStart = false; | 390 m_atStart = false; |
385 } | 391 } |
386 | 392 |
387 inline void BreakingContext::handleBR(EClear& clear) { | 393 inline void BreakingContext::handleBR(EClear& clear) { |
388 if (m_width.fitsOnLine()) { | 394 if (m_width.fitsOnLine()) { |
389 LineLayoutItem br = m_current.getLineLayoutItem(); | 395 LineLayoutItem br = m_current.getLineLayoutItem(); |
390 m_lineBreak.moveToStartOf(br); | 396 m_lineBreak.moveToStartOf(br); |
391 m_lineBreak.increment(); | 397 m_lineBreak.increment(); |
392 | 398 |
393 // A <br> always breaks a line, so don't let the line be collapsed | 399 // A <br> always breaks a line, so don't let the line be collapsed |
394 // away. Also, the space at the end of a line with a <br> does not | 400 // away. Also, the space at the end of a line with a <br> does not |
395 // get collapsed away. It only does this if the previous line broke | 401 // get collapsed away. It only does this if the previous line broke |
396 // cleanly. Otherwise the <br> has no effect on whether the line is | 402 // cleanly. Otherwise the <br> has no effect on whether the line is |
397 // empty or not. | 403 // empty or not. |
398 if (m_startingNewParagraph) | 404 if (m_startingNewParagraph) |
399 m_lineInfo.setEmpty(false); | 405 m_lineInfo.setEmpty(false); |
400 m_trailingObjects.clear(); | 406 m_trailingObjects.clear(); |
401 m_lineInfo.setPreviousLineBrokeCleanly(true); | 407 m_lineInfo.setPreviousLineBrokeCleanly(true); |
402 | 408 |
403 // A <br> with clearance always needs a linebox in case the lines below it g
et dirtied later and | 409 // A <br> with clearance always needs a linebox in case the lines below it |
404 // need to check for floats to clear - so if we're ignoring spaces, stop ign
oring them and add a | 410 // get dirtied later and need to check for floats to clear - so if we're |
405 // run for this object. | 411 // ignoring spaces, stop ignoring them and add a run for this object. |
406 if (m_ignoringSpaces && m_currentStyle->clear() != ClearNone) | 412 if (m_ignoringSpaces && m_currentStyle->clear() != ClearNone) |
407 ensureLineBoxInsideIgnoredSpaces(&m_lineMidpointState, br); | 413 ensureLineBoxInsideIgnoredSpaces(&m_lineMidpointState, br); |
408 | 414 |
409 if (!m_lineInfo.isEmpty()) | 415 if (!m_lineInfo.isEmpty()) |
410 clear = m_currentStyle->clear(); | 416 clear = m_currentStyle->clear(); |
411 } | 417 } |
412 m_atEnd = true; | 418 m_atEnd = true; |
413 } | 419 } |
414 | 420 |
415 inline LayoutUnit borderPaddingMarginStart(LineLayoutInline child) { | 421 inline LayoutUnit borderPaddingMarginStart(LineLayoutInline child) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 inline void BreakingContext::handleOutOfFlowPositioned( | 459 inline void BreakingContext::handleOutOfFlowPositioned( |
454 Vector<LineLayoutBox>& positionedObjects) { | 460 Vector<LineLayoutBox>& positionedObjects) { |
455 // If our original display wasn't an inline type, then we can | 461 // If our original display wasn't an inline type, then we can |
456 // go ahead and determine our static inline position now. | 462 // go ahead and determine our static inline position now. |
457 LineLayoutBox box(m_current.getLineLayoutItem()); | 463 LineLayoutBox box(m_current.getLineLayoutItem()); |
458 bool isInlineType = box.style()->isOriginalDisplayInlineType(); | 464 bool isInlineType = box.style()->isOriginalDisplayInlineType(); |
459 if (!isInlineType) { | 465 if (!isInlineType) { |
460 m_block.setStaticInlinePositionForChild(box, | 466 m_block.setStaticInlinePositionForChild(box, |
461 m_block.startOffsetForContent()); | 467 m_block.startOffsetForContent()); |
462 } else { | 468 } else { |
463 // If our original display was an INLINE type, then we can determine our sta
tic y position | 469 // If our original display was an INLINE type, then we can determine our |
464 // now. Note, however, that if we're paginated, we may have to update this p
osition after | 470 // static y position now. Note, however, that if we're paginated, we may |
465 // the line has been laid out, since the line may be pushed by a pagination
strut. | 471 // have to update this position after the line has been laid out, since the |
| 472 // line may be pushed by a pagination strut. |
466 box.layer()->setStaticBlockPosition(m_block.logicalHeight()); | 473 box.layer()->setStaticBlockPosition(m_block.logicalHeight()); |
467 } | 474 } |
468 | 475 |
469 // If we're ignoring spaces, we have to stop and include this object and | 476 // If we're ignoring spaces, we have to stop and include this object and |
470 // then start ignoring spaces again. | 477 // then start ignoring spaces again. |
471 bool containerIsInline = box.container().isLayoutInline(); | 478 bool containerIsInline = box.container().isLayoutInline(); |
472 if (isInlineType || containerIsInline) { | 479 if (isInlineType || containerIsInline) { |
473 if (m_ignoringSpaces) | 480 if (m_ignoringSpaces) |
474 ensureLineBoxInsideIgnoredSpaces(&m_lineMidpointState, box); | 481 ensureLineBoxInsideIgnoredSpaces(&m_lineMidpointState, box); |
475 m_trailingObjects.appendObjectIfNeeded(box); | 482 m_trailingObjects.appendObjectIfNeeded(box); |
476 } | 483 } |
477 if (!containerIsInline) | 484 if (!containerIsInline) |
478 positionedObjects.append(box); | 485 positionedObjects.append(box); |
479 m_width.addUncommittedWidth( | 486 m_width.addUncommittedWidth( |
480 inlineLogicalWidthFromAncestorsIfNeeded(box).toFloat()); | 487 inlineLogicalWidthFromAncestorsIfNeeded(box).toFloat()); |
481 // Reset prior line break context characters. | 488 // Reset prior line break context characters. |
482 m_layoutTextInfo.m_lineBreakIterator.resetPriorContext(); | 489 m_layoutTextInfo.m_lineBreakIterator.resetPriorContext(); |
483 } | 490 } |
484 | 491 |
485 inline void BreakingContext::handleFloat() { | 492 inline void BreakingContext::handleFloat() { |
486 LineLayoutBox floatBox(m_current.getLineLayoutItem()); | 493 LineLayoutBox floatBox(m_current.getLineLayoutItem()); |
487 FloatingObject* floatingObject = m_block.insertFloatingObject(floatBox); | 494 FloatingObject* floatingObject = m_block.insertFloatingObject(floatBox); |
488 // check if it fits in the current line. | 495 // Check if it fits in the current line; if it does, position it now, |
489 // If it does, position it now, otherwise, position | 496 // otherwise, position it after moving to next line (in newLine() func). |
490 // it after moving to next line (in newLine() func) | 497 // FIXME: Bug 110372: Properly position multiple stacked floats with |
491 // FIXME: Bug 110372: Properly position multiple stacked floats with non-recta
ngular shape outside. | 498 // non-rectangular shape outside. |
492 if (m_floatsFitOnLine && | 499 if (m_floatsFitOnLine && |
493 m_width.fitsOnLine( | 500 m_width.fitsOnLine( |
494 m_block.logicalWidthForFloat(*floatingObject).toFloat(), | 501 m_block.logicalWidthForFloat(*floatingObject).toFloat(), |
495 ExcludeWhitespace)) { | 502 ExcludeWhitespace)) { |
496 m_block.positionNewFloats(&m_width); | 503 m_block.positionNewFloats(&m_width); |
497 if (m_lineBreak.getLineLayoutItem() == m_current.getLineLayoutItem()) { | 504 if (m_lineBreak.getLineLayoutItem() == m_current.getLineLayoutItem()) { |
498 ASSERT(!m_lineBreak.offset()); | 505 ASSERT(!m_lineBreak.offset()); |
499 m_lineBreak.increment(); | 506 m_lineBreak.increment(); |
500 } | 507 } |
501 } else { | 508 } else { |
502 m_floatsFitOnLine = false; | 509 m_floatsFitOnLine = false; |
503 } | 510 } |
504 // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMEN
T CHARACTER) for floating element. | 511 // Update prior line break context characters, using U+FFFD (OBJECT |
| 512 // REPLACEMENT CHARACTER) for floating element. |
505 m_layoutTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter); | 513 m_layoutTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter); |
506 } | 514 } |
507 | 515 |
508 // This is currently just used for list markers and inline flows that have line
boxes. Neither should | 516 // This is currently just used for list markers and inline flows that have line |
509 // have an effect on whitespace at the start of the line. | 517 // boxes. Neither should have an effect on whitespace at the start of the line. |
510 inline bool shouldSkipWhitespaceAfterStartObject( | 518 inline bool shouldSkipWhitespaceAfterStartObject( |
511 LineLayoutBlockFlow block, | 519 LineLayoutBlockFlow block, |
512 LineLayoutItem o, | 520 LineLayoutItem o, |
513 LineMidpointState& lineMidpointState) { | 521 LineMidpointState& lineMidpointState) { |
514 LineLayoutItem next = bidiNextSkippingEmptyInlines(block, o); | 522 LineLayoutItem next = bidiNextSkippingEmptyInlines(block, o); |
515 while (next && next.isFloatingOrOutOfFlowPositioned()) | 523 while (next && next.isFloatingOrOutOfFlowPositioned()) |
516 next = bidiNextSkippingEmptyInlines(block, next); | 524 next = bidiNextSkippingEmptyInlines(block, next); |
517 | 525 |
518 while (next && isEmptyInline(next)) { | 526 while (next && isEmptyInline(next)) { |
519 LineLayoutItem child = LineLayoutInline(next).firstChild(); | 527 LineLayoutItem child = LineLayoutInline(next).firstChild(); |
(...skipping 14 matching lines...) Expand all Loading... |
534 } | 542 } |
535 | 543 |
536 inline void BreakingContext::handleEmptyInline() { | 544 inline void BreakingContext::handleEmptyInline() { |
537 // This should only end up being called on empty inlines | 545 // This should only end up being called on empty inlines |
538 ASSERT(m_current.getLineLayoutItem()); | 546 ASSERT(m_current.getLineLayoutItem()); |
539 | 547 |
540 LineLayoutInline flowBox(m_current.getLineLayoutItem()); | 548 LineLayoutInline flowBox(m_current.getLineLayoutItem()); |
541 | 549 |
542 bool requiresLineBox = alwaysRequiresLineBox(m_current.getLineLayoutItem()); | 550 bool requiresLineBox = alwaysRequiresLineBox(m_current.getLineLayoutItem()); |
543 if (requiresLineBox || requiresLineBoxForContent(flowBox, m_lineInfo)) { | 551 if (requiresLineBox || requiresLineBoxForContent(flowBox, m_lineInfo)) { |
544 // An empty inline that only has line-height, vertical-align or font-metrics
will | 552 // An empty inline that only has line-height, vertical-align or font-metrics |
545 // not force linebox creation (and thus affect the height of the line) if th
e rest of the line is empty. | 553 // will not force linebox creation (and thus affect the height of the line) |
| 554 // if the rest of the line is empty. |
546 if (requiresLineBox) | 555 if (requiresLineBox) |
547 m_lineInfo.setEmpty(false); | 556 m_lineInfo.setEmpty(false); |
548 if (m_ignoringSpaces) { | 557 if (m_ignoringSpaces) { |
549 // If we are in a run of ignored spaces then ensure we get a linebox if li
neboxes are eventually | 558 // If we are in a run of ignored spaces then ensure we get a linebox if |
550 // created for the line... | 559 // lineboxes are eventually created for the line... |
551 m_trailingObjects.clear(); | 560 m_trailingObjects.clear(); |
552 ensureLineBoxInsideIgnoredSpaces(&m_lineMidpointState, | 561 ensureLineBoxInsideIgnoredSpaces(&m_lineMidpointState, |
553 m_current.getLineLayoutItem()); | 562 m_current.getLineLayoutItem()); |
554 } else if (m_blockStyle->collapseWhiteSpace() && | 563 } else if (m_blockStyle->collapseWhiteSpace() && |
555 m_resolver.position().getLineLayoutItem() == | 564 m_resolver.position().getLineLayoutItem() == |
556 m_current.getLineLayoutItem() && | 565 m_current.getLineLayoutItem() && |
557 shouldSkipWhitespaceAfterStartObject( | 566 shouldSkipWhitespaceAfterStartObject( |
558 m_block, m_current.getLineLayoutItem(), | 567 m_block, m_current.getLineLayoutItem(), |
559 m_lineMidpointState)) { | 568 m_lineMidpointState)) { |
560 // If this object is at the start of the line, we need to behave like list
markers and | 569 // If this object is at the start of the line, we need to behave like list |
561 // start ignoring spaces. | 570 // markers and start ignoring spaces. |
562 m_currentCharacterIsSpace = true; | 571 m_currentCharacterIsSpace = true; |
563 m_ignoringSpaces = true; | 572 m_ignoringSpaces = true; |
564 } else { | 573 } else { |
565 // If we are after a trailing space but aren't ignoring spaces yet then en
sure we get a linebox | 574 // If we are after a trailing space but aren't ignoring spaces yet then |
566 // if we encounter collapsible whitepace. | 575 // ensure we get a linebox if we encounter collapsible whitepace. |
567 m_trailingObjects.appendObjectIfNeeded(m_current.getLineLayoutItem()); | 576 m_trailingObjects.appendObjectIfNeeded(m_current.getLineLayoutItem()); |
568 } | 577 } |
569 } | 578 } |
570 | 579 |
571 m_width.addUncommittedWidth( | 580 m_width.addUncommittedWidth( |
572 (inlineLogicalWidthFromAncestorsIfNeeded(m_current.getLineLayoutItem()) + | 581 (inlineLogicalWidthFromAncestorsIfNeeded(m_current.getLineLayoutItem()) + |
573 borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox)) | 582 borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox)) |
574 .toFloat()); | 583 .toFloat()); |
575 } | 584 } |
576 | 585 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 m_ignoringSpaces = true; | 626 m_ignoringSpaces = true; |
618 } | 627 } |
619 if (LineLayoutListMarker(m_current.getLineLayoutItem()).isInside()) | 628 if (LineLayoutListMarker(m_current.getLineLayoutItem()).isInside()) |
620 m_width.addUncommittedWidth(replacedLogicalWidth.toFloat()); | 629 m_width.addUncommittedWidth(replacedLogicalWidth.toFloat()); |
621 } else { | 630 } else { |
622 m_width.addUncommittedWidth(replacedLogicalWidth.toFloat()); | 631 m_width.addUncommittedWidth(replacedLogicalWidth.toFloat()); |
623 } | 632 } |
624 if (m_current.getLineLayoutItem().isRubyRun()) | 633 if (m_current.getLineLayoutItem().isRubyRun()) |
625 m_width.applyOverhang(LineLayoutRubyRun(m_current.getLineLayoutItem()), | 634 m_width.applyOverhang(LineLayoutRubyRun(m_current.getLineLayoutItem()), |
626 m_lastObject, m_nextObject); | 635 m_lastObject, m_nextObject); |
627 // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMEN
T CHARACTER) for replaced element. | 636 // Update prior line break context characters, using U+FFFD (OBJECT |
| 637 // REPLACEMENT CHARACTER) for replaced element. |
628 m_layoutTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter); | 638 m_layoutTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter); |
629 } | 639 } |
630 | 640 |
631 inline void nextCharacter(UChar& currentCharacter, | 641 inline void nextCharacter(UChar& currentCharacter, |
632 UChar& lastCharacter, | 642 UChar& lastCharacter, |
633 UChar& secondToLastCharacter) { | 643 UChar& secondToLastCharacter) { |
634 secondToLastCharacter = lastCharacter; | 644 secondToLastCharacter = lastCharacter; |
635 lastCharacter = currentCharacter; | 645 lastCharacter = currentCharacter; |
636 } | 646 } |
637 | 647 |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 : m_current.previousInSameNode() == softHyphenCharacter; | 871 : m_current.previousInSameNode() == softHyphenCharacter; |
862 } | 872 } |
863 | 873 |
864 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, | 874 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, |
865 bool& hyphenated) { | 875 bool& hyphenated) { |
866 if (!m_current.offset()) | 876 if (!m_current.offset()) |
867 m_appliedStartWidth = false; | 877 m_appliedStartWidth = false; |
868 | 878 |
869 LineLayoutText layoutText(m_current.getLineLayoutItem()); | 879 LineLayoutText layoutText(m_current.getLineLayoutItem()); |
870 | 880 |
871 // If we have left a no-wrap inline and entered an autowrap inline while ignor
ing spaces | 881 // If we have left a no-wrap inline and entered an autowrap inline while |
872 // then we need to mark the start of the autowrap inline as a potential linebr
eak now. | 882 // ignoring spaces then we need to mark the start of the autowrap inline as a |
| 883 // potential linebreak now. |
873 if (m_autoWrap && !ComputedStyle::autoWrap(m_lastWS) && m_ignoringSpaces) { | 884 if (m_autoWrap && !ComputedStyle::autoWrap(m_lastWS) && m_ignoringSpaces) { |
874 m_width.commit(); | 885 m_width.commit(); |
875 m_lineBreak.moveToStartOf(m_current.getLineLayoutItem()); | 886 m_lineBreak.moveToStartOf(m_current.getLineLayoutItem()); |
876 } | 887 } |
877 | 888 |
878 const ComputedStyle& style = layoutText.styleRef(m_lineInfo.isFirstLine()); | 889 const ComputedStyle& style = layoutText.styleRef(m_lineInfo.isFirstLine()); |
879 const Font& font = style.font(); | 890 const Font& font = style.font(); |
880 | 891 |
881 unsigned lastSpace = m_current.offset(); | 892 unsigned lastSpace = m_current.offset(); |
882 float wordSpacing = m_currentStyle->wordSpacing(); | 893 float wordSpacing = m_currentStyle->wordSpacing(); |
883 float lastSpaceWordSpacing = 0; | 894 float lastSpaceWordSpacing = 0; |
884 float wordSpacingForWordMeasurement = 0; | 895 float wordSpacingForWordMeasurement = 0; |
885 | 896 |
886 float widthFromLastBreakingOpportunity = m_width.uncommittedWidth(); | 897 float widthFromLastBreakingOpportunity = m_width.uncommittedWidth(); |
887 float charWidth = 0; | 898 float charWidth = 0; |
888 // Auto-wrapping text should wrap in the middle of a word only if it could not
wrap before the word, | 899 // Auto-wrapping text should wrap in the middle of a word only if it could not |
889 // which is only possible if the word is the first thing on the line, that is,
if |w| is zero. | 900 // wrap before the word, which is only possible if the word is the first thing |
| 901 // on the line, that is, if |w| is zero. |
890 bool breakWords = | 902 bool breakWords = |
891 m_currentStyle->breakWords() && | 903 m_currentStyle->breakWords() && |
892 ((m_autoWrap && !m_width.committedWidth()) || m_currWS == PRE); | 904 ((m_autoWrap && !m_width.committedWidth()) || m_currWS == PRE); |
893 bool midWordBreak = false; | 905 bool midWordBreak = false; |
894 bool breakAll = | 906 bool breakAll = |
895 m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap; | 907 m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap; |
896 bool keepAll = m_currentStyle->wordBreak() == KeepAllWordBreak && m_autoWrap; | 908 bool keepAll = m_currentStyle->wordBreak() == KeepAllWordBreak && m_autoWrap; |
897 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && | 909 bool prohibitBreakInside = m_currentStyle->hasTextCombine() && |
898 layoutText.isCombineText() && | 910 layoutText.isCombineText() && |
899 LineLayoutTextCombine(layoutText).isCombined(); | 911 LineLayoutTextCombine(layoutText).isCombined(); |
900 | 912 |
901 // This is currently only used for word-break: break-all, specifically for the
case | 913 // This is currently only used for word-break: break-all, specifically for the |
902 // where we have a break opportunity within a word, then a string of non-break
able | 914 // case where we have a break opportunity within a word, then a string of non- |
903 // content that ends up making our word wider than the current line. | 915 // breakable content that ends up making our word wider than the current line. |
904 // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html | 916 // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html |
905 float widthMeasurementAtLastBreakOpportunity = 0; | 917 float widthMeasurementAtLastBreakOpportunity = 0; |
906 | 918 |
907 Hyphenation* hyphenation = style.getHyphenation(); | 919 Hyphenation* hyphenation = style.getHyphenation(); |
908 bool disableSoftHyphen = style.getHyphens() == HyphensNone; | 920 bool disableSoftHyphen = style.getHyphens() == HyphensNone; |
909 float hyphenWidth = 0; | 921 float hyphenWidth = 0; |
910 | 922 |
911 if (layoutText.isSVGInlineText()) { | 923 if (layoutText.isSVGInlineText()) { |
912 breakWords = false; | 924 breakWords = false; |
913 breakAll = false; | 925 breakAll = false; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
978 int nextBreakablePosition = m_current.nextBreakablePosition(); | 990 int nextBreakablePosition = m_current.nextBreakablePosition(); |
979 bool betweenWords = | 991 bool betweenWords = |
980 c == newlineCharacter || | 992 c == newlineCharacter || |
981 (m_currWS != PRE && !m_atStart && | 993 (m_currWS != PRE && !m_atStart && |
982 m_layoutTextInfo.m_lineBreakIterator.isBreakable( | 994 m_layoutTextInfo.m_lineBreakIterator.isBreakable( |
983 m_current.offset(), nextBreakablePosition, lineBreakType) && | 995 m_current.offset(), nextBreakablePosition, lineBreakType) && |
984 (!disableSoftHyphen || | 996 (!disableSoftHyphen || |
985 m_current.previousInSameNode() != softHyphenCharacter)); | 997 m_current.previousInSameNode() != softHyphenCharacter)); |
986 m_current.setNextBreakablePosition(nextBreakablePosition); | 998 m_current.setNextBreakablePosition(nextBreakablePosition); |
987 | 999 |
988 // If we're in the middle of a word or at the start of a new one and can't b
reak there, then continue to the next character. | 1000 // If we're in the middle of a word or at the start of a new one and can't |
| 1001 // break there, then continue to the next character. |
989 if (!betweenWords && !midWordBreak) { | 1002 if (!betweenWords && !midWordBreak) { |
990 if (m_ignoringSpaces) { | 1003 if (m_ignoringSpaces) { |
991 // Stop ignoring spaces and begin at this | 1004 // Stop ignoring spaces and begin at this |
992 // new point. | 1005 // new point. |
993 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | 1006 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
994 wordSpacingForWordMeasurement = | 1007 wordSpacingForWordMeasurement = |
995 (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing | 1008 (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing |
996 : 0; | 1009 : 0; |
997 stopIgnoringSpaces(lastSpace); | 1010 stopIgnoringSpaces(lastSpace); |
998 } | 1011 } |
999 | 1012 |
1000 prepareForNextCharacter(layoutText, prohibitBreakInside, | 1013 prepareForNextCharacter(layoutText, prohibitBreakInside, |
1001 previousCharacterIsSpace); | 1014 previousCharacterIsSpace); |
1002 m_atStart = false; | 1015 m_atStart = false; |
1003 nextCharacter(c, lastCharacter, secondToLastCharacter); | 1016 nextCharacter(c, lastCharacter, secondToLastCharacter); |
1004 continue; | 1017 continue; |
1005 } | 1018 } |
1006 | 1019 |
1007 // If we're collapsing space and we're at a collapsible space such as a spac
e or tab, continue to the next character. | 1020 // If we're collapsing space and we're at a collapsible space such as a |
| 1021 // space or tab, continue to the next character. |
1008 if (m_ignoringSpaces && m_currentCharacterIsSpace) { | 1022 if (m_ignoringSpaces && m_currentCharacterIsSpace) { |
1009 lastSpaceWordSpacing = 0; | 1023 lastSpaceWordSpacing = 0; |
1010 // Just keep ignoring these spaces. | 1024 // Just keep ignoring these spaces. |
1011 nextCharacter(c, lastCharacter, secondToLastCharacter); | 1025 nextCharacter(c, lastCharacter, secondToLastCharacter); |
1012 continue; | 1026 continue; |
1013 } | 1027 } |
1014 | 1028 |
1015 // We're in the first whitespace after a word or in whitespace that we don't
collapse, which means we may have a breaking opportunity here. | 1029 // We're in the first whitespace after a word or in whitespace that we don't |
| 1030 // collapse, which means we may have a breaking opportunity here. |
1016 | 1031 |
1017 // If we're here and we're collapsing space then the current character isn't
a form of whitespace we can collapse. Stop ignoring spaces. | 1032 // If we're here and we're collapsing space then the current character isn't |
| 1033 // a form of whitespace we can collapse. Stop ignoring spaces. |
1018 bool stoppedIgnoringSpaces = false; | 1034 bool stoppedIgnoringSpaces = false; |
1019 if (m_ignoringSpaces) { | 1035 if (m_ignoringSpaces) { |
1020 lastSpaceWordSpacing = 0; | 1036 lastSpaceWordSpacing = 0; |
1021 wordSpacingForWordMeasurement = 0; | 1037 wordSpacingForWordMeasurement = 0; |
1022 stoppedIgnoringSpaces = true; | 1038 stoppedIgnoringSpaces = true; |
1023 stopIgnoringSpaces(lastSpace); | 1039 stopIgnoringSpaces(lastSpace); |
1024 } | 1040 } |
1025 | 1041 |
1026 // Update our tally of the width since the last breakable position with the
width of the word we're now at the end of. | 1042 // Update our tally of the width since the last breakable position with the |
| 1043 // width of the word we're now at the end of. |
1027 float lastWidthMeasurement; | 1044 float lastWidthMeasurement; |
1028 WordMeasurement& wordMeasurement = calculateWordWidth( | 1045 WordMeasurement& wordMeasurement = calculateWordWidth( |
1029 wordMeasurements, layoutText, lastSpace, lastWidthMeasurement, | 1046 wordMeasurements, layoutText, lastSpace, lastWidthMeasurement, |
1030 wordSpacingForWordMeasurement, font, wordTrailingSpaceWidth, c); | 1047 wordSpacingForWordMeasurement, font, wordTrailingSpaceWidth, c); |
1031 lastWidthMeasurement += lastSpaceWordSpacing; | 1048 lastWidthMeasurement += lastSpaceWordSpacing; |
1032 m_width.addUncommittedWidth(lastWidthMeasurement); | 1049 m_width.addUncommittedWidth(lastWidthMeasurement); |
1033 | 1050 |
1034 // We keep track of the total width contributed by trailing space as we ofte
n want to exclude it when determining | 1051 // We keep track of the total width contributed by trailing space as we |
| 1052 // often want to exclude it when determining |
1035 // if a run fits on a line. | 1053 // if a run fits on a line. |
1036 if (m_collapseWhiteSpace && previousCharacterIsSpace && | 1054 if (m_collapseWhiteSpace && previousCharacterIsSpace && |
1037 m_currentCharacterIsSpace && lastWidthMeasurement) | 1055 m_currentCharacterIsSpace && lastWidthMeasurement) |
1038 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement); | 1056 m_width.setTrailingWhitespaceWidth(lastWidthMeasurement); |
1039 | 1057 |
1040 // If this is the end of the first word in run of text then make sure we app
ly the width from any leading inlines. | 1058 // If this is the end of the first word in run of text then make sure we |
1041 // For example: '<span style="margin-left: 5px;"><span style="margin-left: 1
0px;">FirstWord</span></span>' would | 1059 // apply the width from any leading inlines. |
1042 // apply a width of 15px from the two span ancestors. | 1060 // For example: '<span style="margin-left: 5px;"><span style="margin-left: |
| 1061 // 10px;">FirstWord</span></span>' would apply a width of 15px from the two |
| 1062 // span ancestors. |
1043 if (!m_appliedStartWidth) { | 1063 if (!m_appliedStartWidth) { |
1044 m_width.addUncommittedWidth( | 1064 m_width.addUncommittedWidth( |
1045 inlineLogicalWidthFromAncestorsIfNeeded(m_current.getLineLayoutItem(), | 1065 inlineLogicalWidthFromAncestorsIfNeeded(m_current.getLineLayoutItem(), |
1046 true, false) | 1066 true, false) |
1047 .toFloat()); | 1067 .toFloat()); |
1048 m_appliedStartWidth = true; | 1068 m_appliedStartWidth = true; |
1049 } | 1069 } |
1050 | 1070 |
1051 midWordBreak = false; | 1071 midWordBreak = false; |
1052 if (!m_width.fitsOnLine()) { | 1072 if (!m_width.fitsOnLine()) { |
(...skipping 14 matching lines...) Expand all Loading... |
1067 lastSpaceWordSpacing, wordMeasurement)) { | 1087 lastSpaceWordSpacing, wordMeasurement)) { |
1068 m_width.addUncommittedWidth(wordMeasurement.width); | 1088 m_width.addUncommittedWidth(wordMeasurement.width); |
1069 hyphenated = true; | 1089 hyphenated = true; |
1070 m_atEnd = true; | 1090 m_atEnd = true; |
1071 return false; | 1091 return false; |
1072 } | 1092 } |
1073 m_width.addUncommittedWidth(wordMeasurement.width); | 1093 m_width.addUncommittedWidth(wordMeasurement.width); |
1074 } | 1094 } |
1075 } | 1095 } |
1076 | 1096 |
1077 // If we haven't hit a breakable position yet and already don't fit on the l
ine try to move below any floats. | 1097 // If we haven't hit a breakable position yet and already don't fit on the |
| 1098 // line try to move below any floats. |
1078 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && | 1099 if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && |
1079 !widthMeasurementAtLastBreakOpportunity) { | 1100 !widthMeasurementAtLastBreakOpportunity) { |
1080 float availableWidthBefore = m_width.availableWidth(); | 1101 float availableWidthBefore = m_width.availableWidth(); |
1081 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); | 1102 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
1082 // If availableWidth changes by moving the line below floats, needs to mea
sure midWordBreak again. | 1103 // If availableWidth changes by moving the line below floats, needs to |
| 1104 // measure midWordBreak again. |
1083 if (midWordBreak && availableWidthBefore != m_width.availableWidth()) | 1105 if (midWordBreak && availableWidthBefore != m_width.availableWidth()) |
1084 midWordBreak = false; | 1106 midWordBreak = false; |
1085 } | 1107 } |
1086 | 1108 |
1087 // If there is a soft-break available at this whitespace position then take
it. | 1109 // If there is a soft-break available at this whitespace position then take |
| 1110 // it. |
1088 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; | 1111 applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; |
1089 if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpaces, | 1112 if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpaces, |
1090 charWidth, hyphenated, disableSoftHyphen, | 1113 charWidth, hyphenated, disableSoftHyphen, |
1091 hyphenWidth, betweenWords, midWordBreak, | 1114 hyphenWidth, betweenWords, midWordBreak, |
1092 canBreakMidWord, previousCharacterIsSpace, | 1115 canBreakMidWord, previousCharacterIsSpace, |
1093 lastWidthMeasurement, layoutText, font, | 1116 lastWidthMeasurement, layoutText, font, |
1094 applyWordSpacing, wordSpacing)) | 1117 applyWordSpacing, wordSpacing)) |
1095 return false; | 1118 return false; |
1096 | 1119 |
1097 // If there is a hard-break available at this whitespace position then take
it. | 1120 // If there is a hard-break available at this whitespace position then take |
| 1121 // it. |
1098 if (c == newlineCharacter && m_preservesNewline) { | 1122 if (c == newlineCharacter && m_preservesNewline) { |
1099 if (!stoppedIgnoringSpaces && m_current.offset()) | 1123 if (!stoppedIgnoringSpaces && m_current.offset()) |
1100 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 1124 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
1101 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset(), | 1125 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset(), |
1102 m_current.nextBreakablePosition()); | 1126 m_current.nextBreakablePosition()); |
1103 m_lineBreak.increment(); | 1127 m_lineBreak.increment(); |
1104 m_lineInfo.setPreviousLineBrokeCleanly(true); | 1128 m_lineInfo.setPreviousLineBrokeCleanly(true); |
1105 return true; | 1129 return true; |
1106 } | 1130 } |
1107 | 1131 |
1108 // Auto-wrapping text should not wrap in the middle of a word once it has ha
d an | 1132 // Auto-wrapping text should not wrap in the middle of a word once it has |
1109 // opportunity to break after a word. | 1133 // had an opportunity to break after a word. |
1110 if (m_autoWrap && betweenWords) { | 1134 if (m_autoWrap && betweenWords) { |
1111 m_width.commit(); | 1135 m_width.commit(); |
1112 widthFromLastBreakingOpportunity = 0; | 1136 widthFromLastBreakingOpportunity = 0; |
1113 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset(), | 1137 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset(), |
1114 m_current.nextBreakablePosition()); | 1138 m_current.nextBreakablePosition()); |
1115 breakWords = false; | 1139 breakWords = false; |
1116 canBreakMidWord = breakAll; | 1140 canBreakMidWord = breakAll; |
1117 widthMeasurementAtLastBreakOpportunity = lastWidthMeasurement; | 1141 widthMeasurementAtLastBreakOpportunity = lastWidthMeasurement; |
1118 } | 1142 } |
1119 | 1143 |
1120 if (betweenWords) { | 1144 if (betweenWords) { |
1121 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; | 1145 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; |
1122 wordSpacingForWordMeasurement = | 1146 wordSpacingForWordMeasurement = |
1123 (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0; | 1147 (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0; |
1124 lastSpace = m_current.offset(); | 1148 lastSpace = m_current.offset(); |
1125 } | 1149 } |
1126 | 1150 |
1127 // If we encounter a newline, or if we encounter a second space, we need to
go ahead and break up | 1151 // If we encounter a newline, or if we encounter a second space, we need to |
1128 // this run and enter a mode where we start collapsing spaces. | 1152 // go ahead and break up this run and enter a mode where we start collapsing |
| 1153 // spaces. |
1129 if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) { | 1154 if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) { |
1130 if (m_currentCharacterIsSpace && previousCharacterIsSpace) { | 1155 if (m_currentCharacterIsSpace && previousCharacterIsSpace) { |
1131 m_ignoringSpaces = true; | 1156 m_ignoringSpaces = true; |
1132 | 1157 |
1133 // We just entered a mode where we are ignoring spaces. Create a midpoin
t to terminate the run | 1158 // We just entered a mode where we are ignoring spaces. Create a |
1134 // before the second space. | 1159 // midpoint to terminate the run before the second space. |
1135 m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces); | 1160 m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces); |
1136 m_trailingObjects.updateMidpointsForTrailingObjects( | 1161 m_trailingObjects.updateMidpointsForTrailingObjects( |
1137 m_lineMidpointState, InlineIterator(), | 1162 m_lineMidpointState, InlineIterator(), |
1138 TrailingObjects::DoNotCollapseFirstSpace); | 1163 TrailingObjects::DoNotCollapseFirstSpace); |
1139 } | 1164 } |
1140 } | 1165 } |
1141 | 1166 |
1142 prepareForNextCharacter(layoutText, prohibitBreakInside, | 1167 prepareForNextCharacter(layoutText, prohibitBreakInside, |
1143 previousCharacterIsSpace); | 1168 previousCharacterIsSpace); |
1144 m_atStart = false; | 1169 m_atStart = false; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1213 } | 1238 } |
1214 } | 1239 } |
1215 return false; | 1240 return false; |
1216 } | 1241 } |
1217 | 1242 |
1218 inline void BreakingContext::prepareForNextCharacter( | 1243 inline void BreakingContext::prepareForNextCharacter( |
1219 const LineLayoutText& layoutText, | 1244 const LineLayoutText& layoutText, |
1220 bool& prohibitBreakInside, | 1245 bool& prohibitBreakInside, |
1221 bool previousCharacterIsSpace) { | 1246 bool previousCharacterIsSpace) { |
1222 if (layoutText.isSVGInlineText() && m_current.offset()) { | 1247 if (layoutText.isSVGInlineText() && m_current.offset()) { |
1223 // Force creation of new InlineBoxes for each absolute positioned character
(those that start new text chunks). | 1248 // Force creation of new InlineBoxes for each absolute positioned character |
| 1249 // (those that start new text chunks). |
1224 if (LineLayoutSVGInlineText(layoutText) | 1250 if (LineLayoutSVGInlineText(layoutText) |
1225 .characterStartsNewTextChunk(m_current.offset())) | 1251 .characterStartsNewTextChunk(m_current.offset())) |
1226 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); | 1252 m_lineMidpointState.ensureCharacterGetsLineBox(m_current); |
1227 } | 1253 } |
1228 if (prohibitBreakInside) { | 1254 if (prohibitBreakInside) { |
1229 m_current.setNextBreakablePosition(layoutText.textLength()); | 1255 m_current.setNextBreakablePosition(layoutText.textLength()); |
1230 prohibitBreakInside = false; | 1256 prohibitBreakInside = false; |
1231 } | 1257 } |
1232 if (m_currentCharacterIsSpace && !previousCharacterIsSpace) { | 1258 if (m_currentCharacterIsSpace && !previousCharacterIsSpace) { |
1233 m_startOfIgnoredSpaces.setLineLayoutItem(m_current.getLineLayoutItem()); | 1259 m_startOfIgnoredSpaces.setLineLayoutItem(m_current.getLineLayoutItem()); |
1234 m_startOfIgnoredSpaces.setOffset(m_current.offset()); | 1260 m_startOfIgnoredSpaces.setOffset(m_current.offset()); |
1235 } | 1261 } |
1236 if (!m_currentCharacterIsSpace && previousCharacterIsSpace) { | 1262 if (!m_currentCharacterIsSpace && previousCharacterIsSpace) { |
1237 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) | 1263 if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace()) |
1238 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset(), | 1264 m_lineBreak.moveTo(m_current.getLineLayoutItem(), m_current.offset(), |
1239 m_current.nextBreakablePosition()); | 1265 m_current.nextBreakablePosition()); |
1240 } | 1266 } |
1241 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces) | 1267 if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces) |
1242 m_trailingObjects.setTrailingWhitespace( | 1268 m_trailingObjects.setTrailingWhitespace( |
1243 LineLayoutText(m_current.getLineLayoutItem())); | 1269 LineLayoutText(m_current.getLineLayoutItem())); |
1244 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace) | 1270 else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace) |
1245 m_trailingObjects.clear(); | 1271 m_trailingObjects.clear(); |
1246 } | 1272 } |
1247 | 1273 |
1248 inline void BreakingContext::stopIgnoringSpaces(unsigned& lastSpace) { | 1274 inline void BreakingContext::stopIgnoringSpaces(unsigned& lastSpace) { |
1249 m_ignoringSpaces = false; | 1275 m_ignoringSpaces = false; |
1250 lastSpace = | 1276 // e.g., "Foo goo", don't add in any of the ignored spaces. |
1251 m_current | 1277 lastSpace = m_current.offset(); |
1252 .offset(); // e.g., "Foo goo", don't add in any of the ignored spa
ces. | |
1253 m_lineMidpointState.stopIgnoringSpaces( | 1278 m_lineMidpointState.stopIgnoringSpaces( |
1254 InlineIterator(0, m_current.getLineLayoutItem(), m_current.offset())); | 1279 InlineIterator(0, m_current.getLineLayoutItem(), m_current.offset())); |
1255 } | 1280 } |
1256 | 1281 |
1257 inline WordMeasurement& BreakingContext::calculateWordWidth( | 1282 inline WordMeasurement& BreakingContext::calculateWordWidth( |
1258 WordMeasurements& wordMeasurements, | 1283 WordMeasurements& wordMeasurements, |
1259 LineLayoutText& layoutText, | 1284 LineLayoutText& layoutText, |
1260 unsigned lastSpace, | 1285 unsigned lastSpace, |
1261 float& lastWidthMeasurement, | 1286 float& lastWidthMeasurement, |
1262 float wordSpacingForWordMeasurement, | 1287 float wordSpacingForWordMeasurement, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1354 if (isBreakAtSoftHyphen() && !disableSoftHyphen) | 1379 if (isBreakAtSoftHyphen() && !disableSoftHyphen) |
1355 hyphenated = true; | 1380 hyphenated = true; |
1356 if (m_lineBreak.offset() && | 1381 if (m_lineBreak.offset() && |
1357 m_lineBreak.offset() != (unsigned)wordMeasurement.endOffset && | 1382 m_lineBreak.offset() != (unsigned)wordMeasurement.endOffset && |
1358 !wordMeasurement.width) { | 1383 !wordMeasurement.width) { |
1359 if (charWidth) { | 1384 if (charWidth) { |
1360 wordMeasurement.endOffset = m_lineBreak.offset(); | 1385 wordMeasurement.endOffset = m_lineBreak.offset(); |
1361 wordMeasurement.width = charWidth; | 1386 wordMeasurement.width = charWidth; |
1362 } | 1387 } |
1363 } | 1388 } |
1364 // Didn't fit. Jump to the end unless there's still an opportunity to collap
se whitespace. | 1389 // Didn't fit. Jump to the end unless there's still an opportunity to |
| 1390 // collapse whitespace. |
1365 if (m_ignoringSpaces || !m_collapseWhiteSpace || | 1391 if (m_ignoringSpaces || !m_collapseWhiteSpace || |
1366 !m_currentCharacterIsSpace || !previousCharacterIsSpace) { | 1392 !m_currentCharacterIsSpace || !previousCharacterIsSpace) { |
1367 m_atEnd = true; | 1393 m_atEnd = true; |
1368 return true; | 1394 return true; |
1369 } | 1395 } |
1370 } else { | 1396 } else { |
1371 if (!betweenWords || (midWordBreak && !m_autoWrap)) | 1397 if (!betweenWords || (midWordBreak && !m_autoWrap)) |
1372 m_width.addUncommittedWidth(-lastWidthMeasurement); | 1398 m_width.addUncommittedWidth(-lastWidthMeasurement); |
1373 if (hyphenWidth) { | 1399 if (hyphenWidth) { |
1374 // Subtract the width of the soft hyphen out since we fit on a line. | 1400 // Subtract the width of the soft hyphen out since we fit on a line. |
(...skipping 16 matching lines...) Expand all Loading... |
1391 } else if (m_nextObject && m_current.getLineLayoutItem().isText() && | 1417 } else if (m_nextObject && m_current.getLineLayoutItem().isText() && |
1392 m_nextObject.isText() && !m_nextObject.isBR() && | 1418 m_nextObject.isText() && !m_nextObject.isBR() && |
1393 (m_autoWrap || m_nextObject.style()->autoWrap())) { | 1419 (m_autoWrap || m_nextObject.style()->autoWrap())) { |
1394 if (m_autoWrap && m_currentCharacterIsSpace) { | 1420 if (m_autoWrap && m_currentCharacterIsSpace) { |
1395 checkForBreak = true; | 1421 checkForBreak = true; |
1396 } else { | 1422 } else { |
1397 LineLayoutText nextText(m_nextObject); | 1423 LineLayoutText nextText(m_nextObject); |
1398 if (nextText.textLength()) { | 1424 if (nextText.textLength()) { |
1399 UChar c = nextText.characterAt(0); | 1425 UChar c = nextText.characterAt(0); |
1400 // If the next item on the line is text, and if we did not end with | 1426 // If the next item on the line is text, and if we did not end with |
1401 // a space, then the next text run continues our word (and so it needs t
o | 1427 // a space, then the next text run continues our word (and so it needs |
1402 // keep adding to the uncommitted width. Just update and continue. | 1428 // to keep adding to the uncommitted width. Just update and continue. |
1403 checkForBreak = | 1429 checkForBreak = |
1404 !m_currentCharacterIsSpace && | 1430 !m_currentCharacterIsSpace && |
1405 (c == spaceCharacter || c == tabulationCharacter || | 1431 (c == spaceCharacter || c == tabulationCharacter || |
1406 (c == newlineCharacter && !m_nextObject.preservesNewline())); | 1432 (c == newlineCharacter && !m_nextObject.preservesNewline())); |
1407 } else if (nextText.isWordBreak()) { | 1433 } else if (nextText.isWordBreak()) { |
1408 checkForBreak = true; | 1434 checkForBreak = true; |
1409 } | 1435 } |
1410 | 1436 |
1411 if (!m_width.fitsOnLine() && !m_width.committedWidth()) | 1437 if (!m_width.fitsOnLine() && !m_width.committedWidth()) |
1412 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); | 1438 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
(...skipping 14 matching lines...) Expand all Loading... |
1427 m_currentStyle->collapseWhiteSpace()) | 1453 m_currentStyle->collapseWhiteSpace()) |
1428 m_trailingObjects.clear(); | 1454 m_trailingObjects.clear(); |
1429 | 1455 |
1430 if (m_width.committedWidth()) { | 1456 if (m_width.committedWidth()) { |
1431 m_atEnd = true; | 1457 m_atEnd = true; |
1432 return; | 1458 return; |
1433 } | 1459 } |
1434 | 1460 |
1435 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); | 1461 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
1436 | 1462 |
1437 // |width| may have been adjusted because we got shoved down past a float (t
hus | 1463 // |width| may have been adjusted because we got shoved down past a float |
1438 // giving us more room), so we need to retest, and only jump to | 1464 // (thus giving us more room), so we need to retest, and only jump to the |
1439 // the end label if we still don't fit on the line. -dwh | 1465 // the end label if we still don't fit on the line. -dwh |
1440 if (!m_width.fitsOnLine()) { | 1466 if (!m_width.fitsOnLine()) { |
1441 m_atEnd = true; | 1467 m_atEnd = true; |
1442 return; | 1468 return; |
1443 } | 1469 } |
1444 } else if (m_blockStyle->autoWrap() && !m_width.fitsOnLine() && | 1470 } else if (m_blockStyle->autoWrap() && !m_width.fitsOnLine() && |
1445 !m_width.committedWidth()) { | 1471 !m_width.committedWidth()) { |
1446 // If the container autowraps but the current child does not then we still n
eed to ensure that it | 1472 // If the container autowraps but the current child does not then we still |
1447 // wraps and moves below any floats. | 1473 // need to ensure that it wraps and moves below any floats. |
1448 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); | 1474 m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
1449 } | 1475 } |
1450 | 1476 |
1451 if (!m_current.getLineLayoutItem().isFloatingOrOutOfFlowPositioned()) { | 1477 if (!m_current.getLineLayoutItem().isFloatingOrOutOfFlowPositioned()) { |
1452 m_lastObject = m_current.getLineLayoutItem(); | 1478 m_lastObject = m_current.getLineLayoutItem(); |
1453 if (m_lastObject.isAtomicInlineLevel() && m_autoWrap && | 1479 if (m_lastObject.isAtomicInlineLevel() && m_autoWrap && |
1454 (!m_lastObject.isImage() || m_allowImagesToBreak) && | 1480 (!m_lastObject.isImage() || m_allowImagesToBreak) && |
1455 (!m_lastObject.isListMarker() || | 1481 (!m_lastObject.isListMarker() || |
1456 LineLayoutListMarker(m_lastObject).isInside()) && | 1482 LineLayoutListMarker(m_lastObject).isInside()) && |
1457 !m_lastObject.isRubyRun()) { | 1483 !m_lastObject.isRubyRun()) { |
(...skipping 13 matching lines...) Expand all Loading... |
1471 | 1497 |
1472 if (style.getTextIndentType() == TextIndentHanging) | 1498 if (style.getTextIndentType() == TextIndentHanging) |
1473 indentText = indentText == IndentText ? DoNotIndentText : IndentText; | 1499 indentText = indentText == IndentText ? DoNotIndentText : IndentText; |
1474 | 1500 |
1475 return indentText; | 1501 return indentText; |
1476 } | 1502 } |
1477 | 1503 |
1478 } // namespace blink | 1504 } // namespace blink |
1479 | 1505 |
1480 #endif // BreakingContextInlineHeaders_h | 1506 #endif // BreakingContextInlineHeaders_h |
OLD | NEW |