Home | History | Annotate | Download | only in line
      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