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. All r
ight reserved. |
4 * Copyright (C) 2010 Google Inc. All rights reserved. | 4 * Copyright (C) 2010 Google Inc. All rights reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
10 * | 10 * |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 if (r->m_lineLayoutItem.isText()) | 274 if (r->m_lineLayoutItem.isText()) |
275 box = createInlineBoxForText(*r, isOnlyRun); | 275 box = createInlineBoxForText(*r, isOnlyRun); |
276 else | 276 else |
277 box = createInlineBoxForLayoutObject(r->m_lineLayoutItem, false, isO
nlyRun); | 277 box = createInlineBoxForLayoutObject(r->m_lineLayoutItem, false, isO
nlyRun); |
278 r->m_box = box; | 278 r->m_box = box; |
279 | 279 |
280 ASSERT(box); | 280 ASSERT(box); |
281 if (!box) | 281 if (!box) |
282 continue; | 282 continue; |
283 | 283 |
284 if (!rootHasSelectedChildren && box->lineLayoutItem().selectionState() !
= SelectionNone) | 284 if (!rootHasSelectedChildren && box->getLineLayoutItem().getSelectionSta
te() != SelectionNone) |
285 rootHasSelectedChildren = true; | 285 rootHasSelectedChildren = true; |
286 | 286 |
287 // If we have no parent box yet, or if the run is not simply a sibling, | 287 // If we have no parent box yet, or if the run is not simply a sibling, |
288 // then we need to construct inline boxes as necessary to properly enclo
se the | 288 // then we need to construct inline boxes as necessary to properly enclo
se the |
289 // run's inline box. Segments can only be siblings at the root level, as | 289 // run's inline box. Segments can only be siblings at the root level, as |
290 // they are positioned separately. | 290 // they are positioned separately. |
291 if (!parentBox || (!parentBox->lineLayoutItem().isEqual(r->m_lineLayoutI
tem.parent()))) { | 291 if (!parentBox || (!parentBox->getLineLayoutItem().isEqual(r->m_lineLayo
utItem.parent()))) { |
292 // Create new inline boxes all the way back to the appropriate inser
tion point. | 292 // Create new inline boxes all the way back to the appropriate inser
tion point. |
293 parentBox = createLineBoxes(r->m_lineLayoutItem.parent(), lineInfo,
box); | 293 parentBox = createLineBoxes(r->m_lineLayoutItem.parent(), lineInfo,
box); |
294 } else { | 294 } else { |
295 // Append the inline box to this line. | 295 // Append the inline box to this line. |
296 parentBox->addToLine(box); | 296 parentBox->addToLine(box); |
297 } | 297 } |
298 | 298 |
299 box->setBidiLevel(r->level()); | 299 box->setBidiLevel(r->level()); |
300 | 300 |
301 if (box->isInlineTextBox()) { | 301 if (box->isInlineTextBox()) { |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 ASSERT(run->m_box->isText()); | 512 ASSERT(run->m_box->isText()); |
513 GlyphOverflowAndFallbackFontsMap::ValueType* it = textBoxDataMap.add(toI
nlineTextBox(run->m_box), std::make_pair(Vector<const SimpleFontData*>(), GlyphO
verflow())).storedValue; | 513 GlyphOverflowAndFallbackFontsMap::ValueType* it = textBoxDataMap.add(toI
nlineTextBox(run->m_box), std::make_pair(Vector<const SimpleFontData*>(), GlyphO
verflow())).storedValue; |
514 it->value.second = glyphOverflow; | 514 it->value.second = glyphOverflow; |
515 run->m_box->clearKnownToHaveNoOverflow(); | 515 run->m_box->clearKnownToHaveNoOverflow(); |
516 } | 516 } |
517 } | 517 } |
518 | 518 |
519 void LayoutBlockFlow::updateLogicalWidthForAlignment(const ETextAlign& textAlign
, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, LayoutUnit& log
icalLeft, LayoutUnit& totalLogicalWidth, LayoutUnit& availableLogicalWidth, unsi
gned expansionOpportunityCount) | 519 void LayoutBlockFlow::updateLogicalWidthForAlignment(const ETextAlign& textAlign
, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, LayoutUnit& log
icalLeft, LayoutUnit& totalLogicalWidth, LayoutUnit& availableLogicalWidth, unsi
gned expansionOpportunityCount) |
520 { | 520 { |
521 TextDirection direction; | 521 TextDirection direction; |
522 if (rootInlineBox && rootInlineBox->lineLayoutItem().style()->unicodeBidi()
== Plaintext) | 522 if (rootInlineBox && rootInlineBox->getLineLayoutItem().style()->unicodeBidi
() == Plaintext) |
523 direction = rootInlineBox->direction(); | 523 direction = rootInlineBox->direction(); |
524 else | 524 else |
525 direction = style()->direction(); | 525 direction = style()->direction(); |
526 | 526 |
527 // Armed with the total width of the line (without justification), | 527 // Armed with the total width of the line (without justification), |
528 // we now examine our text-align property in order to determine where to pos
ition the | 528 // we now examine our text-align property in order to determine where to pos
ition the |
529 // objects horizontally. The total width of the line can be increased if we
end up | 529 // objects horizontally. The total width of the line can be increased if we
end up |
530 // justifying text. | 530 // justifying text. |
531 switch (textAlign) { | 531 switch (textAlign) { |
532 case LEFT: | 532 case LEFT: |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 lastRootBox()->appendFloat(floatingObject.layoutObject()); | 697 lastRootBox()->appendFloat(floatingObject.layoutObject()); |
698 } | 698 } |
699 | 699 |
700 // This function constructs line boxes for all of the text runs in the resolver
and computes their position. | 700 // This function constructs line boxes for all of the text runs in the resolver
and computes their position. |
701 RootInlineBox* LayoutBlockFlow::createLineBoxesFromBidiRuns(unsigned bidiLevel,
BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, V
erticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeas
urements& wordMeasurements) | 701 RootInlineBox* LayoutBlockFlow::createLineBoxesFromBidiRuns(unsigned bidiLevel,
BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, V
erticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeas
urements& wordMeasurements) |
702 { | 702 { |
703 if (!bidiRuns.runCount()) | 703 if (!bidiRuns.runCount()) |
704 return nullptr; | 704 return nullptr; |
705 | 705 |
706 // FIXME: Why is this only done when we had runs? | 706 // FIXME: Why is this only done when we had runs? |
707 lineInfo.setLastLine(!end.lineLayoutItem()); | 707 lineInfo.setLastLine(!end.getLineLayoutItem()); |
708 | 708 |
709 RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo); | 709 RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo); |
710 if (!lineBox) | 710 if (!lineBox) |
711 return nullptr; | 711 return nullptr; |
712 | 712 |
713 lineBox->setBidiLevel(bidiLevel); | 713 lineBox->setBidiLevel(bidiLevel); |
714 lineBox->setEndsWithBreak(lineInfo.previousLineBrokeCleanly()); | 714 lineBox->setEndsWithBreak(lineInfo.previousLineBrokeCleanly()); |
715 | 715 |
716 bool isSVGRootInlineBox = lineBox->isSVGRootInlineBox(); | 716 bool isSVGRootInlineBox = lineBox->isSVGRootInlineBox(); |
717 | 717 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 FloatingObjectSetIterator end = floatingObjectSet.end(); | 796 FloatingObjectSetIterator end = floatingObjectSet.end(); |
797 if (layoutState.lastFloat()) { | 797 if (layoutState.lastFloat()) { |
798 FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(lay
outState.lastFloat()); | 798 FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(lay
outState.lastFloat()); |
799 ASSERT(lastFloatIterator != end); | 799 ASSERT(lastFloatIterator != end); |
800 ++lastFloatIterator; | 800 ++lastFloatIterator; |
801 it = lastFloatIterator; | 801 it = lastFloatIterator; |
802 } | 802 } |
803 for (; it != end; ++it) { | 803 for (; it != end; ++it) { |
804 FloatingObject& floatingObject = *it->get(); | 804 FloatingObject& floatingObject = *it->get(); |
805 // If we've reached the start of clean lines any remaining floating chil
dren belong to them. | 805 // If we've reached the start of clean lines any remaining floating chil
dren belong to them. |
806 if (floatingObject.layoutObject() == cleanLineStart.lineLayoutItem() &&
layoutState.endLine()) { | 806 if (floatingObject.layoutObject() == cleanLineStart.getLineLayoutItem()
&& layoutState.endLine()) { |
807 layoutState.setEndLineMatched(layoutState.endLineMatched() || matche
dEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus)); | 807 layoutState.setEndLineMatched(layoutState.endLineMatched() || matche
dEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus)); |
808 if (layoutState.endLineMatched()) { | 808 if (layoutState.endLineMatched()) { |
809 layoutState.setLastFloat(&floatingObject); | 809 layoutState.setLastFloat(&floatingObject); |
810 return; | 810 return; |
811 } | 811 } |
812 } | 812 } |
813 appendFloatingObjectToLastLine(floatingObject); | 813 appendFloatingObjectToLastLine(floatingObject); |
814 ASSERT(floatingObject.layoutObject() == layoutState.floats()[layoutState
.floatIndex()].object); | 814 ASSERT(floatingObject.layoutObject() == layoutState.floats()[layoutState
.floatIndex()].object); |
815 // If a float's geometry has changed, give up on syncing with clean line
s. | 815 // If a float's geometry has changed, give up on syncing with clean line
s. |
816 if (layoutState.floats()[layoutState.floatIndex()].rect != floatingObjec
t.frameRect()) { | 816 if (layoutState.floats()[layoutState.floatIndex()].rect != floatingObjec
t.frameRect()) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla
ced by an ASSERT (or just removed). | 871 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla
ced by an ASSERT (or just removed). |
872 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0
), 0); | 872 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0
), 0); |
873 break; | 873 break; |
874 } | 874 } |
875 | 875 |
876 ASSERT(endOfLine != resolver.position()); | 876 ASSERT(endOfLine != resolver.position()); |
877 | 877 |
878 // This is a short-cut for empty lines. | 878 // This is a short-cut for empty lines. |
879 if (layoutState.lineInfo().isEmpty()) { | 879 if (layoutState.lineInfo().isEmpty()) { |
880 if (lastRootBox()) | 880 if (lastRootBox()) |
881 lastRootBox()->setLineBreakInfo(endOfLine.lineLayoutItem(), endO
fLine.offset(), resolver.status()); | 881 lastRootBox()->setLineBreakInfo(endOfLine.getLineLayoutItem(), e
ndOfLine.offset(), resolver.status()); |
882 resolver.runs().deleteRuns(); | 882 resolver.runs().deleteRuns(); |
883 } else { | 883 } else { |
884 VisualDirectionOverride override = (styleToUse.rtlOrdering() == Visu
alOrder ? (styleToUse.direction() == LTR ? VisualLeftToRightOverride : VisualRig
htToLeftOverride) : NoVisualOverride); | 884 VisualDirectionOverride override = (styleToUse.rtlOrdering() == Visu
alOrder ? (styleToUse.direction() == LTR ? VisualLeftToRightOverride : VisualRig
htToLeftOverride) : NoVisualOverride); |
885 if (isNewUBAParagraph && styleToUse.unicodeBidi() == Plaintext && !r
esolver.context()->parent()) { | 885 if (isNewUBAParagraph && styleToUse.unicodeBidi() == Plaintext && !r
esolver.context()->parent()) { |
886 TextDirection direction = determinePlaintextDirectionality(resol
ver.position().root(), resolver.position().lineLayoutItem(), resolver.position()
.offset()); | 886 TextDirection direction = determinePlaintextDirectionality(resol
ver.position().root(), resolver.position().getLineLayoutItem(), resolver.positio
n().offset()); |
887 resolver.setStatus(BidiStatus(direction, isOverride(styleToUse.u
nicodeBidi()))); | 887 resolver.setStatus(BidiStatus(direction, isOverride(styleToUse.u
nicodeBidi()))); |
888 } | 888 } |
889 // FIXME: This ownership is reversed. We should own the BidiRunList
and pass it to createBidiRunsForLine. | 889 // FIXME: This ownership is reversed. We should own the BidiRunList
and pass it to createBidiRunsForLine. |
890 BidiRunList<BidiRun>& bidiRuns = resolver.runs(); | 890 BidiRunList<BidiRun>& bidiRuns = resolver.runs(); |
891 constructBidiRunsForLine(resolver, bidiRuns, endOfLine, override, la
youtState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph); | 891 constructBidiRunsForLine(resolver, bidiRuns, endOfLine, override, la
youtState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph); |
892 ASSERT(resolver.position() == endOfLine); | 892 ASSERT(resolver.position() == endOfLine); |
893 | 893 |
894 BidiRun* trailingSpaceRun = resolver.trailingSpaceRun(); | 894 BidiRun* trailingSpaceRun = resolver.trailingSpaceRun(); |
895 | 895 |
896 if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) | 896 if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) |
897 bidiRuns.logicallyLastRun()->m_hasHyphen = true; | 897 bidiRuns.logicallyLastRun()->m_hasHyphen = true; |
898 | 898 |
899 // Now that the runs have been ordered, we create the line boxes. | 899 // Now that the runs have been ordered, we create the line boxes. |
900 // At the same time we figure out where border/padding/margin should
be applied for | 900 // At the same time we figure out where border/padding/margin should
be applied for |
901 // inline flow boxes. | 901 // inline flow boxes. |
902 | 902 |
903 LayoutUnit oldLogicalHeight = logicalHeight(); | 903 LayoutUnit oldLogicalHeight = logicalHeight(); |
904 RootInlineBox* lineBox = createLineBoxesFromBidiRuns(resolver.status
().context->level(), bidiRuns, endOfLine, layoutState.lineInfo(), verticalPositi
onCache, trailingSpaceRun, wordMeasurements); | 904 RootInlineBox* lineBox = createLineBoxesFromBidiRuns(resolver.status
().context->level(), bidiRuns, endOfLine, layoutState.lineInfo(), verticalPositi
onCache, trailingSpaceRun, wordMeasurements); |
905 | 905 |
906 bidiRuns.deleteRuns(); | 906 bidiRuns.deleteRuns(); |
907 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla
ced by an ASSERT (or just removed). | 907 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla
ced by an ASSERT (or just removed). |
908 | 908 |
909 if (lineBox) { | 909 if (lineBox) { |
910 lineBox->setLineBreakInfo(endOfLine.lineLayoutItem(), endOfLine.
offset(), resolver.status()); | 910 lineBox->setLineBreakInfo(endOfLine.getLineLayoutItem(), endOfLi
ne.offset(), resolver.status()); |
911 if (layoutState.usesPaintInvalidationBounds()) | 911 if (layoutState.usesPaintInvalidationBounds()) |
912 layoutState.updatePaintInvalidationRangeFromBox(lineBox); | 912 layoutState.updatePaintInvalidationRangeFromBox(lineBox); |
913 | 913 |
914 if (paginated) { | 914 if (paginated) { |
915 LayoutUnit adjustment; | 915 LayoutUnit adjustment; |
916 adjustLinePositionForPagination(*lineBox, adjustment); | 916 adjustLinePositionForPagination(*lineBox, adjustment); |
917 if (adjustment) { | 917 if (adjustment) { |
918 LayoutUnit oldLineWidth = availableLogicalWidthForLine(o
ldLogicalHeight, layoutState.lineInfo().isFirstLine() ? IndentText : DoNotIndent
Text); | 918 LayoutUnit oldLineWidth = availableLogicalWidthForLine(o
ldLogicalHeight, layoutState.lineInfo().isFirstLine() ? IndentText : DoNotIndent
Text); |
919 lineBox->moveInBlockDirection(adjustment); | 919 lineBox->moveInBlockDirection(adjustment); |
920 if (layoutState.usesPaintInvalidationBounds()) | 920 if (layoutState.usesPaintInvalidationBounds()) |
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1742 return curr; | 1742 return curr; |
1743 } | 1743 } |
1744 | 1744 |
1745 | 1745 |
1746 bool LayoutBlockFlow::lineBoxHasBRWithClearance(RootInlineBox* curr) | 1746 bool LayoutBlockFlow::lineBoxHasBRWithClearance(RootInlineBox* curr) |
1747 { | 1747 { |
1748 // If the linebox breaks cleanly and with clearance then dirty from at least
this point onwards so that we can clear the correct floats without difficulty. | 1748 // If the linebox breaks cleanly and with clearance then dirty from at least
this point onwards so that we can clear the correct floats without difficulty. |
1749 if (!curr->endsWithBreak()) | 1749 if (!curr->endsWithBreak()) |
1750 return false; | 1750 return false; |
1751 InlineBox* lastBox = style()->isLeftToRightDirection() ? curr->lastLeafChild
() : curr->firstLeafChild(); | 1751 InlineBox* lastBox = style()->isLeftToRightDirection() ? curr->lastLeafChild
() : curr->firstLeafChild(); |
1752 return lastBox && lastBox->lineLayoutItem().isBR() && lastBox->lineLayoutIte
m().style()->clear() != CNONE; | 1752 return lastBox && lastBox->getLineLayoutItem().isBR() && lastBox->getLineLay
outItem().style()->clear() != CNONE; |
1753 } | 1753 } |
1754 | 1754 |
1755 void LayoutBlockFlow::determineEndPosition(LineLayoutState& layoutState, RootInl
ineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStat
us) | 1755 void LayoutBlockFlow::determineEndPosition(LineLayoutState& layoutState, RootInl
ineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStat
us) |
1756 { | 1756 { |
1757 ASSERT(!layoutState.endLine()); | 1757 ASSERT(!layoutState.endLine()); |
1758 RootInlineBox* last = nullptr; | 1758 RootInlineBox* last = nullptr; |
1759 for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->next
RootBox()) { | 1759 for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->next
RootBox()) { |
1760 if (!curr->isDirty() && lineBoxHasBRWithClearance(curr)) | 1760 if (!curr->isDirty() && lineBoxHasBRWithClearance(curr)) |
1761 return; | 1761 return; |
1762 | 1762 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1835 | 1835 |
1836 return checkPaginationAndFloatsAtEndLine(layoutState); | 1836 return checkPaginationAndFloatsAtEndLine(layoutState); |
1837 } | 1837 } |
1838 | 1838 |
1839 // The first clean line doesn't match, but we can check a handful of followi
ng lines to try | 1839 // The first clean line doesn't match, but we can check a handful of followi
ng lines to try |
1840 // to match back up. | 1840 // to match back up. |
1841 static int numLines = 8; // The # of lines we're willing to match against. | 1841 static int numLines = 8; // The # of lines we're willing to match against. |
1842 RootInlineBox* originalEndLine = layoutState.endLine(); | 1842 RootInlineBox* originalEndLine = layoutState.endLine(); |
1843 RootInlineBox* line = originalEndLine; | 1843 RootInlineBox* line = originalEndLine; |
1844 for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) { | 1844 for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) { |
1845 if (line->lineBreakObj() == resolver.position().lineLayoutItem() && line
->lineBreakPos() == resolver.position().offset()) { | 1845 if (line->lineBreakObj() == resolver.position().getLineLayoutItem() && l
ine->lineBreakPos() == resolver.position().offset()) { |
1846 // We have a match. | 1846 // We have a match. |
1847 if (line->lineBreakBidiStatus() != resolver.status()) | 1847 if (line->lineBreakBidiStatus() != resolver.status()) |
1848 return false; // ...but the bidi state doesn't match. | 1848 return false; // ...but the bidi state doesn't match. |
1849 | 1849 |
1850 bool matched = false; | 1850 bool matched = false; |
1851 RootInlineBox* result = line->nextRootBox(); | 1851 RootInlineBox* result = line->nextRootBox(); |
1852 layoutState.setEndLine(result); | 1852 layoutState.setEndLine(result); |
1853 if (result) { | 1853 if (result) { |
1854 layoutState.setEndLineLogicalTop(line->lineBottomWithLeading()); | 1854 layoutState.setEndLineLogicalTop(line->lineBottomWithLeading()); |
1855 matched = checkPaginationAndFloatsAtEndLine(layoutState); | 1855 matched = checkPaginationAndFloatsAtEndLine(layoutState); |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2107 if (!line || !line->isFirstLineStyle()) | 2107 if (!line || !line->isFirstLineStyle()) |
2108 return reason; | 2108 return reason; |
2109 // It's the RootInlineBox that paints the ::first-line background. Note that
since it may be | 2109 // It's the RootInlineBox that paints the ::first-line background. Note that
since it may be |
2110 // expensive to figure out if the first line is affected by any ::first-line
selectors at all, | 2110 // expensive to figure out if the first line is affected by any ::first-line
selectors at all, |
2111 // we just invalidate it unconditionally, since that's typically cheaper. | 2111 // we just invalidate it unconditionally, since that's typically cheaper. |
2112 invalidateDisplayItemClient(*line); | 2112 invalidateDisplayItemClient(*line); |
2113 return reason; | 2113 return reason; |
2114 } | 2114 } |
2115 | 2115 |
2116 } // namespace blink | 2116 } // namespace blink |
OLD | NEW |