| 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 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 // CSS3 "text-indent", "each-line" affects the first line of the block conta
iner as well as each line after a forced line break, | 603 // CSS3 "text-indent", "each-line" affects the first line of the block conta
iner as well as each line after a forced line break, |
| 604 // but does not affect lines after a soft wrap break. | 604 // but does not affect lines after a soft wrap break. |
| 605 bool isFirstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent(
)->firstChild() != this); | 605 bool isFirstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent(
)->firstChild() != this); |
| 606 bool isAfterHardLineBreak = lineBox->prevRootBox() && lineBox->prevRootBox()
->endsWithBreak(); | 606 bool isAfterHardLineBreak = lineBox->prevRootBox() && lineBox->prevRootBox()
->endsWithBreak(); |
| 607 IndentTextOrNot shouldIndentText = requiresIndent(isFirstLine, isAfterHardLi
neBreak, style()); | 607 IndentTextOrNot shouldIndentText = requiresIndent(isFirstLine, isAfterHardLi
neBreak, style()); |
| 608 float lineLogicalLeft; | 608 float lineLogicalLeft; |
| 609 float lineLogicalRight; | 609 float lineLogicalRight; |
| 610 float availableLogicalWidth; | 610 float availableLogicalWidth; |
| 611 updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, availa
bleLogicalWidth, isFirstLine, shouldIndentText, 0); | 611 updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, availa
bleLogicalWidth, isFirstLine, shouldIndentText, 0); |
| 612 bool needsWordSpacing; | 612 bool needsWordSpacing; |
| 613 ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo(); | |
| 614 if (shapeInsideInfo && shapeInsideInfo->hasSegments()) { | |
| 615 BidiRun* segmentStart = firstRun; | |
| 616 const SegmentList& segments = shapeInsideInfo->segments(); | |
| 617 float logicalLeft = max<float>(segments[0].logicalLeft, lineLogicalLeft)
; | |
| 618 float logicalRight = min<float>(segments[0].logicalRight, lineLogicalRig
ht); | |
| 619 float startLogicalLeft = logicalLeft; | |
| 620 float endLogicalRight = logicalLeft; | |
| 621 float minLogicalLeft = logicalLeft; | |
| 622 float maxLogicalRight = logicalLeft; | |
| 623 lineBox->beginPlacingBoxRangesInInlineDirection(logicalLeft); | |
| 624 for (size_t i = 0; i < segments.size(); i++) { | |
| 625 if (i) { | |
| 626 logicalLeft = max<float>(segments[i].logicalLeft, lineLogicalLef
t); | |
| 627 logicalRight = min<float>(segments[i].logicalRight, lineLogicalR
ight); | |
| 628 } | |
| 629 availableLogicalWidth = logicalRight - logicalLeft; | |
| 630 BidiRun* newSegmentStart = computeInlineDirectionPositionsForSegment
(lineBox, lineInfo, textAlign, logicalLeft, availableLogicalWidth, segmentStart,
trailingSpaceRun, textBoxDataMap, verticalPositionCache, wordMeasurements); | |
| 631 needsWordSpacing = false; | |
| 632 endLogicalRight = lineBox->placeBoxRangeInInlineDirection(segmentSta
rt->m_box, newSegmentStart ? newSegmentStart->m_box : 0, logicalLeft, minLogical
Left, maxLogicalRight, needsWordSpacing, textBoxDataMap); | |
| 633 if (!newSegmentStart || !newSegmentStart->next()) | |
| 634 break; | |
| 635 ASSERT(newSegmentStart->m_startsSegment); | |
| 636 // Discard the empty segment start marker bidi runs | |
| 637 segmentStart = newSegmentStart->next(); | |
| 638 } | |
| 639 lineBox->endPlacingBoxRangesInInlineDirection(startLogicalLeft, endLogic
alRight, minLogicalLeft, maxLogicalRight); | |
| 640 return; | |
| 641 } | |
| 642 | 613 |
| 643 if (firstRun && firstRun->m_object->isReplaced()) { | 614 if (firstRun && firstRun->m_object->isReplaced()) { |
| 644 RenderBox* renderBox = toRenderBox(firstRun->m_object); | 615 RenderBox* renderBox = toRenderBox(firstRun->m_object); |
| 645 updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, av
ailableLogicalWidth, isFirstLine, shouldIndentText, renderBox->logicalHeight()); | 616 updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, av
ailableLogicalWidth, isFirstLine, shouldIndentText, renderBox->logicalHeight()); |
| 646 } | 617 } |
| 647 | 618 |
| 648 computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, line
LogicalLeft, availableLogicalWidth, firstRun, trailingSpaceRun, textBoxDataMap,
verticalPositionCache, wordMeasurements); | 619 computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, line
LogicalLeft, availableLogicalWidth, firstRun, trailingSpaceRun, textBoxDataMap,
verticalPositionCache, wordMeasurements); |
| 649 // The widths of all runs are now known. We can now place every inline box (
and | 620 // The widths of all runs are now known. We can now place every inline box (
and |
| 650 // compute accurate widths for the inline flow boxes). | 621 // compute accurate widths for the inline flow boxes). |
| 651 needsWordSpacing = false; | 622 needsWordSpacing = false; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 779 static void restoreIsolatedMidpointStates(InlineBidiResolver& topResolver, Inlin
eBidiResolver& isolatedResolver) | 750 static void restoreIsolatedMidpointStates(InlineBidiResolver& topResolver, Inlin
eBidiResolver& isolatedResolver) |
| 780 { | 751 { |
| 781 while (!isolatedResolver.isolatedRuns().isEmpty()) { | 752 while (!isolatedResolver.isolatedRuns().isEmpty()) { |
| 782 BidiRun* run = isolatedResolver.isolatedRuns().last(); | 753 BidiRun* run = isolatedResolver.isolatedRuns().last(); |
| 783 isolatedResolver.isolatedRuns().removeLast(); | 754 isolatedResolver.isolatedRuns().removeLast(); |
| 784 topResolver.setMidpointStateForIsolatedRun(run, isolatedResolver.midpoin
tStateForIsolatedRun(run)); | 755 topResolver.setMidpointStateForIsolatedRun(run, isolatedResolver.midpoin
tStateForIsolatedRun(run)); |
| 785 } | 756 } |
| 786 } | 757 } |
| 787 | 758 |
| 788 // FIXME: BidiResolver should have this logic. | 759 // FIXME: BidiResolver should have this logic. |
| 789 static inline void constructBidiRunsForSegment(InlineBidiResolver& topResolver,
BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfRuns, VisualDirection
Override override, bool previousLineBrokeCleanly, bool isNewUBAParagraph) | 760 static inline void constructBidiRunsForLine(const RenderBlockFlow* block, Inline
BidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator&
endOfLine, VisualDirectionOverride override, bool previousLineBrokeCleanly, boo
l isNewUBAParagraph) |
| 790 { | 761 { |
| 791 // FIXME: We should pass a BidiRunList into createBidiRunsForLine instead | 762 // FIXME: We should pass a BidiRunList into createBidiRunsForLine instead |
| 792 // of the resolver owning the runs. | 763 // of the resolver owning the runs. |
| 793 ASSERT(&topResolver.runs() == &bidiRuns); | 764 ASSERT(&topResolver.runs() == &bidiRuns); |
| 794 ASSERT(topResolver.position() != endOfRuns); | 765 ASSERT(topResolver.position() != endOfLine); |
| 795 RenderObject* currentRoot = topResolver.position().root(); | 766 RenderObject* currentRoot = topResolver.position().root(); |
| 796 topResolver.createBidiRunsForLine(endOfRuns, override, previousLineBrokeClea
nly); | 767 topResolver.createBidiRunsForLine(endOfLine, override, previousLineBrokeClea
nly); |
| 797 | 768 |
| 798 while (!topResolver.isolatedRuns().isEmpty()) { | 769 while (!topResolver.isolatedRuns().isEmpty()) { |
| 799 // It does not matter which order we resolve the runs as long as we reso
lve them all. | 770 // It does not matter which order we resolve the runs as long as we reso
lve them all. |
| 800 BidiRun* isolatedRun = topResolver.isolatedRuns().last(); | 771 BidiRun* isolatedRun = topResolver.isolatedRuns().last(); |
| 801 topResolver.isolatedRuns().removeLast(); | 772 topResolver.isolatedRuns().removeLast(); |
| 802 | 773 |
| 803 RenderObject* startObj = isolatedRun->object(); | 774 RenderObject* startObj = isolatedRun->object(); |
| 804 | 775 |
| 805 // Only inlines make sense with unicode-bidi: isolate (blocks are alread
y isolated). | 776 // Only inlines make sense with unicode-bidi: isolate (blocks are alread
y isolated). |
| 806 // FIXME: Because enterIsolate is not passed a RenderObject, we have to
crawl up the | 777 // FIXME: Because enterIsolate is not passed a RenderObject, we have to
crawl up the |
| (...skipping 22 matching lines...) Expand all Loading... |
| 829 setupResolverToResumeInIsolate(isolatedResolver, isolatedInline, startOb
j); | 800 setupResolverToResumeInIsolate(isolatedResolver, isolatedInline, startOb
j); |
| 830 | 801 |
| 831 // The starting position is the beginning of the first run within the is
olate that was identified | 802 // The starting position is the beginning of the first run within the is
olate that was identified |
| 832 // during the earlier call to createBidiRunsForLine. This can be but is
not necessarily the | 803 // during the earlier call to createBidiRunsForLine. This can be but is
not necessarily the |
| 833 // first run within the isolate. | 804 // first run within the isolate. |
| 834 InlineIterator iter = InlineIterator(isolatedInline, startObj, isolatedR
un->m_start); | 805 InlineIterator iter = InlineIterator(isolatedInline, startObj, isolatedR
un->m_start); |
| 835 isolatedResolver.setPositionIgnoringNestedIsolates(iter); | 806 isolatedResolver.setPositionIgnoringNestedIsolates(iter); |
| 836 // We stop at the next end of line; we may re-enter this isolate in the
next call to constructBidiRuns(). | 807 // We stop at the next end of line; we may re-enter this isolate in the
next call to constructBidiRuns(). |
| 837 // FIXME: What should end and previousLineBrokeCleanly be? | 808 // FIXME: What should end and previousLineBrokeCleanly be? |
| 838 // rniwa says previousLineBrokeCleanly is just a WinIE hack and could al
ways be false here? | 809 // rniwa says previousLineBrokeCleanly is just a WinIE hack and could al
ways be false here? |
| 839 isolatedResolver.createBidiRunsForLine(endOfRuns, NoVisualOverride, prev
iousLineBrokeCleanly); | 810 isolatedResolver.createBidiRunsForLine(endOfLine, NoVisualOverride, prev
iousLineBrokeCleanly); |
| 840 | 811 |
| 841 ASSERT(isolatedResolver.runs().runCount()); | 812 ASSERT(isolatedResolver.runs().runCount()); |
| 842 if (isolatedResolver.runs().runCount()) | 813 if (isolatedResolver.runs().runCount()) |
| 843 bidiRuns.replaceRunWithRuns(isolatedRun, isolatedResolver.runs()); | 814 bidiRuns.replaceRunWithRuns(isolatedRun, isolatedResolver.runs()); |
| 844 | 815 |
| 845 // If we encountered any nested isolate runs, just move them | 816 // If we encountered any nested isolate runs, just move them |
| 846 // to the top resolver's list for later processing. | 817 // to the top resolver's list for later processing. |
| 847 if (!isolatedResolver.isolatedRuns().isEmpty()) { | 818 if (!isolatedResolver.isolatedRuns().isEmpty()) { |
| 848 topResolver.isolatedRuns().appendVector(isolatedResolver.isolatedRun
s()); | 819 topResolver.isolatedRuns().appendVector(isolatedResolver.isolatedRun
s()); |
| 849 currentRoot = isolatedInline; | 820 currentRoot = isolatedInline; |
| 850 restoreIsolatedMidpointStates(topResolver, isolatedResolver); | 821 restoreIsolatedMidpointStates(topResolver, isolatedResolver); |
| 851 } | 822 } |
| 852 } | 823 } |
| 853 } | 824 } |
| 854 | 825 |
| 855 static inline bool segmentIsEmpty(const InlineIterator& segmentStart, const Inli
neIterator& segmentEnd) | |
| 856 { | |
| 857 return segmentStart == segmentEnd; | |
| 858 } | |
| 859 | |
| 860 static inline void constructBidiRunsForLine(const RenderBlockFlow* block, Inline
BidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator&
endOfLine, VisualDirectionOverride override, bool previousLineBrokeCleanly, boo
l isNewUBAParagraph) | |
| 861 { | |
| 862 ShapeInsideInfo* shapeInsideInfo = block->layoutShapeInsideInfo(); | |
| 863 if (!shapeInsideInfo || !shapeInsideInfo->hasSegments()) { | |
| 864 constructBidiRunsForSegment(topResolver, bidiRuns, endOfLine, override,
previousLineBrokeCleanly, isNewUBAParagraph); | |
| 865 return; | |
| 866 } | |
| 867 | |
| 868 const SegmentRangeList& segmentRanges = shapeInsideInfo->segmentRanges(); | |
| 869 ASSERT(segmentRanges.size()); | |
| 870 | |
| 871 for (size_t i = 0; i < segmentRanges.size(); i++) { | |
| 872 LineSegmentIterator iterator = segmentRanges[i].start; | |
| 873 InlineIterator segmentStart(iterator.root, iterator.object, iterator.off
set); | |
| 874 iterator = segmentRanges[i].end; | |
| 875 InlineIterator segmentEnd(iterator.root, iterator.object, iterator.offse
t); | |
| 876 if (i) { | |
| 877 ASSERT(segmentStart.object()); | |
| 878 BidiRun* segmentMarker = createRun(segmentStart.offset(), segmentSta
rt.offset(), segmentStart.object(), topResolver); | |
| 879 segmentMarker->m_startsSegment = true; | |
| 880 bidiRuns.addRun(segmentMarker); | |
| 881 // Do not collapse midpoints between segments | |
| 882 topResolver.midpointState().setBetweenMidpoints(false); | |
| 883 } | |
| 884 if (!segmentIsEmpty(segmentStart, segmentEnd)) { | |
| 885 topResolver.setPosition(segmentStart, numberOfIsolateAncestors(segme
ntStart)); | |
| 886 constructBidiRunsForSegment(topResolver, bidiRuns, segmentEnd, overr
ide, previousLineBrokeCleanly, isNewUBAParagraph); | |
| 887 } | |
| 888 } | |
| 889 } | |
| 890 | |
| 891 // This function constructs line boxes for all of the text runs in the resolver
and computes their position. | 826 // This function constructs line boxes for all of the text runs in the resolver
and computes their position. |
| 892 RootInlineBox* RenderBlockFlow::createLineBoxesFromBidiRuns(unsigned bidiLevel,
BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, V
erticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeas
urements& wordMeasurements) | 827 RootInlineBox* RenderBlockFlow::createLineBoxesFromBidiRuns(unsigned bidiLevel,
BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, V
erticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeas
urements& wordMeasurements) |
| 893 { | 828 { |
| 894 if (!bidiRuns.runCount()) | 829 if (!bidiRuns.runCount()) |
| 895 return 0; | 830 return 0; |
| 896 | 831 |
| 897 // FIXME: Why is this only done when we had runs? | 832 // FIXME: Why is this only done when we had runs? |
| 898 lineInfo.setLastLine(!end.object()); | 833 lineInfo.setLastLine(!end.object()); |
| 899 | 834 |
| 900 RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo); | 835 RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 | 940 |
| 1006 // Before restarting the layout loop with a new logicalHeight, remove all floats
that were added and reset the resolver. | 941 // Before restarting the layout loop with a new logicalHeight, remove all floats
that were added and reset the resolver. |
| 1007 inline const InlineIterator& RenderBlockFlow::restartLayoutRunsAndFloatsInRange(
LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastF
loatFromPreviousLine, InlineBidiResolver& resolver, const InlineIterator& oldEn
d) | 942 inline const InlineIterator& RenderBlockFlow::restartLayoutRunsAndFloatsInRange(
LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastF
loatFromPreviousLine, InlineBidiResolver& resolver, const InlineIterator& oldEn
d) |
| 1008 { | 943 { |
| 1009 removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight); | 944 removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight); |
| 1010 setLogicalHeight(newLogicalHeight); | 945 setLogicalHeight(newLogicalHeight); |
| 1011 resolver.setPositionIgnoringNestedIsolates(oldEnd); | 946 resolver.setPositionIgnoringNestedIsolates(oldEnd); |
| 1012 return oldEnd; | 947 return oldEnd; |
| 1013 } | 948 } |
| 1014 | 949 |
| 1015 static inline LayoutUnit adjustLogicalLineTop(ShapeInsideInfo* shapeInsideInfo,
InlineIterator start, InlineIterator end, const WordMeasurements& wordMeasuremen
ts) | |
| 1016 { | |
| 1017 if (!shapeInsideInfo || end != start) | |
| 1018 return 0; | |
| 1019 | |
| 1020 float minWidth = firstPositiveWidth(wordMeasurements); | |
| 1021 ASSERT(minWidth || wordMeasurements.isEmpty()); | |
| 1022 if (minWidth > 0 && shapeInsideInfo->adjustLogicalLineTop(minWidth)) | |
| 1023 return shapeInsideInfo->logicalLineTop(); | |
| 1024 | |
| 1025 return shapeInsideInfo->shapeLogicalBottom(); | |
| 1026 } | |
| 1027 | |
| 1028 static inline void pushShapeContentOverflowBelowTheContentBox(RenderBlockFlow* b
lock, ShapeInsideInfo* shapeInsideInfo, LayoutUnit lineTop, LayoutUnit lineHeigh
t) | |
| 1029 { | |
| 1030 ASSERT(shapeInsideInfo); | |
| 1031 | |
| 1032 LayoutUnit logicalLineBottom = lineTop + lineHeight; | |
| 1033 LayoutUnit shapeLogicalBottom = shapeInsideInfo->shapeLogicalBottom(); | |
| 1034 LayoutUnit shapeContainingBlockHeight = shapeInsideInfo->shapeContainingBloc
kHeight(); | |
| 1035 | |
| 1036 bool isOverflowPositionedAlready = (shapeContainingBlockHeight - shapeInside
Info->owner().borderAndPaddingAfter() + lineHeight) <= lineTop; | |
| 1037 | |
| 1038 // If the last line overlaps with the shape, we don't need the segments anym
ore | |
| 1039 if (lineTop < shapeLogicalBottom && shapeLogicalBottom < logicalLineBottom) | |
| 1040 shapeInsideInfo->clearSegments(); | |
| 1041 if (logicalLineBottom <= shapeLogicalBottom || !shapeContainingBlockHeight |
| isOverflowPositionedAlready) | |
| 1042 return; | |
| 1043 | |
| 1044 LayoutUnit newLogicalHeight = block->logicalHeight() + (shapeContainingBlock
Height - (lineTop + shapeInsideInfo->owner().borderAndPaddingAfter())); | |
| 1045 block->setLogicalHeight(newLogicalHeight); | |
| 1046 } | |
| 1047 | |
| 1048 void RenderBlockFlow::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& sha
peInsideInfo, const LayoutSize& logicalOffsetFromShapeContainer, LineLayoutState
& layoutState) | |
| 1049 { | |
| 1050 if (layoutState.flowThread()) | |
| 1051 return updateShapeAndSegmentsForCurrentLineInFlowThread(shapeInsideInfo,
layoutState); | |
| 1052 | |
| 1053 if (!shapeInsideInfo) | |
| 1054 return; | |
| 1055 | |
| 1056 LayoutUnit lineTop = logicalHeight() + logicalOffsetFromShapeContainer.heigh
t(); | |
| 1057 LayoutUnit lineLeft = logicalOffsetFromShapeContainer.width(); | |
| 1058 LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(
), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInterior
LineBoxes); | |
| 1059 | |
| 1060 // FIXME: Bug 95361: It is possible for a line to grow beyond lineHeight, in
which case these segments may be incorrect. | |
| 1061 shapeInsideInfo->updateSegmentsForLine(LayoutSize(lineLeft, lineTop), lineHe
ight); | |
| 1062 | |
| 1063 pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, l
ineHeight); | |
| 1064 } | |
| 1065 | |
| 1066 void RenderBlockFlow::updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsi
deInfo*& shapeInsideInfo, LineLayoutState& layoutState) | |
| 1067 { | |
| 1068 ASSERT(layoutState.flowThread()); | |
| 1069 | |
| 1070 RenderRegion* currentRegion = regionAtBlockOffset(logicalHeight()); | |
| 1071 if (!currentRegion || !currentRegion->logicalHeight()) | |
| 1072 return; | |
| 1073 | |
| 1074 shapeInsideInfo = currentRegion->shapeInsideInfo(); | |
| 1075 | |
| 1076 RenderRegion* nextRegion = 0; | |
| 1077 if (!currentRegion->isLastRegion()) { | |
| 1078 RenderRegionList regionList = layoutState.flowThread()->renderRegionList
(); | |
| 1079 RenderRegionList::const_iterator it = regionList.find(currentRegion); | |
| 1080 nextRegion = *(++it); | |
| 1081 } | |
| 1082 | |
| 1083 // We only want to deal regions with shapes, so we check if the next region
has a shape | |
| 1084 if (!shapeInsideInfo && nextRegion && !nextRegion->shapeInsideInfo()) | |
| 1085 return; | |
| 1086 | |
| 1087 LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(
), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInterior
LineBoxes); | |
| 1088 LayoutUnit logicalLineTopInFlowThread = logicalHeight() + offsetFromLogicalT
opOfFirstPage(); | |
| 1089 LayoutUnit logicalLineBottomInFlowThread = logicalLineTopInFlowThread + line
Height; | |
| 1090 LayoutUnit logicalRegionTopInFlowThread = currentRegion->logicalTopForFlowTh
readContent(); | |
| 1091 LayoutUnit logicalRegionBottomInFlowThread = logicalRegionTopInFlowThread +
currentRegion->logicalHeight() - currentRegion->borderAndPaddingBefore() - curre
ntRegion->borderAndPaddingAfter(); | |
| 1092 | |
| 1093 LayoutUnit shapeBottomInFlowThread = LayoutUnit::max(); | |
| 1094 if (shapeInsideInfo) | |
| 1095 shapeBottomInFlowThread = shapeInsideInfo->shapeLogicalBottom() + curren
tRegion->logicalTopForFlowThreadContent(); | |
| 1096 | |
| 1097 bool lineOverLapsWithShapeBottom = shapeBottomInFlowThread < logicalLineBott
omInFlowThread; | |
| 1098 bool lineTopAdjustedIntoNextRegion = layoutState.adjustedLogicalLineTop() >=
currentRegion->logicalHeight(); | |
| 1099 bool lineOverLapsWithRegionBottom = logicalLineBottomInFlowThread > logicalR
egionBottomInFlowThread || lineTopAdjustedIntoNextRegion; | |
| 1100 bool overFlowsToNextRegion = nextRegion && (lineOverLapsWithShapeBottom || l
ineOverLapsWithRegionBottom); | |
| 1101 | |
| 1102 // If the line is between two shapes/regions we position the line to the top
of the next shape/region | |
| 1103 if (overFlowsToNextRegion) { | |
| 1104 ASSERT(currentRegion != nextRegion); | |
| 1105 LayoutUnit deltaToNextRegion = logicalRegionBottomInFlowThread - logical
LineTopInFlowThread; | |
| 1106 setLogicalHeight(logicalHeight() + deltaToNextRegion); | |
| 1107 | |
| 1108 currentRegion = nextRegion; | |
| 1109 shapeInsideInfo = currentRegion->shapeInsideInfo(); | |
| 1110 | |
| 1111 logicalLineTopInFlowThread = logicalHeight() + offsetFromLogicalTopOfFir
stPage(); | |
| 1112 logicalLineBottomInFlowThread = logicalLineTopInFlowThread + lineHeight; | |
| 1113 logicalRegionTopInFlowThread = currentRegion->logicalTopForFlowThreadCon
tent(); | |
| 1114 logicalRegionBottomInFlowThread = logicalRegionTopInFlowThread + current
Region->logicalHeight() - currentRegion->borderAndPaddingBefore() - currentRegio
n->borderAndPaddingAfter(); | |
| 1115 | |
| 1116 if (lineTopAdjustedIntoNextRegion) | |
| 1117 layoutState.setAdjustedLogicalLineTop(0); | |
| 1118 } | |
| 1119 | |
| 1120 if (!shapeInsideInfo) | |
| 1121 return; | |
| 1122 | |
| 1123 bool isFirstLineInRegion = logicalLineBottomInFlowThread <= (logicalRegionTo
pInFlowThread + lineHeight); | |
| 1124 bool isFirstLineAdjusted = (logicalLineTopInFlowThread - logicalRegionTopInF
lowThread) < (layoutState.adjustedLogicalLineTop() - currentRegion->borderAndPad
dingBefore()); | |
| 1125 // We position the first line to the top of the shape in the region or to th
e previously adjusted position in the shape | |
| 1126 if (isFirstLineInRegion || isFirstLineAdjusted) { | |
| 1127 LayoutUnit shapeTopOffset = layoutState.adjustedLogicalLineTop(); | |
| 1128 if (!shapeTopOffset && (shapeInsideInfo->shapeLogicalTop() > 0)) | |
| 1129 shapeTopOffset = shapeInsideInfo->shapeLogicalTop(); | |
| 1130 | |
| 1131 LayoutUnit shapePositionInFlowThread = currentRegion->logicalTopForFlowT
hreadContent() + shapeTopOffset; | |
| 1132 LayoutUnit shapeTopLineTopDelta = shapePositionInFlowThread - logicalLin
eTopInFlowThread - currentRegion->borderAndPaddingBefore(); | |
| 1133 | |
| 1134 setLogicalHeight(logicalHeight() + shapeTopLineTopDelta); | |
| 1135 logicalLineTopInFlowThread += shapeTopLineTopDelta; | |
| 1136 layoutState.setAdjustedLogicalLineTop(0); | |
| 1137 } | |
| 1138 | |
| 1139 LayoutUnit lineTop = logicalLineTopInFlowThread - currentRegion->logicalTopF
orFlowThreadContent() + currentRegion->borderAndPaddingBefore(); | |
| 1140 // FIXME: Shape inside on a region does not yet take into account its paddin
g for nested flow blocks | |
| 1141 shapeInsideInfo->updateSegmentsForLine(LayoutSize(0, lineTop), lineHeight); | |
| 1142 | |
| 1143 if (currentRegion->isLastRegion()) | |
| 1144 pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTo
p, lineHeight); | |
| 1145 } | |
| 1146 | |
| 1147 bool RenderBlockFlow::adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideIn
fo* shapeInsideInfo, LayoutUnit absoluteLogicalTop, LineLayoutState& layoutState
, InlineBidiResolver& resolver, FloatingObject* lastFloatFromPreviousLine, Inlin
eIterator& end, WordMeasurements& wordMeasurements) | |
| 1148 { | |
| 1149 LayoutUnit adjustedLogicalLineTop = adjustLogicalLineTop(shapeInsideInfo, re
solver.position(), end, wordMeasurements); | |
| 1150 | |
| 1151 if (shapeInsideInfo && containsFloats()) { | |
| 1152 lastFloatFromPreviousLine = m_floatingObjects->set().last(); | |
| 1153 if (!wordMeasurements.size()) { | |
| 1154 LayoutUnit floatLogicalTopOffset = shapeInsideInfo->computeFirstFitP
ositionForFloat(logicalSizeForFloat(lastFloatFromPreviousLine)); | |
| 1155 if (logicalHeight() < floatLogicalTopOffset) | |
| 1156 adjustedLogicalLineTop = floatLogicalTopOffset; | |
| 1157 } | |
| 1158 } | |
| 1159 | |
| 1160 if (!adjustedLogicalLineTop) | |
| 1161 return false; | |
| 1162 | |
| 1163 LayoutUnit newLogicalHeight = adjustedLogicalLineTop - absoluteLogicalTop; | |
| 1164 | |
| 1165 if (layoutState.flowThread()) { | |
| 1166 layoutState.setAdjustedLogicalLineTop(adjustedLogicalLineTop); | |
| 1167 newLogicalHeight = logicalHeight(); | |
| 1168 } | |
| 1169 | |
| 1170 end = restartLayoutRunsAndFloatsInRange(logicalHeight(), newLogicalHeight, l
astFloatFromPreviousLine, resolver, end); | |
| 1171 return true; | |
| 1172 } | |
| 1173 | |
| 1174 void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
nlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiSta
tus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines) | 950 void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
nlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiSta
tus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines) |
| 1175 { | 951 { |
| 1176 RenderStyle* styleToUse = style(); | 952 RenderStyle* styleToUse = style(); |
| 1177 bool paginated = view()->layoutState() && view()->layoutState()->isPaginated
(); | 953 bool paginated = view()->layoutState() && view()->layoutState()->isPaginated
(); |
| 1178 LineMidpointState& lineMidpointState = resolver.midpointState(); | 954 LineMidpointState& lineMidpointState = resolver.midpointState(); |
| 1179 InlineIterator endOfLine = resolver.position(); | 955 InlineIterator endOfLine = resolver.position(); |
| 1180 bool checkForEndLineMatch = layoutState.endLine(); | 956 bool checkForEndLineMatch = layoutState.endLine(); |
| 1181 RenderTextInfo renderTextInfo; | 957 RenderTextInfo renderTextInfo; |
| 1182 VerticalPositionCache verticalPositionCache; | 958 VerticalPositionCache verticalPositionCache; |
| 1183 | 959 |
| 1184 LineBreaker lineBreaker(this); | 960 LineBreaker lineBreaker(this); |
| 1185 | 961 |
| 1186 LayoutSize logicalOffsetFromShapeContainer; | 962 LayoutSize logicalOffsetFromShapeContainer; |
| 1187 ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo(); | |
| 1188 if (shapeInsideInfo) { | |
| 1189 ASSERT(&shapeInsideInfo->owner() == this || allowsShapeInsideInfoSharing
(&shapeInsideInfo->owner())); | |
| 1190 if (shapeInsideInfo != this->shapeInsideInfo()) { | |
| 1191 // FIXME Bug 100284: If subsequent LayoutStates are pushed, we will
have to add | |
| 1192 // their offsets from the original shape-inside container. | |
| 1193 logicalOffsetFromShapeContainer = logicalOffsetFromShapeAncestorCont
ainer(&shapeInsideInfo->owner()); | |
| 1194 } | |
| 1195 // Begin layout at the logical top of our shape inside. | |
| 1196 if (logicalHeight() + logicalOffsetFromShapeContainer.height() < shapeIn
sideInfo->shapeLogicalTop()) { | |
| 1197 LayoutUnit logicalHeight = shapeInsideInfo->shapeLogicalTop() - logi
calOffsetFromShapeContainer.height(); | |
| 1198 if (layoutState.flowThread()) | |
| 1199 logicalHeight -= shapeInsideInfo->owner().borderAndPaddingBefore
(); | |
| 1200 setLogicalHeight(logicalHeight); | |
| 1201 } | |
| 1202 } | |
| 1203 | 963 |
| 1204 while (!endOfLine.atEnd()) { | 964 while (!endOfLine.atEnd()) { |
| 1205 // FIXME: Is this check necessary before the first iteration or can it b
e moved to the end? | 965 // FIXME: Is this check necessary before the first iteration or can it b
e moved to the end? |
| 1206 if (checkForEndLineMatch) { | 966 if (checkForEndLineMatch) { |
| 1207 layoutState.setEndLineMatched(matchedEndLine(layoutState, resolver,
cleanLineStart, cleanLineBidiStatus)); | 967 layoutState.setEndLineMatched(matchedEndLine(layoutState, resolver,
cleanLineStart, cleanLineBidiStatus)); |
| 1208 if (layoutState.endLineMatched()) { | 968 if (layoutState.endLineMatched()) { |
| 1209 resolver.setPosition(InlineIterator(resolver.position().root(),
0, 0), 0); | 969 resolver.setPosition(InlineIterator(resolver.position().root(),
0, 0), 0); |
| 1210 break; | 970 break; |
| 1211 } | 971 } |
| 1212 } | 972 } |
| 1213 | 973 |
| 1214 lineMidpointState.reset(); | 974 lineMidpointState.reset(); |
| 1215 | 975 |
| 1216 layoutState.lineInfo().setEmpty(true); | 976 layoutState.lineInfo().setEmpty(true); |
| 1217 layoutState.lineInfo().resetRunsFromLeadingWhitespace(); | 977 layoutState.lineInfo().resetRunsFromLeadingWhitespace(); |
| 1218 | 978 |
| 1219 const InlineIterator previousEndofLine = endOfLine; | 979 const InlineIterator previousEndofLine = endOfLine; |
| 1220 bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly
(); | 980 bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly
(); |
| 1221 FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_float
ingObjects->set().last() : 0; | 981 FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_float
ingObjects->set().last() : 0; |
| 1222 | 982 |
| 1223 updateShapeAndSegmentsForCurrentLine(shapeInsideInfo, logicalOffsetFromS
hapeContainer, layoutState); | |
| 1224 | |
| 1225 WordMeasurements wordMeasurements; | 983 WordMeasurements wordMeasurements; |
| 1226 endOfLine = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(),
renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasu
rements); | 984 endOfLine = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(),
renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasu
rements); |
| 1227 renderTextInfo.m_lineBreakIterator.resetPriorContext(); | 985 renderTextInfo.m_lineBreakIterator.resetPriorContext(); |
| 1228 if (resolver.position().atEnd()) { | 986 if (resolver.position().atEnd()) { |
| 1229 // FIXME: We shouldn't be creating any runs in nextLineBreak to begi
n with! | 987 // FIXME: We shouldn't be creating any runs in nextLineBreak to begi
n with! |
| 1230 // Once BidiRunList is separated from BidiResolver this will not be
needed. | 988 // Once BidiRunList is separated from BidiResolver this will not be
needed. |
| 1231 resolver.runs().deleteRuns(); | 989 resolver.runs().deleteRuns(); |
| 1232 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla
ced by an ASSERT (or just removed). | 990 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla
ced by an ASSERT (or just removed). |
| 1233 layoutState.setCheckForFloatsFromLastLine(true); | 991 layoutState.setCheckForFloatsFromLastLine(true); |
| 1234 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0
), 0); | 992 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0
), 0); |
| 1235 break; | 993 break; |
| 1236 } | 994 } |
| 1237 | 995 |
| 1238 if (adjustLogicalLineTopAndLogicalHeightIfNeeded(shapeInsideInfo, logica
lOffsetFromShapeContainer.height(), layoutState, resolver, lastFloatFromPrevious
Line, endOfLine, wordMeasurements)) | |
| 1239 continue; | |
| 1240 | |
| 1241 ASSERT(endOfLine != resolver.position()); | 996 ASSERT(endOfLine != resolver.position()); |
| 1242 | 997 |
| 1243 // This is a short-cut for empty lines. | 998 // This is a short-cut for empty lines. |
| 1244 if (layoutState.lineInfo().isEmpty()) { | 999 if (layoutState.lineInfo().isEmpty()) { |
| 1245 if (lastRootBox()) | 1000 if (lastRootBox()) |
| 1246 lastRootBox()->setLineBreakInfo(endOfLine.object(), endOfLine.of
fset(), resolver.status()); | 1001 lastRootBox()->setLineBreakInfo(endOfLine.object(), endOfLine.of
fset(), resolver.status()); |
| 1247 } else { | 1002 } else { |
| 1248 VisualDirectionOverride override = (styleToUse->rtlOrdering() == Vis
ualOrder ? (styleToUse->direction() == LTR ? VisualLeftToRightOverride : VisualR
ightToLeftOverride) : NoVisualOverride); | 1003 VisualDirectionOverride override = (styleToUse->rtlOrdering() == Vis
ualOrder ? (styleToUse->direction() == LTR ? VisualLeftToRightOverride : VisualR
ightToLeftOverride) : NoVisualOverride); |
| 1249 if (isNewUBAParagraph && styleToUse->unicodeBidi() == Plaintext && !
resolver.context()->parent()) { | 1004 if (isNewUBAParagraph && styleToUse->unicodeBidi() == Plaintext && !
resolver.context()->parent()) { |
| 1250 TextDirection direction = determinePlaintextDirectionality(resol
ver.position().root(), resolver.position().object(), resolver.position().offset(
)); | 1005 TextDirection direction = determinePlaintextDirectionality(resol
ver.position().root(), resolver.position().object(), resolver.position().offset(
)); |
| (...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2450 float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false).toFloat
(); | 2205 float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false).toFloat
(); |
| 2451 float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), fal
se) - logicalLeft; | 2206 float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), fal
se) - logicalLeft; |
| 2452 updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, totalLogicalWid
th, availableLogicalWidth, 0); | 2207 updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, totalLogicalWid
th, availableLogicalWidth, 0); |
| 2453 | 2208 |
| 2454 if (!style()->isLeftToRightDirection()) | 2209 if (!style()->isLeftToRightDirection()) |
| 2455 return logicalWidth() - logicalLeft; | 2210 return logicalWidth() - logicalLeft; |
| 2456 return logicalLeft; | 2211 return logicalLeft; |
| 2457 } | 2212 } |
| 2458 | 2213 |
| 2459 } | 2214 } |
| OLD | NEW |