OLD | NEW |
(Empty) | |
| 1 /* |
| 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. |
| 4 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 5 * |
| 6 * This library is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU Library General Public |
| 8 * License as published by the Free Software Foundation; either |
| 9 * version 2 of the License, or (at your option) any later version. |
| 10 * |
| 11 * This library is distributed in the hope that it will be useful, |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 * Library General Public License for more details. |
| 15 * |
| 16 * You should have received a copy of the GNU Library General Public License |
| 17 * along with this library; see the file COPYING.LIB. If not, write to |
| 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 19 * Boston, MA 02110-1301, USA. |
| 20 * |
| 21 */ |
| 22 |
| 23 #include "config.h" |
| 24 #include "core/rendering/line/LineBreaker.h" |
| 25 |
| 26 #include "core/rendering/line/BreakingContextInlineHeaders.h" |
| 27 |
| 28 namespace WebCore { |
| 29 |
| 30 void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo&
lineInfo, |
| 31 FloatingObject* lastFloatFromPreviousLine, LineWidth& width) |
| 32 { |
| 33 while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(),
lineInfo, LeadingWhitespace)) { |
| 34 RenderObject* object = resolver.position().object(); |
| 35 if (object->isOutOfFlowPositioned()) { |
| 36 setStaticPositions(m_block, toRenderBox(object)); |
| 37 if (object->style()->isOriginalDisplayInlineType()) { |
| 38 resolver.runs().addRun(createRun(0, 1, object, resolver)); |
| 39 lineInfo.incrementRunsFromLeadingWhitespace(); |
| 40 } |
| 41 } else if (object->isFloating()) { |
| 42 m_block->positionNewFloatOnLine(m_block->insertFloatingObject(toRend
erBox(object)), lastFloatFromPreviousLine, lineInfo, width); |
| 43 } else if (object->isText() && object->style()->hasTextCombine() && obje
ct->isCombineText() && !toRenderCombineText(object)->isCombined()) { |
| 44 toRenderCombineText(object)->combineText(); |
| 45 if (toRenderCombineText(object)->isCombined()) |
| 46 continue; |
| 47 } |
| 48 resolver.position().increment(&resolver); |
| 49 } |
| 50 resolver.commitExplicitEmbedding(); |
| 51 } |
| 52 |
| 53 void LineBreaker::reset() |
| 54 { |
| 55 m_positionedObjects.clear(); |
| 56 m_hyphenated = false; |
| 57 m_clear = CNONE; |
| 58 } |
| 59 |
| 60 InlineIterator LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo
& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviou
sLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements) |
| 61 { |
| 62 ShapeInsideInfo* shapeInsideInfo = m_block->layoutShapeInsideInfo(); |
| 63 |
| 64 if (!shapeInsideInfo || !shapeInsideInfo->lineOverlapsShapeBounds()) |
| 65 return nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFro
mPreviousLine, consecutiveHyphenatedLines, wordMeasurements); |
| 66 |
| 67 InlineIterator end = resolver.position(); |
| 68 InlineIterator oldEnd = end; |
| 69 |
| 70 if (!shapeInsideInfo->hasSegments()) { |
| 71 end = nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFrom
PreviousLine, consecutiveHyphenatedLines, wordMeasurements); |
| 72 resolver.setPositionIgnoringNestedIsolates(oldEnd); |
| 73 return oldEnd; |
| 74 } |
| 75 |
| 76 const SegmentList& segments = shapeInsideInfo->segments(); |
| 77 SegmentRangeList& segmentRanges = shapeInsideInfo->segmentRanges(); |
| 78 |
| 79 for (unsigned i = 0; i < segments.size() && !end.atEnd(); i++) { |
| 80 const InlineIterator segmentStart = resolver.position(); |
| 81 end = nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFrom
PreviousLine, consecutiveHyphenatedLines, wordMeasurements); |
| 82 |
| 83 ASSERT(segmentRanges.size() == i); |
| 84 if (resolver.position().atEnd()) { |
| 85 segmentRanges.append(LineSegmentRange(segmentStart, end)); |
| 86 break; |
| 87 } |
| 88 if (resolver.position() == end) { |
| 89 // Nothing fit this segment |
| 90 end = segmentStart; |
| 91 segmentRanges.append(LineSegmentRange(segmentStart, segmentStart)); |
| 92 resolver.setPositionIgnoringNestedIsolates(segmentStart); |
| 93 } else { |
| 94 // Note that resolver.position is already skipping some of the white
space at the beginning of the line, |
| 95 // so that's why segmentStart might be different than resolver.posit
ion(). |
| 96 LineSegmentRange range(resolver.position(), end); |
| 97 segmentRanges.append(range); |
| 98 resolver.setPosition(end, numberOfIsolateAncestors(end)); |
| 99 |
| 100 if (lineInfo.previousLineBrokeCleanly()) { |
| 101 // If we hit a new line break, just stop adding anything to this
line. |
| 102 break; |
| 103 } |
| 104 } |
| 105 } |
| 106 resolver.setPositionIgnoringNestedIsolates(oldEnd); |
| 107 return end; |
| 108 } |
| 109 |
| 110 InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
nfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPrev
iousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurement
s) |
| 111 { |
| 112 reset(); |
| 113 |
| 114 ASSERT(resolver.position().root() == m_block); |
| 115 |
| 116 bool appliedStartWidth = resolver.position().offset() > 0; |
| 117 |
| 118 LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.is
FirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style())); |
| 119 |
| 120 skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width); |
| 121 |
| 122 if (resolver.position().atEnd()) |
| 123 return resolver.position(); |
| 124 |
| 125 BreakingContext context(resolver, lineInfo, width, renderTextInfo, lastFloat
FromPreviousLine, appliedStartWidth, m_block); |
| 126 |
| 127 while (context.currentObject()) { |
| 128 context.initializeForCurrentObject(); |
| 129 if (context.currentObject()->isBR()) { |
| 130 context.handleBR(m_clear); |
| 131 } else if (context.currentObject()->isOutOfFlowPositioned()) { |
| 132 context.handleOutOfFlowPositioned(m_positionedObjects); |
| 133 } else if (context.currentObject()->isFloating()) { |
| 134 context.handleFloat(); |
| 135 } else if (context.currentObject()->isRenderInline()) { |
| 136 context.handleEmptyInline(); |
| 137 } else if (context.currentObject()->isReplaced()) { |
| 138 context.handleReplaced(); |
| 139 } else if (context.currentObject()->isText()) { |
| 140 if (context.handleText(wordMeasurements, m_hyphenated)) { |
| 141 // We've hit a hard text line break. Our line break iterator is
updated, so go ahead and early return. |
| 142 return context.lineBreak(); |
| 143 } |
| 144 } else { |
| 145 ASSERT_NOT_REACHED(); |
| 146 } |
| 147 |
| 148 if (context.atEnd()) |
| 149 return context.handleEndOfLine(); |
| 150 |
| 151 context.commitAndUpdateLineBreakIfNeeded(); |
| 152 |
| 153 if (context.atEnd()) |
| 154 return context.handleEndOfLine(); |
| 155 |
| 156 context.increment(); |
| 157 } |
| 158 |
| 159 context.clearLineBreakIfFitsOnLine(); |
| 160 |
| 161 return context.handleEndOfLine(); |
| 162 } |
| 163 |
| 164 } |
OLD | NEW |