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