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 |