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 17 matching lines...) Expand all Loading... |
28 #include "core/rendering/RenderFlowThread.h" | 28 #include "core/rendering/RenderFlowThread.h" |
29 #include "core/rendering/RenderLayer.h" | 29 #include "core/rendering/RenderLayer.h" |
30 #include "core/rendering/RenderListMarker.h" | 30 #include "core/rendering/RenderListMarker.h" |
31 #include "core/rendering/RenderRegion.h" | 31 #include "core/rendering/RenderRegion.h" |
32 #include "core/rendering/RenderRubyRun.h" | 32 #include "core/rendering/RenderRubyRun.h" |
33 #include "core/rendering/RenderView.h" | 33 #include "core/rendering/RenderView.h" |
34 #include "core/rendering/TrailingFloatsRootInlineBox.h" | 34 #include "core/rendering/TrailingFloatsRootInlineBox.h" |
35 #include "core/rendering/VerticalPositionCache.h" | 35 #include "core/rendering/VerticalPositionCache.h" |
36 #include "core/rendering/line/BreakingContextInlineHeaders.h" | 36 #include "core/rendering/line/BreakingContextInlineHeaders.h" |
37 #include "core/rendering/line/LineLayoutState.h" | 37 #include "core/rendering/line/LineLayoutState.h" |
| 38 #include "core/rendering/line/LineWidth.h" |
38 #include "core/rendering/svg/SVGRootInlineBox.h" | 39 #include "core/rendering/svg/SVGRootInlineBox.h" |
39 #include "platform/text/BidiResolver.h" | 40 #include "platform/text/BidiResolver.h" |
40 #include "wtf/RefCountedLeakCounter.h" | 41 #include "wtf/RefCountedLeakCounter.h" |
41 #include "wtf/StdLibExtras.h" | 42 #include "wtf/StdLibExtras.h" |
42 #include "wtf/Vector.h" | 43 #include "wtf/Vector.h" |
43 #include "wtf/unicode/CharacterNames.h" | 44 #include "wtf/unicode/CharacterNames.h" |
44 | 45 |
45 namespace WebCore { | 46 namespace WebCore { |
46 | 47 |
47 using namespace std; | 48 using namespace std; |
48 using namespace WTF::Unicode; | 49 using namespace WTF::Unicode; |
49 | 50 |
50 static IndentTextOrNot requiresIndent(bool isFirstLine, bool isAfterHardLineBrea
k, RenderStyle* style) | |
51 { | |
52 if (isFirstLine) | |
53 return IndentText; | |
54 if (isAfterHardLineBreak && style->textIndentLine() == TextIndentEachLine) | |
55 return IndentText; | |
56 | |
57 return DoNotIndentText; | |
58 } | |
59 | |
60 class LineBreaker { | |
61 public: | |
62 friend class BreakingContext; | |
63 LineBreaker(RenderBlockFlow* block) | |
64 : m_block(block) | |
65 { | |
66 reset(); | |
67 } | |
68 | |
69 InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&
, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines
, WordMeasurements&); | |
70 | |
71 bool lineWasHyphenated() { return m_hyphenated; } | |
72 const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects;
} | |
73 EClear clear() { return m_clear; } | |
74 private: | |
75 void reset(); | |
76 | |
77 InlineIterator nextSegmentBreak(InlineBidiResolver&, LineInfo&, RenderTextIn
fo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLi
nes, WordMeasurements&); | |
78 void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* l
astFloatFromPreviousLine, LineWidth&); | |
79 | |
80 RenderBlockFlow* m_block; | |
81 bool m_hyphenated; | |
82 EClear m_clear; | |
83 Vector<RenderBox*> m_positionedObjects; | |
84 }; | |
85 | |
86 static RenderObject* firstRenderObjectForDirectionalityDetermination(RenderObjec
t* root, RenderObject* current = 0) | 51 static RenderObject* firstRenderObjectForDirectionalityDetermination(RenderObjec
t* root, RenderObject* current = 0) |
87 { | 52 { |
88 RenderObject* next = current; | 53 RenderObject* next = current; |
89 while (current) { | 54 while (current) { |
90 if (isIsolated(current->style()->unicodeBidi()) | 55 if (isIsolated(current->style()->unicodeBidi()) |
91 && (current->isRenderInline() || current->isRenderBlock())) { | 56 && (current->isRenderInline() || current->isRenderBlock())) { |
92 if (current != root) | 57 if (current != root) |
93 current = 0; | 58 current = 0; |
94 else | 59 else |
95 current = next; | 60 current = next; |
(...skipping 1835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1931 ASSERT(inlineObj->parent() == this); | 1896 ASSERT(inlineObj->parent() == this); |
1932 | 1897 |
1933 InlineIterator it(this, inlineObj, 0); | 1898 InlineIterator it(this, inlineObj, 0); |
1934 // FIXME: We should pass correct value for WhitespacePosition. | 1899 // FIXME: We should pass correct value for WhitespacePosition. |
1935 while (!it.atEnd() && !requiresLineBox(it)) | 1900 while (!it.atEnd() && !requiresLineBox(it)) |
1936 it.increment(); | 1901 it.increment(); |
1937 | 1902 |
1938 return !it.atEnd(); | 1903 return !it.atEnd(); |
1939 } | 1904 } |
1940 | 1905 |
1941 void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo&
lineInfo, | |
1942 FloatingObject* lastFloatFr
omPreviousLine, LineWidth& width) | |
1943 { | |
1944 while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(),
lineInfo, LeadingWhitespace)) { | |
1945 RenderObject* object = resolver.position().object(); | |
1946 if (object->isOutOfFlowPositioned()) { | |
1947 setStaticPositions(m_block, toRenderBox(object)); | |
1948 if (object->style()->isOriginalDisplayInlineType()) { | |
1949 resolver.runs().addRun(createRun(0, 1, object, resolver)); | |
1950 lineInfo.incrementRunsFromLeadingWhitespace(); | |
1951 } | |
1952 } else if (object->isFloating()) | |
1953 m_block->positionNewFloatOnLine(m_block->insertFloatingObject(toRend
erBox(object)), lastFloatFromPreviousLine, lineInfo, width); | |
1954 else if (object->isText() && object->style()->hasTextCombine() && object
->isCombineText() && !toRenderCombineText(object)->isCombined()) { | |
1955 toRenderCombineText(object)->combineText(); | |
1956 if (toRenderCombineText(object)->isCombined()) | |
1957 continue; | |
1958 } | |
1959 resolver.position().increment(&resolver); | |
1960 } | |
1961 resolver.commitExplicitEmbedding(); | |
1962 } | |
1963 | |
1964 void LineBreaker::reset() | |
1965 { | |
1966 m_positionedObjects.clear(); | |
1967 m_hyphenated = false; | |
1968 m_clear = CNONE; | |
1969 } | |
1970 | |
1971 InlineIterator LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo
& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviou
sLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements) | |
1972 { | |
1973 ShapeInsideInfo* shapeInsideInfo = m_block->layoutShapeInsideInfo(); | |
1974 | |
1975 if (!shapeInsideInfo || !shapeInsideInfo->lineOverlapsShapeBounds()) | |
1976 return nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFro
mPreviousLine, consecutiveHyphenatedLines, wordMeasurements); | |
1977 | |
1978 InlineIterator end = resolver.position(); | |
1979 InlineIterator oldEnd = end; | |
1980 | |
1981 if (!shapeInsideInfo->hasSegments()) { | |
1982 end = nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFrom
PreviousLine, consecutiveHyphenatedLines, wordMeasurements); | |
1983 resolver.setPositionIgnoringNestedIsolates(oldEnd); | |
1984 return oldEnd; | |
1985 } | |
1986 | |
1987 const SegmentList& segments = shapeInsideInfo->segments(); | |
1988 SegmentRangeList& segmentRanges = shapeInsideInfo->segmentRanges(); | |
1989 | |
1990 for (unsigned i = 0; i < segments.size() && !end.atEnd(); i++) { | |
1991 const InlineIterator segmentStart = resolver.position(); | |
1992 end = nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFrom
PreviousLine, consecutiveHyphenatedLines, wordMeasurements); | |
1993 | |
1994 ASSERT(segmentRanges.size() == i); | |
1995 if (resolver.position().atEnd()) { | |
1996 segmentRanges.append(LineSegmentRange(segmentStart, end)); | |
1997 break; | |
1998 } | |
1999 if (resolver.position() == end) { | |
2000 // Nothing fit this segment | |
2001 end = segmentStart; | |
2002 segmentRanges.append(LineSegmentRange(segmentStart, segmentStart)); | |
2003 resolver.setPositionIgnoringNestedIsolates(segmentStart); | |
2004 } else { | |
2005 // Note that resolver.position is already skipping some of the white
space at the beginning of the line, | |
2006 // so that's why segmentStart might be different than resolver.posit
ion(). | |
2007 LineSegmentRange range(resolver.position(), end); | |
2008 segmentRanges.append(range); | |
2009 resolver.setPosition(end, numberOfIsolateAncestors(end)); | |
2010 | |
2011 if (lineInfo.previousLineBrokeCleanly()) { | |
2012 // If we hit a new line break, just stop adding anything to this
line. | |
2013 break; | |
2014 } | |
2015 } | |
2016 } | |
2017 resolver.setPositionIgnoringNestedIsolates(oldEnd); | |
2018 return end; | |
2019 } | |
2020 | |
2021 InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
nfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPrev
iousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurement
s) | |
2022 { | |
2023 reset(); | |
2024 | |
2025 ASSERT(resolver.position().root() == m_block); | |
2026 | |
2027 bool appliedStartWidth = resolver.position().offset() > 0; | |
2028 | |
2029 LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.is
FirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style())); | |
2030 | |
2031 skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width); | |
2032 | |
2033 if (resolver.position().atEnd()) | |
2034 return resolver.position(); | |
2035 | |
2036 BreakingContext context(resolver, lineInfo, width, renderTextInfo, lastFloat
FromPreviousLine, appliedStartWidth, m_block); | |
2037 | |
2038 while (context.currentObject()) { | |
2039 context.initializeForCurrentObject(); | |
2040 if (context.currentObject()->isBR()) { | |
2041 context.handleBR(m_clear); | |
2042 } else if (context.currentObject()->isOutOfFlowPositioned()) { | |
2043 context.handleOutOfFlowPositioned(m_positionedObjects); | |
2044 } else if (context.currentObject()->isFloating()) { | |
2045 context.handleFloat(); | |
2046 } else if (context.currentObject()->isRenderInline()) { | |
2047 context.handleEmptyInline(); | |
2048 } else if (context.currentObject()->isReplaced()) { | |
2049 context.handleReplaced(); | |
2050 } else if (context.currentObject()->isText()) { | |
2051 if (context.handleText(wordMeasurements, m_hyphenated)) { | |
2052 // We've hit a hard text line break. Our line break iterator is
updated, so go ahead and early return. | |
2053 return context.lineBreak(); | |
2054 } | |
2055 } else { | |
2056 ASSERT_NOT_REACHED(); | |
2057 } | |
2058 | |
2059 if (context.atEnd()) | |
2060 return context.handleEndOfLine(); | |
2061 | |
2062 context.commitAndUpdateLineBreakIfNeeded(); | |
2063 | |
2064 if (context.atEnd()) | |
2065 return context.handleEndOfLine(); | |
2066 | |
2067 context.increment(); | |
2068 } | |
2069 | |
2070 context.clearLineBreakIfFitsOnLine(); | |
2071 | |
2072 return context.handleEndOfLine(); | |
2073 } | |
2074 | 1906 |
2075 void RenderBlockFlow::addOverflowFromInlineChildren() | 1907 void RenderBlockFlow::addOverflowFromInlineChildren() |
2076 { | 1908 { |
2077 LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit(); | 1909 LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit(); |
2078 // FIXME: Need to find another way to do this, since scrollbars could show w
hen we don't want them to. | 1910 // FIXME: Need to find another way to do this, since scrollbars could show w
hen we don't want them to. |
2079 if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElem
ent() && style()->isLeftToRightDirection()) | 1911 if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElem
ent() && style()->isLeftToRightDirection()) |
2080 endPadding = 1; | 1912 endPadding = 1; |
2081 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
{ | 1913 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
{ |
2082 addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding)); | 1914 addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding)); |
2083 LayoutRect visualOverflow = curr->visualOverflowRect(curr->lineTop(), cu
rr->lineBottom()); | 1915 LayoutRect visualOverflow = curr->visualOverflowRect(curr->lineTop(), cu
rr->lineBottom()); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2245 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver
ticalPositionCache); | 2077 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver
ticalPositionCache); |
2246 | 2078 |
2247 setLineGridBox(lineGridBox); | 2079 setLineGridBox(lineGridBox); |
2248 | 2080 |
2249 // FIXME: If any of the characteristics of the box change compared to the ol
d one, then we need to do a deep dirtying | 2081 // FIXME: If any of the characteristics of the box change compared to the ol
d one, then we need to do a deep dirtying |
2250 // (similar to what happens when the page height changes). Ideally, though,
we only do this if someone is actually snapping | 2082 // (similar to what happens when the page height changes). Ideally, though,
we only do this if someone is actually snapping |
2251 // to this grid. | 2083 // to this grid. |
2252 } | 2084 } |
2253 | 2085 |
2254 } | 2086 } |
OLD | NEW |