1 /* 2 * Copyright (C) 2000 Lars Knoll (knoll (at) kde.org) 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right 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 blink { 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(toRenderBox(object)), lastFloatFromPreviousLine, lineInfo, width); 43 } else if (object->isText() && object->style()->hasTextCombine() && object->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(resolver.runs()); 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, 61 RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, 62 WordMeasurements& wordMeasurements) 63 { 64 reset(); 65 66 ASSERT(resolver.position().root() == m_block); 67 68 bool appliedStartWidth = resolver.position().offset() > 0; 69 70 LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.isFirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style())); 71 72 skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width); 73 74 if (resolver.position().atEnd()) 75 return resolver.position(); 76 77 BreakingContext context(resolver, lineInfo, width, renderTextInfo, lastFloatFromPreviousLine, appliedStartWidth, m_block); 78 79 while (context.currentObject()) { 80 context.initializeForCurrentObject(); 81 if (context.currentObject()->isBR()) { 82 context.handleBR(m_clear); 83 } else if (context.currentObject()->isOutOfFlowPositioned()) { 84 context.handleOutOfFlowPositioned(m_positionedObjects); 85 } else if (context.currentObject()->isFloating()) { 86 context.handleFloat(); 87 } else if (context.currentObject()->isRenderInline()) { 88 context.handleEmptyInline(); 89 } else if (context.currentObject()->isReplaced()) { 90 context.handleReplaced(); 91 } else if (context.currentObject()->isText()) { 92 if (context.handleText(wordMeasurements, m_hyphenated)) { 93 // We've hit a hard text line break. Our line break iterator is updated, so go ahead and early return. 94 return context.lineBreak(); 95 } 96 } else { 97 ASSERT_NOT_REACHED(); 98 } 99 100 if (context.atEnd()) 101 return context.handleEndOfLine(); 102 103 context.commitAndUpdateLineBreakIfNeeded(); 104 105 if (context.atEnd()) 106 return context.handleEndOfLine(); 107 108 context.increment(); 109 } 110 111 context.clearLineBreakIfFitsOnLine(); 112 113 return context.handleEndOfLine(); 114 } 115 116 } 117