OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. |
| 3 * All rights reserved. |
3 * | 4 * |
4 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
8 * | 9 * |
9 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 * Library General Public License for more details. | 13 * Library General Public License for more details. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 (parentStyle.verticalAlign() != VerticalAlignBaseline && | 128 (parentStyle.verticalAlign() != VerticalAlignBaseline && |
128 !isRootInlineBox()) || | 129 !isRootInlineBox()) || |
129 childStyle.verticalAlign() != VerticalAlignBaseline) | 130 childStyle.verticalAlign() != VerticalAlignBaseline) |
130 shouldClearDescendantsHaveSameLineHeightAndBaseline = true; | 131 shouldClearDescendantsHaveSameLineHeightAndBaseline = true; |
131 } | 132 } |
132 if (childStyle.hasTextCombine() || | 133 if (childStyle.hasTextCombine() || |
133 childStyle.getTextEmphasisMark() != TextEmphasisMarkNone) | 134 childStyle.getTextEmphasisMark() != TextEmphasisMarkNone) |
134 shouldClearDescendantsHaveSameLineHeightAndBaseline = true; | 135 shouldClearDescendantsHaveSameLineHeightAndBaseline = true; |
135 } else { | 136 } else { |
136 if (child->getLineLayoutItem().isBR()) { | 137 if (child->getLineLayoutItem().isBR()) { |
137 // FIXME: This is dumb. We only turn off because current layout test res
ults expect the <br> to be 0-height on the baseline. | 138 // FIXME: This is dumb. We only turn off because current layout test |
138 // Other than making a zillion tests have to regenerate results, there's
no reason to ditch the optimization here. | 139 // results expect the <br> to be 0-height on the baseline. |
| 140 // Other than making a zillion tests have to regenerate results, there's |
| 141 // no reason to ditch the optimization here. |
139 shouldClearDescendantsHaveSameLineHeightAndBaseline = true; | 142 shouldClearDescendantsHaveSameLineHeightAndBaseline = true; |
140 } else { | 143 } else { |
141 ASSERT(isInlineFlowBox()); | 144 ASSERT(isInlineFlowBox()); |
142 InlineFlowBox* childFlowBox = toInlineFlowBox(child); | 145 InlineFlowBox* childFlowBox = toInlineFlowBox(child); |
143 // Check the child's bit, and then also check for differences in font, l
ine-height, vertical-align | 146 // Check the child's bit, and then also check for differences in font, |
| 147 // line-height, vertical-align |
144 if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline() || | 148 if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline() || |
145 !parentStyle.font() | 149 !parentStyle.font() |
146 .getFontMetrics() | 150 .getFontMetrics() |
147 .hasIdenticalAscentDescentAndLineGap( | 151 .hasIdenticalAscentDescentAndLineGap( |
148 childStyle.font().getFontMetrics()) || | 152 childStyle.font().getFontMetrics()) || |
149 parentStyle.lineHeight() != childStyle.lineHeight() || | 153 parentStyle.lineHeight() != childStyle.lineHeight() || |
150 (parentStyle.verticalAlign() != VerticalAlignBaseline && | 154 (parentStyle.verticalAlign() != VerticalAlignBaseline && |
151 !isRootInlineBox()) || | 155 !isRootInlineBox()) || |
152 childStyle.verticalAlign() != VerticalAlignBaseline || | 156 childStyle.verticalAlign() != VerticalAlignBaseline || |
153 childStyle.hasBorder() || childStyle.hasPadding() || | 157 childStyle.hasBorder() || childStyle.hasPadding() || |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 lineBoxes()->attachLineBox(this); | 270 lineBoxes()->attachLineBox(this); |
267 } | 271 } |
268 | 272 |
269 void InlineFlowBox::move(const LayoutSize& delta) { | 273 void InlineFlowBox::move(const LayoutSize& delta) { |
270 InlineBox::move(delta); | 274 InlineBox::move(delta); |
271 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { | 275 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { |
272 if (child->getLineLayoutItem().isOutOfFlowPositioned()) | 276 if (child->getLineLayoutItem().isOutOfFlowPositioned()) |
273 continue; | 277 continue; |
274 child->move(delta); | 278 child->move(delta); |
275 } | 279 } |
276 if (m_overflow) | 280 if (m_overflow) { |
277 m_overflow->move( | 281 // FIXME: Rounding error here since overflow was pixel snapped, but nobody |
278 delta.width(), | 282 // other than list markers passes non-integral values here. |
279 delta | 283 m_overflow->move(delta.width(), delta.height()); |
280 .height()); // FIXME: Rounding error here since overflow was pixel
snapped, but nobody other than list markers passes non-integral values here. | 284 } |
281 } | 285 } |
282 | 286 |
283 LineBoxList* InlineFlowBox::lineBoxes() const { | 287 LineBoxList* InlineFlowBox::lineBoxes() const { |
284 return LineLayoutInline(getLineLayoutItem()).lineBoxes(); | 288 return LineLayoutInline(getLineLayoutItem()).lineBoxes(); |
285 } | 289 } |
286 | 290 |
287 static inline bool isLastChildForLayoutObject(LineLayoutItem ancestor, | 291 static inline bool isLastChildForLayoutObject(LineLayoutItem ancestor, |
288 LineLayoutItem child) { | 292 LineLayoutItem child) { |
289 if (!child) | 293 if (!child) |
290 return false; | 294 return false; |
(...skipping 24 matching lines...) Expand all Loading... |
315 return true; | 319 return true; |
316 item = item.parent(); | 320 item = item.parent(); |
317 } | 321 } |
318 return false; | 322 return false; |
319 } | 323 } |
320 | 324 |
321 void InlineFlowBox::determineSpacingForFlowBoxes( | 325 void InlineFlowBox::determineSpacingForFlowBoxes( |
322 bool lastLine, | 326 bool lastLine, |
323 bool isLogicallyLastRunWrapped, | 327 bool isLogicallyLastRunWrapped, |
324 LineLayoutItem logicallyLastRunLayoutObject) { | 328 LineLayoutItem logicallyLastRunLayoutObject) { |
325 // All boxes start off open. They will not apply any margins/border/padding o
n | 329 // All boxes start off open. They will not apply any margins/border/padding |
326 // any side. | 330 // on any side. |
327 bool includeLeftEdge = false; | 331 bool includeLeftEdge = false; |
328 bool includeRightEdge = false; | 332 bool includeRightEdge = false; |
329 | 333 |
330 // The root inline box never has borders/margins/padding. | 334 // The root inline box never has borders/margins/padding. |
331 if (parent()) { | 335 if (parent()) { |
332 bool ltr = getLineLayoutItem().style()->isLeftToRightDirection(); | 336 bool ltr = getLineLayoutItem().style()->isLeftToRightDirection(); |
333 | 337 |
334 // Check to see if all initial lines are unconstructed. If so, then | 338 // Check to see if all initial lines are unconstructed. If so, then |
335 // we know the inline began on this line (unless we are a continuation). | 339 // we know the inline began on this line (unless we are a continuation). |
336 LineBoxList* lineBoxList = lineBoxes(); | 340 LineBoxList* lineBoxList = lineBoxes(); |
(...skipping 12 matching lines...) Expand all Loading... |
349 LineLayoutInline inlineFlow = LineLayoutInline(getLineLayoutItem()); | 353 LineLayoutInline inlineFlow = LineLayoutInline(getLineLayoutItem()); |
350 LineLayoutItem logicallyLastRunLayoutItem(logicallyLastRunLayoutObject); | 354 LineLayoutItem logicallyLastRunLayoutItem(logicallyLastRunLayoutObject); |
351 bool isLastObjectOnLine = | 355 bool isLastObjectOnLine = |
352 !isAncestorAndWithinBlock(getLineLayoutItem(), | 356 !isAncestorAndWithinBlock(getLineLayoutItem(), |
353 logicallyLastRunLayoutItem) || | 357 logicallyLastRunLayoutItem) || |
354 (isLastChildForLayoutObject(getLineLayoutItem(), | 358 (isLastChildForLayoutObject(getLineLayoutItem(), |
355 logicallyLastRunLayoutItem) && | 359 logicallyLastRunLayoutItem) && |
356 !isLogicallyLastRunWrapped); | 360 !isLogicallyLastRunWrapped); |
357 | 361 |
358 // We include the border under these conditions: | 362 // We include the border under these conditions: |
359 // (1) The next line was not created, or it is constructed. We check the p
revious line for rtl. | 363 // (1) The next line was not created, or it is constructed. We check the |
| 364 // previous line for rtl. |
360 // (2) The logicallyLastRun is not a descendant of this layout object. | 365 // (2) The logicallyLastRun is not a descendant of this layout object. |
361 // (3) The logicallyLastRun is a descendant of this layout object, but it
is the last child of this layout object and it does not wrap to the next line. | 366 // (3) The logicallyLastRun is a descendant of this layout object, but it |
362 // (4) The decoration break is set to clone therefore there will be border
s on every sides. | 367 // is the last child of this layout object and it does not wrap to the |
| 368 // next line. |
| 369 // (4) The decoration break is set to clone therefore there will be |
| 370 // borders on every sides. |
363 if (getLineLayoutItem().style()->boxDecorationBreak() == | 371 if (getLineLayoutItem().style()->boxDecorationBreak() == |
364 BoxDecorationBreakClone) { | 372 BoxDecorationBreakClone) { |
365 includeLeftEdge = includeRightEdge = true; | 373 includeLeftEdge = includeRightEdge = true; |
366 } else if (ltr) { | 374 } else if (ltr) { |
367 if (!nextLineBox() && | 375 if (!nextLineBox() && |
368 ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation())) | 376 ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation())) |
369 includeRightEdge = true; | 377 includeRightEdge = true; |
370 } else { | 378 } else { |
371 if ((!prevLineBox() || prevLineBox()->isConstructed()) && | 379 if ((!prevLineBox() || prevLineBox()->isConstructed()) && |
372 ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation())) | 380 ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation())) |
(...skipping 29 matching lines...) Expand all Loading... |
402 placeBoxRangeInInlineDirection(firstChild(), nullptr, logicalLeft, | 410 placeBoxRangeInInlineDirection(firstChild(), nullptr, logicalLeft, |
403 minLogicalLeft, maxLogicalRight, | 411 minLogicalLeft, maxLogicalRight, |
404 needsWordSpacing); | 412 needsWordSpacing); |
405 | 413 |
406 logicalLeft += borderLogicalRight() + paddingLogicalRight(); | 414 logicalLeft += borderLogicalRight() + paddingLogicalRight(); |
407 endPlacingBoxRangesInInlineDirection(startLogicalLeft, logicalLeft, | 415 endPlacingBoxRangesInInlineDirection(startLogicalLeft, logicalLeft, |
408 minLogicalLeft, maxLogicalRight); | 416 minLogicalLeft, maxLogicalRight); |
409 return logicalLeft; | 417 return logicalLeft; |
410 } | 418 } |
411 | 419 |
412 // TODO(wkorman): needsWordSpacing may not need to be a reference in the below.
Seek a test case. | 420 // TODO(wkorman): needsWordSpacing may not need to be a reference in the below. |
| 421 // Seek a test case. |
413 void InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, | 422 void InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, |
414 InlineBox* lastChild, | 423 InlineBox* lastChild, |
415 LayoutUnit& logicalLeft, | 424 LayoutUnit& logicalLeft, |
416 LayoutUnit& minLogicalLeft, | 425 LayoutUnit& minLogicalLeft, |
417 LayoutUnit& maxLogicalRight, | 426 LayoutUnit& maxLogicalRight, |
418 bool& needsWordSpacing) { | 427 bool& needsWordSpacing) { |
419 for (InlineBox* curr = firstChild; curr && curr != lastChild; | 428 for (InlineBox* curr = firstChild; curr && curr != lastChild; |
420 curr = curr->nextOnLine()) { | 429 curr = curr->nextOnLine()) { |
421 if (curr->getLineLayoutItem().isText()) { | 430 if (curr->getLineLayoutItem().isText()) { |
422 InlineTextBox* text = toInlineTextBox(curr); | 431 InlineTextBox* text = toInlineTextBox(curr); |
(...skipping 20 matching lines...) Expand all Loading... |
443 if (knownToHaveNoOverflow()) | 452 if (knownToHaveNoOverflow()) |
444 maxLogicalRight = std::max(logicalLeft, maxLogicalRight); | 453 maxLogicalRight = std::max(logicalLeft, maxLogicalRight); |
445 } else { | 454 } else { |
446 if (curr->getLineLayoutItem().isOutOfFlowPositioned()) { | 455 if (curr->getLineLayoutItem().isOutOfFlowPositioned()) { |
447 if (curr->getLineLayoutItem() | 456 if (curr->getLineLayoutItem() |
448 .parent() | 457 .parent() |
449 .style() | 458 .style() |
450 ->isLeftToRightDirection()) { | 459 ->isLeftToRightDirection()) { |
451 curr->setLogicalLeft(logicalLeft); | 460 curr->setLogicalLeft(logicalLeft); |
452 } else { | 461 } else { |
453 // Our offset that we cache needs to be from the edge of the right bor
der box and | 462 // Our offset that we cache needs to be from the edge of the right |
454 // not the left border box. We have to subtract |x| from the width of
the block | 463 // border box and not the left border box. We have to subtract |x| |
455 // (which can be obtained from the root line box). | 464 // from the width of the block (which can be obtained from the root |
| 465 // line box). |
456 curr->setLogicalLeft(root().block().logicalWidth() - logicalLeft); | 466 curr->setLogicalLeft(root().block().logicalWidth() - logicalLeft); |
457 } | 467 } |
458 continue; // The positioned object has no effect on the width. | 468 continue; // The positioned object has no effect on the width. |
459 } | 469 } |
460 if (curr->getLineLayoutItem().isLayoutInline()) { | 470 if (curr->getLineLayoutItem().isLayoutInline()) { |
461 InlineFlowBox* flow = toInlineFlowBox(curr); | 471 InlineFlowBox* flow = toInlineFlowBox(curr); |
462 logicalLeft += flow->marginLogicalLeft(); | 472 logicalLeft += flow->marginLogicalLeft(); |
463 if (knownToHaveNoOverflow()) | 473 if (knownToHaveNoOverflow()) |
464 minLogicalLeft = std::min(logicalLeft, minLogicalLeft); | 474 minLogicalLeft = std::min(logicalLeft, minLogicalLeft); |
465 logicalLeft = | 475 logicalLeft = |
466 flow->placeBoxesInInlineDirection(logicalLeft, needsWordSpacing); | 476 flow->placeBoxesInInlineDirection(logicalLeft, needsWordSpacing); |
467 if (knownToHaveNoOverflow()) | 477 if (knownToHaveNoOverflow()) |
468 maxLogicalRight = std::max(logicalLeft, maxLogicalRight); | 478 maxLogicalRight = std::max(logicalLeft, maxLogicalRight); |
469 logicalLeft += flow->marginLogicalRight(); | 479 logicalLeft += flow->marginLogicalRight(); |
470 } else if (!curr->getLineLayoutItem().isListMarker() || | 480 } else if (!curr->getLineLayoutItem().isListMarker() || |
471 LineLayoutListMarker(curr->getLineLayoutItem()).isInside()) { | 481 LineLayoutListMarker(curr->getLineLayoutItem()).isInside()) { |
472 // The box can have a different writing-mode than the overall line, so t
his is a bit complicated. | 482 // The box can have a different writing-mode than the overall line, so |
473 // Just get all the physical margin and overflow values by hand based of
f |isHorizontal|. | 483 // this is a bit complicated. Just get all the physical margin and |
| 484 // overflow values by hand based off |isHorizontal|. |
474 LineLayoutBoxModel box = curr->boxModelObject(); | 485 LineLayoutBoxModel box = curr->boxModelObject(); |
475 LayoutUnit logicalLeftMargin; | 486 LayoutUnit logicalLeftMargin; |
476 LayoutUnit logicalRightMargin; | 487 LayoutUnit logicalRightMargin; |
477 if (isHorizontal()) { | 488 if (isHorizontal()) { |
478 logicalLeftMargin = box.marginLeft(); | 489 logicalLeftMargin = box.marginLeft(); |
479 logicalRightMargin = box.marginRight(); | 490 logicalRightMargin = box.marginRight(); |
480 } else { | 491 } else { |
481 logicalLeftMargin = box.marginTop(); | 492 logicalLeftMargin = box.marginTop(); |
482 logicalRightMargin = box.marginBottom(); | 493 logicalRightMargin = box.marginBottom(); |
483 } | 494 } |
484 | 495 |
485 logicalLeft += logicalLeftMargin; | 496 logicalLeft += logicalLeftMargin; |
486 curr->setLogicalLeft(logicalLeft); | 497 curr->setLogicalLeft(logicalLeft); |
487 if (knownToHaveNoOverflow()) | 498 if (knownToHaveNoOverflow()) |
488 minLogicalLeft = std::min(logicalLeft, minLogicalLeft); | 499 minLogicalLeft = std::min(logicalLeft, minLogicalLeft); |
489 logicalLeft += curr->logicalWidth(); | 500 logicalLeft += curr->logicalWidth(); |
490 if (knownToHaveNoOverflow()) | 501 if (knownToHaveNoOverflow()) |
491 maxLogicalRight = std::max(logicalLeft, maxLogicalRight); | 502 maxLogicalRight = std::max(logicalLeft, maxLogicalRight); |
492 logicalLeft += logicalRightMargin; | 503 logicalLeft += logicalRightMargin; |
493 // If we encounter any space after this inline block then ensure it is t
reated as the space between two words. | 504 // If we encounter any space after this inline block then ensure it is |
| 505 // treated as the space between two words. |
494 needsWordSpacing = true; | 506 needsWordSpacing = true; |
495 } | 507 } |
496 } | 508 } |
497 } | 509 } |
498 } | 510 } |
499 | 511 |
500 FontBaseline InlineFlowBox::dominantBaseline() const { | 512 FontBaseline InlineFlowBox::dominantBaseline() const { |
501 // Use "central" (Ideographic) baseline if writing-mode is vertical-* and text
-orientation is not sideways-*. | 513 // Use "central" (Ideographic) baseline if writing-mode is vertical-* and |
| 514 // text-orientation is not sideways-*. |
502 // http://dev.w3.org/csswg/css-writing-modes-3/#text-baselines | 515 // http://dev.w3.org/csswg/css-writing-modes-3/#text-baselines |
503 if (!isHorizontal() && | 516 if (!isHorizontal() && |
504 getLineLayoutItem() | 517 getLineLayoutItem() |
505 .style(isFirstLineStyle()) | 518 .style(isFirstLineStyle()) |
506 ->getFontDescription() | 519 ->getFontDescription() |
507 .isVerticalAnyUpright()) | 520 .isVerticalAnyUpright()) |
508 return IdeographicBaseline; | 521 return IdeographicBaseline; |
509 return AlphabeticBaseline; | 522 return AlphabeticBaseline; |
510 } | 523 } |
511 | 524 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 LayoutUnit& maxPositionTop, | 561 LayoutUnit& maxPositionTop, |
549 LayoutUnit& maxPositionBottom, | 562 LayoutUnit& maxPositionBottom, |
550 int& maxAscent, | 563 int& maxAscent, |
551 int& maxDescent, | 564 int& maxDescent, |
552 bool& setMaxAscent, | 565 bool& setMaxAscent, |
553 bool& setMaxDescent, | 566 bool& setMaxDescent, |
554 bool noQuirksMode, | 567 bool noQuirksMode, |
555 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, | 568 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, |
556 FontBaseline baselineType, | 569 FontBaseline baselineType, |
557 VerticalPositionCache& verticalPositionCache) { | 570 VerticalPositionCache& verticalPositionCache) { |
558 // The primary purpose of this function is to compute the maximal ascent and d
escent values for | 571 // The primary purpose of this function is to compute the maximal ascent and |
559 // a line. | 572 // descent values for a line. |
560 // | 573 // |
561 // The maxAscent value represents the distance of the highest point of any box
(typically including line-height) from | 574 // The maxAscent value represents the distance of the highest point of any box |
562 // the root box's baseline. The maxDescent value represents the distance of th
e lowest point of any box | 575 // (typically including line-height) from the root box's baseline. The |
563 // (also typically including line-height) from the root box baseline. These va
lues can be negative. | 576 // maxDescent value represents the distance of the lowest point of any box |
| 577 // (also typically including line-height) from the root box baseline. These |
| 578 // values can be negative. |
564 // | 579 // |
565 // A secondary purpose of this function is to store the offset of every box's
baseline from the root box's | 580 // A secondary purpose of this function is to store the offset of every box's |
566 // baseline. This information is cached in the logicalTop() of every box. We'r
e effectively just using | 581 // baseline from the root box's baseline. This information is cached in the |
567 // the logicalTop() as scratch space. | 582 // logicalTop() of every box. We're effectively just using the logicalTop() as |
| 583 // scratch space. |
568 // | 584 // |
569 // Because a box can be positioned such that it ends up fully above or fully b
elow the | 585 // Because a box can be positioned such that it ends up fully above or fully |
570 // root line box, we only consider it to affect the maxAscent and maxDescent v
alues if some | 586 // below the root line box, we only consider it to affect the maxAscent and |
571 // part of the box (EXCLUDING leading) is above (for ascent) or below (for des
cent) the root box's baseline. | 587 // maxDescent values if some part of the box (EXCLUDING leading) is above (for |
| 588 // ascent) or below (for descent) the root box's baseline. |
572 bool affectsAscent = false; | 589 bool affectsAscent = false; |
573 bool affectsDescent = false; | 590 bool affectsDescent = false; |
574 bool checkChildren = !descendantsHaveSameLineHeightAndBaseline(); | 591 bool checkChildren = !descendantsHaveSameLineHeightAndBaseline(); |
575 | 592 |
576 if (isRootInlineBox()) { | 593 if (isRootInlineBox()) { |
577 // Examine our root box. | 594 // Examine our root box. |
578 int ascent = 0; | 595 int ascent = 0; |
579 int descent = 0; | 596 int descent = 0; |
580 rootBox->ascentAndDescentForBox(rootBox, textBoxDataMap, ascent, descent, | 597 rootBox->ascentAndDescentForBox(rootBox, textBoxDataMap, ascent, descent, |
581 affectsAscent, affectsDescent); | 598 affectsAscent, affectsDescent); |
(...skipping 16 matching lines...) Expand all Loading... |
598 for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { | 615 for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { |
599 if (curr->getLineLayoutItem().isOutOfFlowPositioned()) | 616 if (curr->getLineLayoutItem().isOutOfFlowPositioned()) |
600 continue; // Positioned placeholders don't affect calculations. | 617 continue; // Positioned placeholders don't affect calculations. |
601 | 618 |
602 InlineFlowBox* inlineFlowBox = | 619 InlineFlowBox* inlineFlowBox = |
603 curr->isInlineFlowBox() ? toInlineFlowBox(curr) : nullptr; | 620 curr->isInlineFlowBox() ? toInlineFlowBox(curr) : nullptr; |
604 | 621 |
605 bool affectsAscent = false; | 622 bool affectsAscent = false; |
606 bool affectsDescent = false; | 623 bool affectsDescent = false; |
607 | 624 |
608 // The verticalPositionForBox function returns the distance between the chil
d box's baseline | 625 // The verticalPositionForBox function returns the distance between the |
609 // and the root box's baseline. The value is negative if the child box's ba
seline is above the | 626 // child box's baseline and the root box's baseline. The value is negative |
610 // root box's baseline, and it is positive if the child box's baseline is be
low the root box's baseline. | 627 // if the child box's baseline is above the root box's baseline, and it is |
| 628 // positive if the child box's baseline is below the root box's baseline. |
611 curr->setLogicalTop( | 629 curr->setLogicalTop( |
612 rootBox->verticalPositionForBox(curr, verticalPositionCache)); | 630 rootBox->verticalPositionForBox(curr, verticalPositionCache)); |
613 | 631 |
614 int ascent = 0; | 632 int ascent = 0; |
615 int descent = 0; | 633 int descent = 0; |
616 rootBox->ascentAndDescentForBox(curr, textBoxDataMap, ascent, descent, | 634 rootBox->ascentAndDescentForBox(curr, textBoxDataMap, ascent, descent, |
617 affectsAscent, affectsDescent); | 635 affectsAscent, affectsDescent); |
618 | 636 |
619 LayoutUnit boxHeight(ascent + descent); | 637 LayoutUnit boxHeight(ascent + descent); |
620 if (curr->verticalAlign() == VerticalAlignTop) { | 638 if (curr->verticalAlign() == VerticalAlignTop) { |
621 if (maxPositionTop < boxHeight) | 639 if (maxPositionTop < boxHeight) |
622 maxPositionTop = boxHeight; | 640 maxPositionTop = boxHeight; |
623 } else if (curr->verticalAlign() == VerticalAlignBottom) { | 641 } else if (curr->verticalAlign() == VerticalAlignBottom) { |
624 if (maxPositionBottom < boxHeight) | 642 if (maxPositionBottom < boxHeight) |
625 maxPositionBottom = boxHeight; | 643 maxPositionBottom = boxHeight; |
626 } else if (!inlineFlowBox || noQuirksMode || | 644 } else if (!inlineFlowBox || noQuirksMode || |
627 inlineFlowBox->hasTextChildren() || | 645 inlineFlowBox->hasTextChildren() || |
628 (inlineFlowBox->descendantsHaveSameLineHeightAndBaseline() && | 646 (inlineFlowBox->descendantsHaveSameLineHeightAndBaseline() && |
629 inlineFlowBox->hasTextDescendants()) || | 647 inlineFlowBox->hasTextDescendants()) || |
630 inlineFlowBox->boxModelObject() | 648 inlineFlowBox->boxModelObject() |
631 .hasInlineDirectionBordersOrPadding()) { | 649 .hasInlineDirectionBordersOrPadding()) { |
632 // Note that these values can be negative. Even though we only affect the
maxAscent and maxDescent values | 650 // Note that these values can be negative. Even though we only affect the |
633 // if our box (excluding line-height) was above (for ascent) or below (for
descent) the root baseline, once you factor in line-height | 651 // maxAscent and maxDescent values if our box (excluding line-height) was |
634 // the final box can end up being fully above or fully below the root box'
s baseline! This is ok, but what it | 652 // above (for ascent) or below (for descent) the root baseline, once you |
635 // means is that ascent and descent (including leading), can end up being
negative. The setMaxAscent and | 653 // factor in line-height the final box can end up being fully above or |
636 // setMaxDescent booleans are used to ensure that we're willing to initial
ly set maxAscent/Descent to negative | 654 // fully below the root box's baseline! This is ok, but what it means is |
637 // values. | 655 // that ascent and descent (including leading), can end up being negative. |
| 656 // The setMaxAscent and setMaxDescent booleans are used to ensure that |
| 657 // we're willing to initially set maxAscent/Descent to negative values. |
638 ascent -= curr->logicalTop().round(); | 658 ascent -= curr->logicalTop().round(); |
639 descent += curr->logicalTop().round(); | 659 descent += curr->logicalTop().round(); |
640 if (affectsAscent && (maxAscent < ascent || !setMaxAscent)) { | 660 if (affectsAscent && (maxAscent < ascent || !setMaxAscent)) { |
641 maxAscent = ascent; | 661 maxAscent = ascent; |
642 setMaxAscent = true; | 662 setMaxAscent = true; |
643 } | 663 } |
644 | 664 |
645 if (affectsDescent && (maxDescent < descent || !setMaxDescent)) { | 665 if (affectsDescent && (maxDescent < descent || !setMaxDescent)) { |
646 maxDescent = descent; | 666 maxDescent = descent; |
647 setMaxDescent = true; | 667 setMaxDescent = true; |
(...skipping 19 matching lines...) Expand all Loading... |
667 bool& setLineTop, | 687 bool& setLineTop, |
668 LayoutUnit& lineTopIncludingMargins, | 688 LayoutUnit& lineTopIncludingMargins, |
669 LayoutUnit& lineBottomIncludingMargins, | 689 LayoutUnit& lineBottomIncludingMargins, |
670 bool& hasAnnotationsBefore, | 690 bool& hasAnnotationsBefore, |
671 bool& hasAnnotationsAfter, | 691 bool& hasAnnotationsAfter, |
672 FontBaseline baselineType) { | 692 FontBaseline baselineType) { |
673 bool isRootBox = isRootInlineBox(); | 693 bool isRootBox = isRootInlineBox(); |
674 if (isRootBox) { | 694 if (isRootBox) { |
675 const FontMetrics& fontMetrics = | 695 const FontMetrics& fontMetrics = |
676 getLineLayoutItem().style(isFirstLineStyle())->getFontMetrics(); | 696 getLineLayoutItem().style(isFirstLineStyle())->getFontMetrics(); |
677 // RootInlineBoxes are always placed at pixel boundaries in their logical y
direction. Not doing | 697 // RootInlineBoxes are always placed at pixel boundaries in their logical y |
678 // so results in incorrect layout of text decorations, most notably underlin
es. | 698 // direction. Not doing so results in incorrect layout of text decorations, |
| 699 // most notably underlines. |
679 setLogicalTop(LayoutUnit( | 700 setLogicalTop(LayoutUnit( |
680 roundToInt(top + maxAscent - fontMetrics.ascent(baselineType)))); | 701 roundToInt(top + maxAscent - fontMetrics.ascent(baselineType)))); |
681 } | 702 } |
682 | 703 |
683 LayoutUnit adjustmentForChildrenWithSameLineHeightAndBaseline; | 704 LayoutUnit adjustmentForChildrenWithSameLineHeightAndBaseline; |
684 if (descendantsHaveSameLineHeightAndBaseline()) { | 705 if (descendantsHaveSameLineHeightAndBaseline()) { |
685 adjustmentForChildrenWithSameLineHeightAndBaseline = logicalTop(); | 706 adjustmentForChildrenWithSameLineHeightAndBaseline = logicalTop(); |
686 if (parent()) | 707 if (parent()) |
687 adjustmentForChildrenWithSameLineHeightAndBaseline += | 708 adjustmentForChildrenWithSameLineHeightAndBaseline += |
688 boxModelObject().borderAndPaddingOver(); | 709 boxModelObject().borderAndPaddingOver(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
728 if (curr->isInlineFlowBox()) { | 749 if (curr->isInlineFlowBox()) { |
729 LineLayoutBoxModel boxObject = | 750 LineLayoutBoxModel boxObject = |
730 LineLayoutBoxModel(curr->getLineLayoutItem()); | 751 LineLayoutBoxModel(curr->getLineLayoutItem()); |
731 newLogicalTop -= boxObject.borderAndPaddingOver(); | 752 newLogicalTop -= boxObject.borderAndPaddingOver(); |
732 borderPaddingHeight = boxObject.borderAndPaddingLogicalHeight(); | 753 borderPaddingHeight = boxObject.borderAndPaddingLogicalHeight(); |
733 } | 754 } |
734 newLogicalTopIncludingMargins = newLogicalTop; | 755 newLogicalTopIncludingMargins = newLogicalTop; |
735 } else if (!curr->getLineLayoutItem().isBR()) { | 756 } else if (!curr->getLineLayoutItem().isBR()) { |
736 LineLayoutBox box = LineLayoutBox(curr->getLineLayoutItem()); | 757 LineLayoutBox box = LineLayoutBox(curr->getLineLayoutItem()); |
737 newLogicalTopIncludingMargins = newLogicalTop; | 758 newLogicalTopIncludingMargins = newLogicalTop; |
738 // TODO(kojii): isHorizontal() does not match to m_layoutObject.isHorizont
alWritingMode(). crbug.com/552954 | 759 // TODO(kojii): isHorizontal() does not match to |
739 // ASSERT(curr->isHorizontal() == curr->getLineLayoutItem().style()->isHor
izontalWritingMode()); | 760 // m_layoutObject.isHorizontalWritingMode(). crbug.com/552954 |
| 761 // ASSERT(curr->isHorizontal() == |
| 762 // curr->getLineLayoutItem().style()->isHorizontalWritingMode()); |
740 LayoutUnit overSideMargin = | 763 LayoutUnit overSideMargin = |
741 curr->isHorizontal() ? box.marginTop() : box.marginRight(); | 764 curr->isHorizontal() ? box.marginTop() : box.marginRight(); |
742 LayoutUnit underSideMargin = | 765 LayoutUnit underSideMargin = |
743 curr->isHorizontal() ? box.marginBottom() : box.marginLeft(); | 766 curr->isHorizontal() ? box.marginBottom() : box.marginLeft(); |
744 newLogicalTop += overSideMargin; | 767 newLogicalTop += overSideMargin; |
745 boxHeightIncludingMargins += overSideMargin + underSideMargin; | 768 boxHeightIncludingMargins += overSideMargin + underSideMargin; |
746 } | 769 } |
747 | 770 |
748 curr->setLogicalTop(newLogicalTop); | 771 curr->setLogicalTop(newLogicalTop); |
749 | 772 |
750 if (childAffectsTopBottomPos) { | 773 if (childAffectsTopBottomPos) { |
751 if (curr->getLineLayoutItem().isRubyRun()) { | 774 if (curr->getLineLayoutItem().isRubyRun()) { |
752 // Treat the leading on the first and last lines of ruby runs as not bei
ng part of the overall lineTop/lineBottom. | 775 // Treat the leading on the first and last lines of ruby runs as not |
753 // Really this is a workaround hack for the fact that ruby should have b
een done as line layout and not done using | 776 // being part of the overall lineTop/lineBottom. |
754 // inline-block. | 777 // Really this is a workaround hack for the fact that ruby should have |
| 778 // been done as line layout and not done using inline-block. |
755 if (getLineLayoutItem().style()->isFlippedLinesWritingMode() == | 779 if (getLineLayoutItem().style()->isFlippedLinesWritingMode() == |
756 (curr->getLineLayoutItem().style()->getRubyPosition() == | 780 (curr->getLineLayoutItem().style()->getRubyPosition() == |
757 RubyPositionAfter)) | 781 RubyPositionAfter)) |
758 hasAnnotationsBefore = true; | 782 hasAnnotationsBefore = true; |
759 else | 783 else |
760 hasAnnotationsAfter = true; | 784 hasAnnotationsAfter = true; |
761 | 785 |
762 LineLayoutRubyRun rubyRun = | 786 LineLayoutRubyRun rubyRun = |
763 LineLayoutRubyRun(curr->getLineLayoutItem()); | 787 LineLayoutRubyRun(curr->getLineLayoutItem()); |
764 if (LineLayoutRubyBase rubyBase = rubyRun.rubyBase()) { | 788 if (LineLayoutRubyBase rubyBase = rubyRun.rubyBase()) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 } | 832 } |
809 selectionBottom = std::max( | 833 selectionBottom = std::max( |
810 selectionBottom, newLogicalTop + boxHeight - borderPaddingHeight); | 834 selectionBottom, newLogicalTop + boxHeight - borderPaddingHeight); |
811 lineBottom = std::max(lineBottom, newLogicalTop + boxHeight); | 835 lineBottom = std::max(lineBottom, newLogicalTop + boxHeight); |
812 lineBottomIncludingMargins = std::max( | 836 lineBottomIncludingMargins = std::max( |
813 lineBottom, | 837 lineBottom, |
814 std::max(lineBottomIncludingMargins, | 838 std::max(lineBottomIncludingMargins, |
815 newLogicalTopIncludingMargins + boxHeightIncludingMargins)); | 839 newLogicalTopIncludingMargins + boxHeightIncludingMargins)); |
816 } | 840 } |
817 | 841 |
818 // Adjust boxes to use their real box y/height and not the logical height (a
s dictated by | 842 // Adjust boxes to use their real box y/height and not the logical height |
819 // line-height). | 843 // (as dictated by line-height). |
820 if (inlineFlowBox) | 844 if (inlineFlowBox) |
821 inlineFlowBox->placeBoxesInBlockDirection( | 845 inlineFlowBox->placeBoxesInBlockDirection( |
822 top, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom, | 846 top, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom, |
823 selectionBottom, setLineTop, lineTopIncludingMargins, | 847 selectionBottom, setLineTop, lineTopIncludingMargins, |
824 lineBottomIncludingMargins, hasAnnotationsBefore, hasAnnotationsAfter, | 848 lineBottomIncludingMargins, hasAnnotationsBefore, hasAnnotationsAfter, |
825 baselineType); | 849 baselineType); |
826 } | 850 } |
827 | 851 |
828 if (isRootBox) { | 852 if (isRootBox) { |
829 if (noQuirksMode || hasTextChildren() || | 853 if (noQuirksMode || hasTextChildren() || |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 maxLogicalTop = std::max<LayoutUnit>(maxLogicalTop, curr->y()); | 885 maxLogicalTop = std::max<LayoutUnit>(maxLogicalTop, curr->y()); |
862 LayoutUnit localMaxLogicalTop; | 886 LayoutUnit localMaxLogicalTop; |
863 if (curr->isInlineFlowBox()) | 887 if (curr->isInlineFlowBox()) |
864 toInlineFlowBox(curr)->computeMaxLogicalTop(localMaxLogicalTop); | 888 toInlineFlowBox(curr)->computeMaxLogicalTop(localMaxLogicalTop); |
865 maxLogicalTop = std::max<LayoutUnit>(maxLogicalTop, localMaxLogicalTop); | 889 maxLogicalTop = std::max<LayoutUnit>(maxLogicalTop, localMaxLogicalTop); |
866 } | 890 } |
867 } | 891 } |
868 | 892 |
869 void InlineFlowBox::flipLinesInBlockDirection(LayoutUnit lineTop, | 893 void InlineFlowBox::flipLinesInBlockDirection(LayoutUnit lineTop, |
870 LayoutUnit lineBottom) { | 894 LayoutUnit lineBottom) { |
871 // Flip the box on the line such that the top is now relative to the lineBotto
m instead of the lineTop. | 895 // Flip the box on the line such that the top is now relative to the |
| 896 // lineBottom instead of the lineTop. |
872 setLogicalTop(lineBottom - (logicalTop() - lineTop) - logicalHeight()); | 897 setLogicalTop(lineBottom - (logicalTop() - lineTop) - logicalHeight()); |
873 | 898 |
874 for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { | 899 for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { |
875 if (curr->getLineLayoutItem().isOutOfFlowPositioned()) | 900 if (curr->getLineLayoutItem().isOutOfFlowPositioned()) |
876 continue; // Positioned placeholders aren't affected here. | 901 continue; // Positioned placeholders aren't affected here. |
877 | 902 |
878 if (curr->isInlineFlowBox()) | 903 if (curr->isInlineFlowBox()) |
879 toInlineFlowBox(curr)->flipLinesInBlockDirection(lineTop, lineBottom); | 904 toInlineFlowBox(curr)->flipLinesInBlockDirection(lineTop, lineBottom); |
880 else | 905 else |
881 curr->setLogicalTop(lineBottom - (curr->logicalTop() - lineTop) - | 906 curr->setLogicalTop(lineBottom - (curr->logicalTop() - lineTop) - |
(...skipping 10 matching lines...) Expand all Loading... |
892 if (!parent() && | 917 if (!parent() && |
893 (!isFirstLineStyle() || &style == getLineLayoutItem().style())) | 918 (!isFirstLineStyle() || &style == getLineLayoutItem().style())) |
894 return; | 919 return; |
895 | 920 |
896 WritingMode writingMode = style.getWritingMode(); | 921 WritingMode writingMode = style.getWritingMode(); |
897 ShadowList* boxShadow = style.boxShadow(); | 922 ShadowList* boxShadow = style.boxShadow(); |
898 if (!boxShadow) | 923 if (!boxShadow) |
899 return; | 924 return; |
900 | 925 |
901 LayoutRectOutsets outsets(boxShadow->rectOutsetsIncludingOriginal()); | 926 LayoutRectOutsets outsets(boxShadow->rectOutsetsIncludingOriginal()); |
902 // Similar to how glyph overflow works, if our lines are flipped, then it's ac
tually the opposite shadow that applies, since | 927 // Similar to how glyph overflow works, if our lines are flipped, then it's |
903 // the line is "upside down" in terms of block coordinates. | 928 // actually the opposite shadow that applies, since the line is "upside down" |
| 929 // in terms of block coordinates. |
904 LayoutRectOutsets logicalOutsets( | 930 LayoutRectOutsets logicalOutsets( |
905 outsets.logicalOutsetsWithFlippedLines(writingMode)); | 931 outsets.logicalOutsetsWithFlippedLines(writingMode)); |
906 | 932 |
907 LayoutRect shadowBounds(logicalFrameRect()); | 933 LayoutRect shadowBounds(logicalFrameRect()); |
908 shadowBounds.expand(logicalOutsets); | 934 shadowBounds.expand(logicalOutsets); |
909 logicalVisualOverflow.unite(shadowBounds); | 935 logicalVisualOverflow.unite(shadowBounds); |
910 } | 936 } |
911 | 937 |
912 inline void InlineFlowBox::addBorderOutsetVisualOverflow( | 938 inline void InlineFlowBox::addBorderOutsetVisualOverflow( |
913 LayoutRect& logicalVisualOverflow) { | 939 LayoutRect& logicalVisualOverflow) { |
914 const ComputedStyle& style = getLineLayoutItem().styleRef(isFirstLineStyle()); | 940 const ComputedStyle& style = getLineLayoutItem().styleRef(isFirstLineStyle()); |
915 | 941 |
916 // border-image-outset on the block element applies to the block and not to th
e lines, | 942 // border-image-outset on the block element applies to the block and not to |
917 // unless it is modified by :first-line pseudo element. | 943 // the lines, unless it is modified by :first-line pseudo element. |
918 if (!parent() && | 944 if (!parent() && |
919 (!isFirstLineStyle() || &style == getLineLayoutItem().style())) | 945 (!isFirstLineStyle() || &style == getLineLayoutItem().style())) |
920 return; | 946 return; |
921 | 947 |
922 if (!style.hasBorderImageOutsets()) | 948 if (!style.hasBorderImageOutsets()) |
923 return; | 949 return; |
924 | 950 |
925 // Similar to how glyph overflow works, if our lines are flipped, then it's ac
tually the opposite border that applies, since | 951 // Similar to how glyph overflow works, if our lines are flipped, then it's |
926 // the line is "upside down" in terms of block coordinates. vertical-rl is the
flipped line mode. | 952 // actually the opposite border that applies, since the line is "upside down" |
| 953 // in terms of block coordinates. vertical-rl is the flipped line mode. |
927 LayoutRectOutsets logicalOutsets = | 954 LayoutRectOutsets logicalOutsets = |
928 style.borderImageOutsets().logicalOutsetsWithFlippedLines( | 955 style.borderImageOutsets().logicalOutsetsWithFlippedLines( |
929 style.getWritingMode()); | 956 style.getWritingMode()); |
930 | 957 |
931 if (!includeLogicalLeftEdge()) | 958 if (!includeLogicalLeftEdge()) |
932 logicalOutsets.setLeft(LayoutUnit()); | 959 logicalOutsets.setLeft(LayoutUnit()); |
933 if (!includeLogicalRightEdge()) | 960 if (!includeLogicalRightEdge()) |
934 logicalOutsets.setRight(LayoutUnit()); | 961 logicalOutsets.setRight(LayoutUnit()); |
935 | 962 |
936 LayoutRect borderOutsetBounds(logicalFrameRect()); | 963 LayoutRect borderOutsetBounds(logicalFrameRect()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 textBox->getEmphasisMarkPosition(style, emphasisMarkPosition)) { | 1014 textBox->getEmphasisMarkPosition(style, emphasisMarkPosition)) { |
988 float emphasisMarkHeight = | 1015 float emphasisMarkHeight = |
989 style.font().emphasisMarkHeight(style.textEmphasisMarkString()); | 1016 style.font().emphasisMarkHeight(style.textEmphasisMarkString()); |
990 if ((emphasisMarkPosition == TextEmphasisPositionOver) == | 1017 if ((emphasisMarkPosition == TextEmphasisPositionOver) == |
991 (!style.isFlippedLinesWritingMode())) | 1018 (!style.isFlippedLinesWritingMode())) |
992 topGlyphOverflow = std::min(topGlyphOverflow, -emphasisMarkHeight); | 1019 topGlyphOverflow = std::min(topGlyphOverflow, -emphasisMarkHeight); |
993 else | 1020 else |
994 bottomGlyphOverflow = std::max(bottomGlyphOverflow, emphasisMarkHeight); | 1021 bottomGlyphOverflow = std::max(bottomGlyphOverflow, emphasisMarkHeight); |
995 } | 1022 } |
996 | 1023 |
997 // If letter-spacing is negative, we should factor that into right layout over
flow. Even in RTL, letter-spacing is | 1024 // If letter-spacing is negative, we should factor that into right layout |
998 // applied to the right, so this is not an issue with left overflow. | 1025 // overflow. Even in RTL, letter-spacing is applied to the right, so this is |
| 1026 // not an issue with left overflow. |
999 rightGlyphOverflow -= | 1027 rightGlyphOverflow -= |
1000 std::min(0.0f, style.font().getFontDescription().letterSpacing()); | 1028 std::min(0.0f, style.font().getFontDescription().letterSpacing()); |
1001 | 1029 |
1002 LayoutRectOutsets textShadowLogicalOutsets; | 1030 LayoutRectOutsets textShadowLogicalOutsets; |
1003 if (ShadowList* textShadow = style.textShadow()) | 1031 if (ShadowList* textShadow = style.textShadow()) |
1004 textShadowLogicalOutsets = | 1032 textShadowLogicalOutsets = |
1005 LayoutRectOutsets(textShadow->rectOutsetsIncludingOriginal()) | 1033 LayoutRectOutsets(textShadow->rectOutsetsIncludingOriginal()) |
1006 .logicalOutsets(style.getWritingMode()); | 1034 .logicalOutsets(style.getWritingMode()); |
1007 | 1035 |
1008 // FIXME: This code currently uses negative values for expansion of the top | 1036 // FIXME: This code currently uses negative values for expansion of the top |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 if (logicalVisualOverflow != textBox->logicalFrameRect()) | 1077 if (logicalVisualOverflow != textBox->logicalFrameRect()) |
1050 textBox->setLogicalOverflowRect(logicalVisualOverflow); | 1078 textBox->setLogicalOverflowRect(logicalVisualOverflow); |
1051 } | 1079 } |
1052 | 1080 |
1053 inline void InlineFlowBox::addReplacedChildOverflow( | 1081 inline void InlineFlowBox::addReplacedChildOverflow( |
1054 const InlineBox* inlineBox, | 1082 const InlineBox* inlineBox, |
1055 LayoutRect& logicalLayoutOverflow, | 1083 LayoutRect& logicalLayoutOverflow, |
1056 LayoutRect& logicalVisualOverflow) { | 1084 LayoutRect& logicalVisualOverflow) { |
1057 LineLayoutBox box = LineLayoutBox(inlineBox->getLineLayoutItem()); | 1085 LineLayoutBox box = LineLayoutBox(inlineBox->getLineLayoutItem()); |
1058 | 1086 |
1059 // Visual overflow only propagates if the box doesn't have a self-painting lay
er. This rectangle does not include | 1087 // Visual overflow only propagates if the box doesn't have a self-painting |
1060 // transforms or relative positioning (since those objects always have self-pa
inting layers), but it does need to be adjusted | 1088 // layer. This rectangle does not include transforms or relative positioning |
1061 // for writing-mode differences. | 1089 // (since those objects always have self-painting layers), but it does need to |
| 1090 // be adjusted for writing-mode differences. |
1062 if (!box.hasSelfPaintingLayer()) { | 1091 if (!box.hasSelfPaintingLayer()) { |
1063 LayoutRect childLogicalVisualOverflow = | 1092 LayoutRect childLogicalVisualOverflow = |
1064 box.logicalVisualOverflowRectForPropagation( | 1093 box.logicalVisualOverflowRectForPropagation( |
1065 getLineLayoutItem().styleRef()); | 1094 getLineLayoutItem().styleRef()); |
1066 childLogicalVisualOverflow.move(inlineBox->logicalLeft(), | 1095 childLogicalVisualOverflow.move(inlineBox->logicalLeft(), |
1067 inlineBox->logicalTop()); | 1096 inlineBox->logicalTop()); |
1068 logicalVisualOverflow.unite(childLogicalVisualOverflow); | 1097 logicalVisualOverflow.unite(childLogicalVisualOverflow); |
1069 } | 1098 } |
1070 | 1099 |
1071 // Layout overflow internal to the child box only propagates if the child box
doesn't have overflow clip set. | 1100 // Layout overflow internal to the child box only propagates if the child box |
1072 // Otherwise the child border box propagates as layout overflow. This rectang
le must include transforms and relative positioning | 1101 // doesn't have overflow clip set. Otherwise the child border box propagates |
1073 // and be adjusted for writing-mode differences. | 1102 // as layout overflow. This rectangle must include transforms and relative |
| 1103 // positioning and be adjusted for writing-mode differences. |
1074 LayoutRect childLogicalLayoutOverflow = | 1104 LayoutRect childLogicalLayoutOverflow = |
1075 box.logicalLayoutOverflowRectForPropagation( | 1105 box.logicalLayoutOverflowRectForPropagation( |
1076 getLineLayoutItem().styleRef()); | 1106 getLineLayoutItem().styleRef()); |
1077 childLogicalLayoutOverflow.move(inlineBox->logicalLeft(), | 1107 childLogicalLayoutOverflow.move(inlineBox->logicalLeft(), |
1078 inlineBox->logicalTop()); | 1108 inlineBox->logicalTop()); |
1079 logicalLayoutOverflow.unite(childLogicalLayoutOverflow); | 1109 logicalLayoutOverflow.unite(childLogicalLayoutOverflow); |
1080 } | 1110 } |
1081 | 1111 |
1082 void InlineFlowBox::computeOverflow( | 1112 void InlineFlowBox::computeOverflow( |
1083 LayoutUnit lineTop, | 1113 LayoutUnit lineTop, |
1084 LayoutUnit lineBottom, | 1114 LayoutUnit lineBottom, |
1085 GlyphOverflowAndFallbackFontsMap& textBoxDataMap) { | 1115 GlyphOverflowAndFallbackFontsMap& textBoxDataMap) { |
1086 // If we know we have no overflow, we can just bail. | 1116 // If we know we have no overflow, we can just bail. |
1087 if (knownToHaveNoOverflow()) { | 1117 if (knownToHaveNoOverflow()) { |
1088 ASSERT(!m_overflow); | 1118 ASSERT(!m_overflow); |
1089 return; | 1119 return; |
1090 } | 1120 } |
1091 | 1121 |
1092 if (m_overflow) | 1122 if (m_overflow) |
1093 m_overflow.reset(); | 1123 m_overflow.reset(); |
1094 | 1124 |
1095 // Visual overflow just includes overflow for stuff we need to issues paint in
validations for ourselves. Self-painting layers are ignored. | 1125 // Visual overflow just includes overflow for stuff we need to issues paint |
1096 // Layout overflow is used to determine scrolling extent, so it still includes
child layers and also factors in | 1126 // invalidations for ourselves. Self-painting layers are ignored. |
1097 // transforms, relative positioning, etc. | 1127 // Layout overflow is used to determine scrolling extent, so it still includes |
| 1128 // child layers and also factors in transforms, relative positioning, etc. |
1098 LayoutRect logicalLayoutOverflow( | 1129 LayoutRect logicalLayoutOverflow( |
1099 logicalFrameRectIncludingLineHeight(lineTop, lineBottom)); | 1130 logicalFrameRectIncludingLineHeight(lineTop, lineBottom)); |
1100 LayoutRect logicalVisualOverflow(logicalLayoutOverflow); | 1131 LayoutRect logicalVisualOverflow(logicalLayoutOverflow); |
1101 | 1132 |
1102 addBoxShadowVisualOverflow(logicalVisualOverflow); | 1133 addBoxShadowVisualOverflow(logicalVisualOverflow); |
1103 addBorderOutsetVisualOverflow(logicalVisualOverflow); | 1134 addBorderOutsetVisualOverflow(logicalVisualOverflow); |
1104 addOutlineVisualOverflow(logicalVisualOverflow); | 1135 addOutlineVisualOverflow(logicalVisualOverflow); |
1105 | 1136 |
1106 for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { | 1137 for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { |
1107 if (curr->getLineLayoutItem().isOutOfFlowPositioned()) | 1138 if (curr->getLineLayoutItem().isOutOfFlowPositioned()) |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1183 const HitTestLocation& locationInContainer, | 1214 const HitTestLocation& locationInContainer, |
1184 const LayoutPoint& accumulatedOffset, | 1215 const LayoutPoint& accumulatedOffset, |
1185 LayoutUnit lineTop, | 1216 LayoutUnit lineTop, |
1186 LayoutUnit lineBottom) { | 1217 LayoutUnit lineBottom) { |
1187 LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom)); | 1218 LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom)); |
1188 flipForWritingMode(overflowRect); | 1219 flipForWritingMode(overflowRect); |
1189 overflowRect.moveBy(accumulatedOffset); | 1220 overflowRect.moveBy(accumulatedOffset); |
1190 if (!locationInContainer.intersects(overflowRect)) | 1221 if (!locationInContainer.intersects(overflowRect)) |
1191 return false; | 1222 return false; |
1192 | 1223 |
1193 // We need to hit test both our inline children (Inline Boxes) and culled inli
nes | 1224 // We need to hit test both our inline children (Inline Boxes) and culled |
1194 // (LayoutObjects). We check our inlines in the same order as line layout but | 1225 // inlines (LayoutObjects). We check our inlines in the same order as line |
1195 // for each inline we additionally need to hit test its culled inline parents. | 1226 // layout but for each inline we additionally need to hit test its culled |
1196 // While hit testing culled inline parents, we can stop once we reach | 1227 // inline parents. While hit testing culled inline parents, we can stop once |
1197 // a non-inline parent or a culled inline associated with a different inline b
ox. | 1228 // we reach a non-inline parent or a culled inline associated with a different |
| 1229 // inline box. |
1198 InlineBox* prev; | 1230 InlineBox* prev; |
1199 for (InlineBox* curr = lastChild(); curr; curr = prev) { | 1231 for (InlineBox* curr = lastChild(); curr; curr = prev) { |
1200 prev = curr->prevOnLine(); | 1232 prev = curr->prevOnLine(); |
1201 | 1233 |
1202 // Layers will handle hit testing themselves. | 1234 // Layers will handle hit testing themselves. |
1203 if (!curr->boxModelObject() || | 1235 if (!curr->boxModelObject() || |
1204 !curr->boxModelObject().hasSelfPaintingLayer()) { | 1236 !curr->boxModelObject().hasSelfPaintingLayer()) { |
1205 if (curr->nodeAtPoint(result, locationInContainer, accumulatedOffset, | 1237 if (curr->nodeAtPoint(result, locationInContainer, accumulatedOffset, |
1206 lineTop, lineBottom)) { | 1238 lineTop, lineBottom)) { |
1207 getLineLayoutItem().updateHitTestResult( | 1239 getLineLayoutItem().updateHitTestResult( |
1208 result, | 1240 result, |
1209 locationInContainer.point() - toLayoutSize(accumulatedOffset)); | 1241 locationInContainer.point() - toLayoutSize(accumulatedOffset)); |
1210 return true; | 1242 return true; |
1211 } | 1243 } |
1212 } | 1244 } |
1213 | 1245 |
1214 // If the current inline box's layout object and the previous inline box's l
ayout object are same, | 1246 // If the current inline box's layout object and the previous inline box's |
1215 // we should yield the hit-test to the previous inline box. | 1247 // layout object are same, we should yield the hit-test to the previous |
| 1248 // inline box. |
1216 if (prev && curr->getLineLayoutItem() == prev->getLineLayoutItem()) | 1249 if (prev && curr->getLineLayoutItem() == prev->getLineLayoutItem()) |
1217 continue; | 1250 continue; |
1218 | 1251 |
1219 // Hit test the culled inline if necessary. | 1252 // Hit test the culled inline if necessary. |
1220 LineLayoutItem currLayoutItem = curr->getLineLayoutItem(); | 1253 LineLayoutItem currLayoutItem = curr->getLineLayoutItem(); |
1221 while (true) { | 1254 while (true) { |
1222 // If the previous inline box is not a descendant of a current inline's pa
rent, | 1255 // If the previous inline box is not a descendant of a current inline's |
1223 // the parent is a culled inline and we hit test it. | 1256 // parent, the parent is a culled inline and we hit test it. |
1224 // Otherwise, move to the previous inline box because we hit test first al
l | 1257 // Otherwise, move to the previous inline box because we hit test first |
1225 // candidate inline boxes under the parent to take a pre-order tree traver
sal in reverse. | 1258 // all candidate inline boxes under the parent to take a pre-order tree |
| 1259 // traversal in reverse. |
1226 bool hasSibling = | 1260 bool hasSibling = |
1227 currLayoutItem.previousSibling() || currLayoutItem.nextSibling(); | 1261 currLayoutItem.previousSibling() || currLayoutItem.nextSibling(); |
1228 LineLayoutItem culledParent = currLayoutItem.parent(); | 1262 LineLayoutItem culledParent = currLayoutItem.parent(); |
1229 ASSERT(culledParent); | 1263 ASSERT(culledParent); |
1230 | 1264 |
1231 if (culledParent == getLineLayoutItem() || | 1265 if (culledParent == getLineLayoutItem() || |
1232 (hasSibling && prev && | 1266 (hasSibling && prev && |
1233 prev->getLineLayoutItem().isDescendantOf(culledParent))) | 1267 prev->getLineLayoutItem().isDescendantOf(culledParent))) |
1234 break; | 1268 break; |
1235 | 1269 |
(...skipping 27 matching lines...) Expand all Loading... |
1263 LayoutRect rect = | 1297 LayoutRect rect = |
1264 InlineFlowBoxPainter(*this).frameRectClampedToLineTopAndBottomIfNeeded(); | 1298 InlineFlowBoxPainter(*this).frameRectClampedToLineTopAndBottomIfNeeded(); |
1265 | 1299 |
1266 flipForWritingMode(rect); | 1300 flipForWritingMode(rect); |
1267 rect.moveBy(accumulatedOffset); | 1301 rect.moveBy(accumulatedOffset); |
1268 | 1302 |
1269 // Pixel snap hit testing. | 1303 // Pixel snap hit testing. |
1270 rect = LayoutRect(pixelSnappedIntRect(rect)); | 1304 rect = LayoutRect(pixelSnappedIntRect(rect)); |
1271 if (visibleToHitTestRequest(result.hitTestRequest()) && | 1305 if (visibleToHitTestRequest(result.hitTestRequest()) && |
1272 locationInContainer.intersects(rect)) { | 1306 locationInContainer.intersects(rect)) { |
| 1307 // Don't add in m_topLeft here, we want coords in the containing block's |
| 1308 // coordinate space. |
1273 getLineLayoutItem().updateHitTestResult( | 1309 getLineLayoutItem().updateHitTestResult( |
1274 result, | 1310 result, flipForWritingMode(locationInContainer.point() - |
1275 flipForWritingMode( | 1311 toLayoutSize(accumulatedOffset))); |
1276 locationInContainer.point() - | |
1277 toLayoutSize( | |
1278 accumulatedOffset))); // Don't add in m_topLeft here, we want c
oords in the containing block's space. | |
1279 if (result.addNodeToListBasedTestResult(getLineLayoutItem().node(), | 1312 if (result.addNodeToListBasedTestResult(getLineLayoutItem().node(), |
1280 locationInContainer, | 1313 locationInContainer, |
1281 rect) == StopHitTesting) | 1314 rect) == StopHitTesting) |
1282 return true; | 1315 return true; |
1283 } | 1316 } |
1284 | 1317 |
1285 return false; | 1318 return false; |
1286 } | 1319 } |
1287 | 1320 |
1288 void InlineFlowBox::paint(const PaintInfo& paintInfo, | 1321 void InlineFlowBox::paint(const PaintInfo& paintInfo, |
1289 const LayoutPoint& paintOffset, | 1322 const LayoutPoint& paintOffset, |
1290 LayoutUnit lineTop, | 1323 LayoutUnit lineTop, |
1291 LayoutUnit lineBottom) const { | 1324 LayoutUnit lineBottom) const { |
1292 InlineFlowBoxPainter(*this).paint(paintInfo, paintOffset, lineTop, | 1325 InlineFlowBoxPainter(*this).paint(paintInfo, paintOffset, lineTop, |
1293 lineBottom); | 1326 lineBottom); |
1294 } | 1327 } |
1295 | 1328 |
1296 bool InlineFlowBox::boxShadowCanBeAppliedToBackground( | 1329 bool InlineFlowBox::boxShadowCanBeAppliedToBackground( |
1297 const FillLayer& lastBackgroundLayer) const { | 1330 const FillLayer& lastBackgroundLayer) const { |
1298 // The checks here match how paintFillLayer() decides whether to clip (if it d
oes, the shadow | 1331 // The checks here match how paintFillLayer() decides whether to clip (if it |
| 1332 // does, the shadow |
1299 // would be clipped out, so it has to be drawn separately). | 1333 // would be clipped out, so it has to be drawn separately). |
1300 StyleImage* image = lastBackgroundLayer.image(); | 1334 StyleImage* image = lastBackgroundLayer.image(); |
1301 bool hasFillImage = image && image->canRender(); | 1335 bool hasFillImage = image && image->canRender(); |
1302 return (!hasFillImage && !getLineLayoutItem().style()->hasBorderRadius()) || | 1336 return (!hasFillImage && !getLineLayoutItem().style()->hasBorderRadius()) || |
1303 (!prevLineBox() && !nextLineBox()) || !parent(); | 1337 (!prevLineBox() && !nextLineBox()) || !parent(); |
1304 } | 1338 } |
1305 | 1339 |
1306 InlineBox* InlineFlowBox::firstLeafChild() const { | 1340 InlineBox* InlineFlowBox::firstLeafChild() const { |
1307 InlineBox* leaf = nullptr; | 1341 InlineBox* leaf = nullptr; |
1308 for (InlineBox* child = firstChild(); child && !leaf; | 1342 for (InlineBox* child = firstChild(); child && !leaf; |
(...skipping 24 matching lines...) Expand all Loading... |
1333 return true; | 1367 return true; |
1334 } | 1368 } |
1335 | 1369 |
1336 LayoutUnit InlineFlowBox::placeEllipsisBox(bool ltr, | 1370 LayoutUnit InlineFlowBox::placeEllipsisBox(bool ltr, |
1337 LayoutUnit blockLeftEdge, | 1371 LayoutUnit blockLeftEdge, |
1338 LayoutUnit blockRightEdge, | 1372 LayoutUnit blockRightEdge, |
1339 LayoutUnit ellipsisWidth, | 1373 LayoutUnit ellipsisWidth, |
1340 LayoutUnit& truncatedWidth, | 1374 LayoutUnit& truncatedWidth, |
1341 bool& foundBox) { | 1375 bool& foundBox) { |
1342 LayoutUnit result(-1); | 1376 LayoutUnit result(-1); |
1343 // We iterate over all children, the foundBox variable tells us when we've fou
nd the | 1377 // We iterate over all children, the foundBox variable tells us when we've |
1344 // box containing the ellipsis. All boxes after that one in the flow are hidd
en. | 1378 // found the box containing the ellipsis. All boxes after that one in the |
1345 // If our flow is ltr then iterate over the boxes from left to right, otherwis
e iterate | 1379 // flow are hidden. |
1346 // from right to left. Varying the order allows us to correctly hide the boxes
following the ellipsis. | 1380 // If our flow is ltr then iterate over the boxes from left to right, |
| 1381 // otherwise iterate from right to left. Varying the order allows us to |
| 1382 // correctly hide the boxes following the ellipsis. |
1347 InlineBox* box = ltr ? firstChild() : lastChild(); | 1383 InlineBox* box = ltr ? firstChild() : lastChild(); |
1348 | 1384 |
1349 // NOTE: these will cross after foundBox = true. | 1385 // NOTE: these will cross after foundBox = true. |
1350 int visibleLeftEdge = blockLeftEdge.toInt(); | 1386 int visibleLeftEdge = blockLeftEdge.toInt(); |
1351 int visibleRightEdge = blockRightEdge.toInt(); | 1387 int visibleRightEdge = blockRightEdge.toInt(); |
1352 | 1388 |
1353 while (box) { | 1389 while (box) { |
1354 int currResult = | 1390 int currResult = |
1355 box->placeEllipsisBox(ltr, LayoutUnit(visibleLeftEdge), | 1391 box->placeEllipsisBox(ltr, LayoutUnit(visibleLeftEdge), |
1356 LayoutUnit(visibleRightEdge), ellipsisWidth, | 1392 LayoutUnit(visibleRightEdge), ellipsisWidth, |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1506 } | 1542 } |
1507 } | 1543 } |
1508 return result; | 1544 return result; |
1509 } | 1545 } |
1510 | 1546 |
1511 void InlineFlowBox::collectLeafBoxesInLogicalOrder( | 1547 void InlineFlowBox::collectLeafBoxesInLogicalOrder( |
1512 Vector<InlineBox*>& leafBoxesInLogicalOrder, | 1548 Vector<InlineBox*>& leafBoxesInLogicalOrder, |
1513 CustomInlineBoxRangeReverse customReverseImplementation) const { | 1549 CustomInlineBoxRangeReverse customReverseImplementation) const { |
1514 InlineBox* leaf = firstLeafChild(); | 1550 InlineBox* leaf = firstLeafChild(); |
1515 | 1551 |
1516 // FIXME: The reordering code is a copy of parts from BidiResolver::createBidi
RunsForLine, operating directly on InlineBoxes, instead of BidiRuns. | 1552 // FIXME: The reordering code is a copy of parts from BidiResolver:: |
1517 // Investigate on how this code could possibly be shared. | 1553 // createBidiRunsForLine, operating directly on InlineBoxes, instead of |
| 1554 // BidiRuns. Investigate on how this code could possibly be shared. |
1518 unsigned char minLevel = 128; | 1555 unsigned char minLevel = 128; |
1519 unsigned char maxLevel = 0; | 1556 unsigned char maxLevel = 0; |
1520 | 1557 |
1521 // First find highest and lowest levels, and initialize leafBoxesInLogicalOrde
r with the leaf boxes in visual order. | 1558 // First find highest and lowest levels, and initialize |
| 1559 // leafBoxesInLogicalOrder with the leaf boxes in visual order. |
1522 for (; leaf; leaf = leaf->nextLeafChild()) { | 1560 for (; leaf; leaf = leaf->nextLeafChild()) { |
1523 minLevel = std::min(minLevel, leaf->bidiLevel()); | 1561 minLevel = std::min(minLevel, leaf->bidiLevel()); |
1524 maxLevel = std::max(maxLevel, leaf->bidiLevel()); | 1562 maxLevel = std::max(maxLevel, leaf->bidiLevel()); |
1525 leafBoxesInLogicalOrder.append(leaf); | 1563 leafBoxesInLogicalOrder.append(leaf); |
1526 } | 1564 } |
1527 | 1565 |
1528 if (getLineLayoutItem().style()->rtlOrdering() == VisualOrder) | 1566 if (getLineLayoutItem().style()->rtlOrdering() == VisualOrder) |
1529 return; | 1567 return; |
1530 | 1568 |
1531 // Reverse of reordering of the line (L2 according to Bidi spec): | 1569 // Reverse of reordering of the line (L2 according to Bidi spec): |
1532 // L2. From the highest level found in the text to the lowest odd level on eac
h line, | 1570 // L2. From the highest level found in the text to the lowest odd level on |
1533 // reverse any contiguous sequence of characters that are at that level or hig
her. | 1571 // each line, reverse any contiguous sequence of characters that are at that |
| 1572 // level or higher. |
1534 | 1573 |
1535 // Reversing the reordering of the line is only done up to the lowest odd leve
l. | 1574 // Reversing the reordering of the line is only done up to the lowest odd |
| 1575 // level. |
1536 if (!(minLevel % 2)) | 1576 if (!(minLevel % 2)) |
1537 ++minLevel; | 1577 ++minLevel; |
1538 | 1578 |
1539 Vector<InlineBox*>::iterator end = leafBoxesInLogicalOrder.end(); | 1579 Vector<InlineBox*>::iterator end = leafBoxesInLogicalOrder.end(); |
1540 while (minLevel <= maxLevel) { | 1580 while (minLevel <= maxLevel) { |
1541 Vector<InlineBox*>::iterator it = leafBoxesInLogicalOrder.begin(); | 1581 Vector<InlineBox*>::iterator it = leafBoxesInLogicalOrder.begin(); |
1542 while (it != end) { | 1582 while (it != end) { |
1543 while (it != end) { | 1583 while (it != end) { |
1544 if ((*it)->bidiLevel() >= minLevel) | 1584 if ((*it)->bidiLevel() >= minLevel) |
1545 break; | 1585 break; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1593 ASSERT(child->prevOnLine() == prev); | 1633 ASSERT(child->prevOnLine() == prev); |
1594 prev = child; | 1634 prev = child; |
1595 } | 1635 } |
1596 ASSERT(prev == m_lastChild); | 1636 ASSERT(prev == m_lastChild); |
1597 #endif | 1637 #endif |
1598 } | 1638 } |
1599 | 1639 |
1600 #endif | 1640 #endif |
1601 | 1641 |
1602 } // namespace blink | 1642 } // namespace blink |
OLD | NEW |