Changeset 159354 in webkit


Ignore:
Timestamp:
Nov 15, 2013 1:40:59 PM (11 years ago)
Author:
zoltan@webkit.org
Message:

Move BreakingContext and LineBreaker into their own files
<https://webkit.org/b/124336>

Reviewed by David Hyatt.

In this change I introduced 'line' subdirectory inside 'rendering', this directory will contain all the classes
which have been refactored from RenderBlockLineLayout.cpp. This change contains the separation of BreakingContext,
and the separation of LineBreaker classes. Since I wanted to keep the helper functions organized, I also added a
new file called LineInlineHeaders.h, which contains the functions which used in LineBreaker.h and BreakingContext.h.
I moved LineInfo class into line directory. It was necessary this time, since I added a cpp for it. I'll move the
rest of the line layout related helper classes later. (I wanted to minimize merge conflicts.)

No new tests, no behavior change.

  • CMakeLists.txt:
  • GNUmakefile.am:
  • GNUmakefile.list.am:
  • WebCore.vcxproj/WebCore.vcxproj:
  • WebCore.vcxproj/WebCoreCommon.props:
  • WebCore.xcodeproj/project.pbxproj:
  • rendering/RenderBlockLineLayout.cpp:

(WebCore::createRun):

  • rendering/line/BreakingContextInlineHeaders.h: Added.

(WebCore::WordMeasurement::WordMeasurement):
(WebCore::TrailingObjects::TrailingObjects):
(WebCore::TrailingObjects::setTrailingWhitespace):
(WebCore::TrailingObjects::clear):
(WebCore::TrailingObjects::appendBoxIfNeeded):
(WebCore::deprecatedAddMidpoint):
(WebCore::startIgnoringSpaces):
(WebCore::stopIgnoringSpaces):
(WebCore::ensureLineBoxInsideIgnoredSpaces):
(WebCore::TrailingObjects::updateMidpointsForTrailingBoxes):
(WebCore::BreakingContext::BreakingContext):
(WebCore::BreakingContext::currentObject):
(WebCore::BreakingContext::lineBreak):
(WebCore::BreakingContext::lineBreakRef):
(WebCore::BreakingContext::lineWidth):
(WebCore::BreakingContext::atEnd):
(WebCore::BreakingContext::clearLineBreakIfFitsOnLine):
(WebCore::BreakingContext::commitLineBreakAtCurrentWidth):
(WebCore::BreakingContext::initializeForCurrentObject):
(WebCore::BreakingContext::increment):
(WebCore::BreakingContext::handleBR):
(WebCore::borderPaddingMarginStart):
(WebCore::borderPaddingMarginEnd):
(WebCore::shouldAddBorderPaddingMargin):
(WebCore::previousInFlowSibling):
(WebCore::inlineLogicalWidth):
(WebCore::BreakingContext::handleOutOfFlowPositioned):
(WebCore::BreakingContext::handleFloat):
(WebCore::shouldSkipWhitespaceAfterStartObject):
(WebCore::BreakingContext::handleEmptyInline):
(WebCore::BreakingContext::handleReplaced):
(WebCore::firstPositiveWidth):
(WebCore::updateSegmentsForShapes):
(WebCore::iteratorIsBeyondEndOfRenderCombineText):
(WebCore::nextCharacter):
(WebCore::updateCounterIfNeeded):
(WebCore::measureHyphenWidth):
(WebCore::textWidth):
(WebCore::ensureCharacterGetsLineBox):
(WebCore::tryHyphenating):
(WebCore::BreakingContext::handleText):
(WebCore::textBeginsWithBreakablePosition):
(WebCore::BreakingContext::canBreakAtThisPosition):
(WebCore::BreakingContext::commitAndUpdateLineBreakIfNeeded):
(WebCore::checkMidpoints):
(WebCore::BreakingContext::handleEndOfLine):

  • rendering/line/LineBreaker.cpp: Added.

(WebCore::LineBreaker::reset):
(WebCore::LineBreaker::skipTrailingWhitespace):
(WebCore::LineBreaker::skipLeadingWhitespace):

  • rendering/line/LineBreaker.h: Added.

(WebCore::LineBreaker::LineBreaker):
(WebCore::LineBreaker::lineWasHyphenated):
(WebCore::LineBreaker::positionedObjects):
(WebCore::LineBreaker::clear):

  • rendering/line/LineInfo.cpp: Added.

(WebCore::LineInfo::setEmpty):

  • rendering/line/LineInfo.h: Renamed from Source/WebCore/rendering/LineInfo.h.

(WebCore::LineInfo::LineInfo):
(WebCore::LineInfo::isFirstLine):
(WebCore::LineInfo::isLastLine):
(WebCore::LineInfo::isEmpty):
(WebCore::LineInfo::previousLineBrokeCleanly):
(WebCore::LineInfo::floatPaginationStrut):
(WebCore::LineInfo::runsFromLeadingWhitespace):
(WebCore::LineInfo::resetRunsFromLeadingWhitespace):
(WebCore::LineInfo::incrementRunsFromLeadingWhitespace):
(WebCore::LineInfo::setFirstLine):
(WebCore::LineInfo::setLastLine):
(WebCore::LineInfo::setPreviousLineBrokeCleanly):
(WebCore::LineInfo::setFloatPaginationStrut):

  • rendering/line/LineInlineHeaders.h: Added.

(WebCore::hasInlineDirectionBordersPaddingOrMargin):
(WebCore::lineStyle):
(WebCore::requiresLineBoxForContent):
(WebCore::shouldCollapseWhiteSpace):
(WebCore::skipNonBreakingSpace):
(WebCore::alwaysRequiresLineBox):
(WebCore::requiresLineBox):
(WebCore::setStaticPositions):

Location:
trunk/Source/WebCore
Files:
6 added
8 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/CMakeLists.txt

    r159268 r159354  
    7777    "${WEBCORE_DIR}/plugins"
    7878    "${WEBCORE_DIR}/rendering"
     79    "${WEBCORE_DIR}/rendering/line"
    7980    "${WEBCORE_DIR}/rendering/mathml"
    8081    "${WEBCORE_DIR}/rendering/shapes"
     
    22102211    rendering/break_lines.cpp
    22112212
     2213    rendering/line/LineBreaker.cpp
     2214    rendering/line/LineInfo.cpp
     2215
    22122216    rendering/mathml/RenderMathMLBlock.cpp
    22132217    rendering/mathml/RenderMathMLFenced.cpp
  • trunk/Source/WebCore/ChangeLog

    r159353 r159354  
     12013-11-15  Zoltan Horvath  <zoltan@webkit.org>
     2
     3        Move BreakingContext and LineBreaker into their own files
     4        <https://webkit.org/b/124336>
     5
     6        Reviewed by David Hyatt.
     7
     8        In this change I introduced 'line' subdirectory inside 'rendering', this directory will contain all the classes
     9        which have been refactored from RenderBlockLineLayout.cpp. This change contains the separation of BreakingContext,
     10        and the separation of LineBreaker classes. Since I wanted to keep the helper functions organized, I also added a
     11        new file called LineInlineHeaders.h, which contains the functions which used in LineBreaker.h and BreakingContext.h.
     12        I moved LineInfo class into line directory. It was necessary this time, since I added a cpp for it. I'll move the
     13        rest of the line layout related helper classes later. (I wanted to minimize merge conflicts.)
     14
     15        No new tests, no behavior change.
     16
     17        * CMakeLists.txt:
     18        * GNUmakefile.am:
     19        * GNUmakefile.list.am:
     20        * WebCore.vcxproj/WebCore.vcxproj:
     21        * WebCore.vcxproj/WebCoreCommon.props:
     22        * WebCore.xcodeproj/project.pbxproj:
     23        * rendering/RenderBlockLineLayout.cpp:
     24        (WebCore::createRun):
     25        * rendering/line/BreakingContextInlineHeaders.h: Added.
     26        (WebCore::WordMeasurement::WordMeasurement):
     27        (WebCore::TrailingObjects::TrailingObjects):
     28        (WebCore::TrailingObjects::setTrailingWhitespace):
     29        (WebCore::TrailingObjects::clear):
     30        (WebCore::TrailingObjects::appendBoxIfNeeded):
     31        (WebCore::deprecatedAddMidpoint):
     32        (WebCore::startIgnoringSpaces):
     33        (WebCore::stopIgnoringSpaces):
     34        (WebCore::ensureLineBoxInsideIgnoredSpaces):
     35        (WebCore::TrailingObjects::updateMidpointsForTrailingBoxes):
     36        (WebCore::BreakingContext::BreakingContext):
     37        (WebCore::BreakingContext::currentObject):
     38        (WebCore::BreakingContext::lineBreak):
     39        (WebCore::BreakingContext::lineBreakRef):
     40        (WebCore::BreakingContext::lineWidth):
     41        (WebCore::BreakingContext::atEnd):
     42        (WebCore::BreakingContext::clearLineBreakIfFitsOnLine):
     43        (WebCore::BreakingContext::commitLineBreakAtCurrentWidth):
     44        (WebCore::BreakingContext::initializeForCurrentObject):
     45        (WebCore::BreakingContext::increment):
     46        (WebCore::BreakingContext::handleBR):
     47        (WebCore::borderPaddingMarginStart):
     48        (WebCore::borderPaddingMarginEnd):
     49        (WebCore::shouldAddBorderPaddingMargin):
     50        (WebCore::previousInFlowSibling):
     51        (WebCore::inlineLogicalWidth):
     52        (WebCore::BreakingContext::handleOutOfFlowPositioned):
     53        (WebCore::BreakingContext::handleFloat):
     54        (WebCore::shouldSkipWhitespaceAfterStartObject):
     55        (WebCore::BreakingContext::handleEmptyInline):
     56        (WebCore::BreakingContext::handleReplaced):
     57        (WebCore::firstPositiveWidth):
     58        (WebCore::updateSegmentsForShapes):
     59        (WebCore::iteratorIsBeyondEndOfRenderCombineText):
     60        (WebCore::nextCharacter):
     61        (WebCore::updateCounterIfNeeded):
     62        (WebCore::measureHyphenWidth):
     63        (WebCore::textWidth):
     64        (WebCore::ensureCharacterGetsLineBox):
     65        (WebCore::tryHyphenating):
     66        (WebCore::BreakingContext::handleText):
     67        (WebCore::textBeginsWithBreakablePosition):
     68        (WebCore::BreakingContext::canBreakAtThisPosition):
     69        (WebCore::BreakingContext::commitAndUpdateLineBreakIfNeeded):
     70        (WebCore::checkMidpoints):
     71        (WebCore::BreakingContext::handleEndOfLine):
     72        * rendering/line/LineBreaker.cpp: Added.
     73        (WebCore::LineBreaker::reset):
     74        (WebCore::LineBreaker::skipTrailingWhitespace):
     75        (WebCore::LineBreaker::skipLeadingWhitespace):
     76        * rendering/line/LineBreaker.h: Added.
     77        (WebCore::LineBreaker::LineBreaker):
     78        (WebCore::LineBreaker::lineWasHyphenated):
     79        (WebCore::LineBreaker::positionedObjects):
     80        (WebCore::LineBreaker::clear):
     81        * rendering/line/LineInfo.cpp: Added.
     82        (WebCore::LineInfo::setEmpty):
     83        * rendering/line/LineInfo.h: Renamed from Source/WebCore/rendering/LineInfo.h.
     84        (WebCore::LineInfo::LineInfo):
     85        (WebCore::LineInfo::isFirstLine):
     86        (WebCore::LineInfo::isLastLine):
     87        (WebCore::LineInfo::isEmpty):
     88        (WebCore::LineInfo::previousLineBrokeCleanly):
     89        (WebCore::LineInfo::floatPaginationStrut):
     90        (WebCore::LineInfo::runsFromLeadingWhitespace):
     91        (WebCore::LineInfo::resetRunsFromLeadingWhitespace):
     92        (WebCore::LineInfo::incrementRunsFromLeadingWhitespace):
     93        (WebCore::LineInfo::setFirstLine):
     94        (WebCore::LineInfo::setLastLine):
     95        (WebCore::LineInfo::setPreviousLineBrokeCleanly):
     96        (WebCore::LineInfo::setFloatPaginationStrut):
     97        * rendering/line/LineInlineHeaders.h: Added.
     98        (WebCore::hasInlineDirectionBordersPaddingOrMargin):
     99        (WebCore::lineStyle):
     100        (WebCore::requiresLineBoxForContent):
     101        (WebCore::shouldCollapseWhiteSpace):
     102        (WebCore::skipNonBreakingSpace):
     103        (WebCore::alwaysRequiresLineBox):
     104        (WebCore::requiresLineBox):
     105        (WebCore::setStaticPositions):
     106
    11072013-11-15  Brady Eidson  <beidson@apple.com>
    2108
  • trunk/Source/WebCore/GNUmakefile.am

    r159335 r159354  
    9292        -I$(srcdir)/Source/WebCore/plugins/win \
    9393        -I$(srcdir)/Source/WebCore/rendering \
     94        -I$(srcdir)/Source/WebCore/rendering/line \
    9495        -I$(srcdir)/Source/WebCore/rendering/mathml \
    9596        -I$(srcdir)/Source/WebCore/rendering/shapes \
  • trunk/Source/WebCore/GNUmakefile.list.am

    r159349 r159354  
    43024302        Source/WebCore/rendering/LayoutRepainter.h \
    43034303        Source/WebCore/rendering/LayoutRepainter.cpp \
    4304         Source/WebCore/rendering/LineInfo.h \
    43054304        Source/WebCore/rendering/LineLayoutState.h \
    43064305        Source/WebCore/rendering/LineWidth.h \
     
    45074506        Source/WebCore/rendering/TextPaintStyle.h \
    45084507        Source/WebCore/rendering/VerticalPositionCache.h \
     4508        Source/WebCore/rendering/line/BreakingContextInlineHeaders.h \
     4509        Source/WebCore/rendering/line/LineInfo.h \
     4510        Source/WebCore/rendering/line/LineInfo.cpp \
     4511        Source/WebCore/rendering/line/LineBreaker.h \
     4512        Source/WebCore/rendering/line/LineBreaker.cpp \
     4513        Source/WebCore/rendering/line/LineInlineHeaders.h \
    45094514        Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp \
    45104515        Source/WebCore/rendering/mathml/RenderMathMLBlock.h \
  • trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj

    r159349 r159354  
    1105111051    <ClCompile Include="..\rendering\SimpleLineLayoutFunctions.cpp" />
    1105211052    <ClCompile Include="..\rendering\TextPaintStyle.cpp" />
     11053    <ClCompile Include="..\rendering\line\LineBreaker.cpp" />
     11054    <ClCompile Include="..\rendering\line\LineInfo.cpp" />
    1105311055    <ClCompile Include="..\rendering\shapes\PolygonShape.cpp" />
    1105411056    <ClCompile Include="..\rendering\shapes\RasterShape.cpp" />
     
    1978019782    <ClInclude Include="..\rendering\LayoutRepainter.h" />
    1978119783    <ClInclude Include="..\rendering\LayoutState.h" />
    19782     <ClInclude Include="..\rendering\LineInfo.h" />
    1978319784    <ClInclude Include="..\rendering\LineLayoutState.h" />
    1978419785    <ClInclude Include="..\rendering\LineWidth.h" />
     
    1985519856    <ClInclude Include="..\rendering\RenderSlider.h" />
    1985619857    <ClInclude Include="..\rendering\RenderSnapshottedPlugIn.h" />
     19858    <ClInclude Include="..\rendering\line\BreakingContextInlineHeaders.h" />
     19859    <ClInclude Include="..\rendering\line\LineBreaker.h" />
     19860    <ClInclude Include="..\rendering\line\LineInfo.h" />
     19861    <ClInclude Include="..\rendering\line\LineInlineHeaders.h" />
    1985719862    <ClInclude Include="..\rendering\shapes\PolygonShape.h" />
    1985819863    <ClInclude Include="..\rendering\shapes\RasterShape.h" />
  • trunk/Source/WebCore/WebCore.vcxproj/WebCoreCommon.props

    r157432 r159354  
    88  <ItemDefinitionGroup>
    99    <ClCompile>
    10       <AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)..\Modules\mediacontrols;$(ProjectDir)..\Modules\mediastream;$(ProjectDir)..\Modules\filesystem;$(ProjectDir)..\Modules\geolocation;$(ProjectDir)..\Modules\indexeddb;$(ProjectDir)..\Modules\mediasource;$(ProjectDir)..\Modules\navigatorcontentutils;$(ProjectDir)..\Modules\speech;$(ProjectDir)..\Modules\proximity;$(ProjectDir)..\Modules\quota;$(ProjectDir)..\Modules\notifications;$(ProjectDir)..\Modules\webdatabase;$(ProjectDir)..\Modules\websockets;$(ProjectDir)..\accessibility;$(ProjectDir)..\accessibility\win;$(ProjectDir)..\bridge;$(ProjectDir)..\bridge\c;$(ProjectDir)..\bridge\jsc;$(ProjectDir)..\css;$(ProjectDir)..\editing;$(ProjectDir)..\fileapi;$(ProjectDir)..\rendering;$(ProjectDir)..\rendering\mathml;$(ProjectDir)..\rendering\shapes;$(ProjectDir)..\rendering\style;$(ProjectDir)..\rendering\svg;$(ProjectDir)..\bindings;$(ProjectDir)..\bindings\generic;$(ProjectDir)..\bindings\js;$(ProjectDir)..\bindings\js\specialization;$(ProjectDir)..\dom;$(ProjectDir)..\dom\default;$(ProjectDir)..\history;$(ProjectDir)..\html;$(ProjectDir)..\html\canvas;$(ProjectDir)..\html\forms;$(ProjectDir)..\html\parser;$(ProjectDir)..\html\shadow;$(ProjectDir)..\html\track;$(ProjectDir)..\inspector;$(ProjectDir)..\loader;$(ProjectDir)..\loader\appcache;$(ProjectDir)..\loader\archive;$(ProjectDir)..\loader\archive\cf;$(ProjectDir)..\loader\cache;$(ProjectDir)..\loader\icon;$(ProjectDir)..\mathml;$(ProjectDir)..\page;$(ProjectDir)..\page\animation;$(ProjectDir)..\page\scrolling;$(ProjectDir)..\page\win;$(ProjectDir)..\platform;$(ProjectDir)..\platform\animation;$(ProjectDir)..\platform\mock;$(ProjectDir)..\platform\sql;$(ProjectDir)..\platform\win;$(ProjectDir)..\platform\network;$(ProjectDir)..\platform\network\win;$(ProjectDir)..\platform\cf;$(ProjectDir)..\platform\graphics;$(ProjectDir)..\platform\graphics\ca;$(ProjectDir)..\platform\graphics\cpu\arm\filters;$(ProjectDir)..\platform\graphics\filters;$(ProjectDir)..\platform\graphics\filters\arm;$(ProjectDir)..\platform\graphics\opentype;$(ProjectDir)..\platform\graphics\transforms;$(ProjectDir)..\platform\text;$(ProjectDir)..\platform\text\transcoder;$(ProjectDir)..\platform\graphics\win;$(ProjectDir)..\xml;$(ProjectDir)..\xml\parser;$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\WebCore\DerivedSources;$(ProjectDir)..\plugins;$(ProjectDir)..\plugins\win;$(ProjectDir)..\svg\animation;$(ProjectDir)..\svg\graphics;$(ProjectDir)..\svg\properties;$(ProjectDir)..\svg\graphics\filters;$(ProjectDir)..\svg;$(ProjectDir)..\testing;$(ProjectDir)..\crypto;$(ProjectDir)..\wml;$(ProjectDir)..\storage;$(ProjectDir)..\style;$(ProjectDir)..\websockets;$(ProjectDir)..\workers;$(ConfigurationBuildDir)\include;$(ConfigurationBuildDir)\include\private;$(ConfigurationBuildDir)\include\JavaScriptCore;$(ConfigurationBuildDir)\include\private\JavaScriptCore;$(ProjectDir)..\ForwardingHeaders;$(ProjectDir)..\platform\graphics\gpu;$(ProjectDir)..\platform\graphics\egl;$(ProjectDir)..\platform\graphics\surfaces;$(ProjectDir)..\platform\graphics\surfaces\egl;$(ProjectDir)..\platform\graphics\opengl;$(WebKit_Libraries)\include;$(WebKit_Libraries)\include\private;$(WebKit_Libraries)\include\private\JavaScriptCore;$(WebKit_Libraries)\include\sqlite;$(WebKit_Libraries)\include\JavaScriptCore;$(WebKit_Libraries)\include\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     10      <AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)..\Modules\mediacontrols;$(ProjectDir)..\Modules\mediastream;$(ProjectDir)..\Modules\filesystem;$(ProjectDir)..\Modules\geolocation;$(ProjectDir)..\Modules\indexeddb;$(ProjectDir)..\Modules\mediasource;$(ProjectDir)..\Modules\navigatorcontentutils;$(ProjectDir)..\Modules\speech;$(ProjectDir)..\Modules\proximity;$(ProjectDir)..\Modules\quota;$(ProjectDir)..\Modules\notifications;$(ProjectDir)..\Modules\webdatabase;$(ProjectDir)..\Modules\websockets;$(ProjectDir)..\accessibility;$(ProjectDir)..\accessibility\win;$(ProjectDir)..\bridge;$(ProjectDir)..\bridge\c;$(ProjectDir)..\bridge\jsc;$(ProjectDir)..\css;$(ProjectDir)..\editing;$(ProjectDir)..\fileapi;$(ProjectDir)..\rendering;$(ProjectDir)..\rendering\line;$(ProjectDir)..\rendering\mathml;$(ProjectDir)..\rendering\shapes;$(ProjectDir)..\rendering\style;$(ProjectDir)..\rendering\svg;$(ProjectDir)..\bindings;$(ProjectDir)..\bindings\generic;$(ProjectDir)..\bindings\js;$(ProjectDir)..\bindings\js\specialization;$(ProjectDir)..\dom;$(ProjectDir)..\dom\default;$(ProjectDir)..\history;$(ProjectDir)..\html;$(ProjectDir)..\html\canvas;$(ProjectDir)..\html\forms;$(ProjectDir)..\html\parser;$(ProjectDir)..\html\shadow;$(ProjectDir)..\html\track;$(ProjectDir)..\inspector;$(ProjectDir)..\loader;$(ProjectDir)..\loader\appcache;$(ProjectDir)..\loader\archive;$(ProjectDir)..\loader\archive\cf;$(ProjectDir)..\loader\cache;$(ProjectDir)..\loader\icon;$(ProjectDir)..\mathml;$(ProjectDir)..\page;$(ProjectDir)..\page\animation;$(ProjectDir)..\page\scrolling;$(ProjectDir)..\page\win;$(ProjectDir)..\platform;$(ProjectDir)..\platform\animation;$(ProjectDir)..\platform\mock;$(ProjectDir)..\platform\sql;$(ProjectDir)..\platform\win;$(ProjectDir)..\platform\network;$(ProjectDir)..\platform\network\win;$(ProjectDir)..\platform\cf;$(ProjectDir)..\platform\graphics;$(ProjectDir)..\platform\graphics\ca;$(ProjectDir)..\platform\graphics\cpu\arm\filters;$(ProjectDir)..\platform\graphics\filters;$(ProjectDir)..\platform\graphics\filters\arm;$(ProjectDir)..\platform\graphics\opentype;$(ProjectDir)..\platform\graphics\transforms;$(ProjectDir)..\platform\text;$(ProjectDir)..\platform\text\transcoder;$(ProjectDir)..\platform\graphics\win;$(ProjectDir)..\xml;$(ProjectDir)..\xml\parser;$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\WebCore\DerivedSources;$(ProjectDir)..\plugins;$(ProjectDir)..\plugins\win;$(ProjectDir)..\svg\animation;$(ProjectDir)..\svg\graphics;$(ProjectDir)..\svg\properties;$(ProjectDir)..\svg\graphics\filters;$(ProjectDir)..\svg;$(ProjectDir)..\testing;$(ProjectDir)..\crypto;$(ProjectDir)..\wml;$(ProjectDir)..\storage;$(ProjectDir)..\style;$(ProjectDir)..\websockets;$(ProjectDir)..\workers;$(ConfigurationBuildDir)\include;$(ConfigurationBuildDir)\include\private;$(ConfigurationBuildDir)\include\JavaScriptCore;$(ConfigurationBuildDir)\include\private\JavaScriptCore;$(ProjectDir)..\ForwardingHeaders;$(ProjectDir)..\platform\graphics\gpu;$(ProjectDir)..\platform\graphics\egl;$(ProjectDir)..\platform\graphics\surfaces;$(ProjectDir)..\platform\graphics\surfaces\egl;$(ProjectDir)..\platform\graphics\opengl;$(WebKit_Libraries)\include;$(WebKit_Libraries)\include\private;$(WebKit_Libraries)\include\private\JavaScriptCore;$(WebKit_Libraries)\include\sqlite;$(WebKit_Libraries)\include\JavaScriptCore;$(WebKit_Libraries)\include\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    1111      <PreprocessorDefinitions>DISABLE_3D_RENDERING;WEBCORE_CONTEXT_MENUS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    1212      <PrecompiledHeader>Use</PrecompiledHeader>
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r159353 r159354  
    34383438                A024575116CEAA27000E5671 /* EXTDrawBuffers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A024574E16CEAA27000E5671 /* EXTDrawBuffers.cpp */; };
    34393439                A024575216CEAA27000E5671 /* EXTDrawBuffers.h in Headers */ = {isa = PBXBuildFile; fileRef = A024574F16CEAA27000E5671 /* EXTDrawBuffers.h */; };
    3440                 A06BFE2E17DFB43F008302BB /* LineInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = A06BFE2C17DFB433008302BB /* LineInfo.h */; };
    34413440                A07D3355152B630E001B6393 /* JSWebGLShaderPrecisionFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A07D3353152B630E001B6393 /* JSWebGLShaderPrecisionFormat.cpp */; };
    34423441                A07D3356152B630E001B6393 /* JSWebGLShaderPrecisionFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = A07D3354152B630E001B6393 /* JSWebGLShaderPrecisionFormat.h */; };
     
    63006299                FF945ECB161F7F3600971BC8 /* PseudoElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FF945EC9161F7F3600971BC8 /* PseudoElement.cpp */; };
    63016300                FF945ECC161F7F3600971BC8 /* PseudoElement.h in Headers */ = {isa = PBXBuildFile; fileRef = FF945ECA161F7F3600971BC8 /* PseudoElement.h */; };
     6301                FFB698CC1833EE0D00158A31 /* LineBreaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FFB698CA1833EC3800158A31 /* LineBreaker.cpp */; };
     6302                FFB698CF183402BB00158A31 /* LineInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FFB698CD1833F17600158A31 /* LineInfo.cpp */; };
    63026303                FFD5B97A135CC97800D5E92A /* PageVisibilityState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FFD5B977135CC97800D5E92A /* PageVisibilityState.cpp */; };
    63036304                FFD5B97B135CC97800D5E92A /* PageVisibilityState.h in Headers */ = {isa = PBXBuildFile; fileRef = FFD5B978135CC97800D5E92A /* PageVisibilityState.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    1020710208                A024574F16CEAA27000E5671 /* EXTDrawBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EXTDrawBuffers.h; path = canvas/EXTDrawBuffers.h; sourceTree = "<group>"; };
    1020810209                A024575016CEAA27000E5671 /* EXTDrawBuffers.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = EXTDrawBuffers.idl; path = canvas/EXTDrawBuffers.idl; sourceTree = "<group>"; };
    10209                 A06BFE2C17DFB433008302BB /* LineInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineInfo.h; sourceTree = "<group>"; };
    1021010210                A0718BE817E26F1600F6BF44 /* LineLayoutState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineLayoutState.h; sourceTree = "<group>"; };
    1021110211                A07D3353152B630E001B6393 /* JSWebGLShaderPrecisionFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLShaderPrecisionFormat.cpp; sourceTree = "<group>"; };
     
    1347313473                FF945EC9161F7F3600971BC8 /* PseudoElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PseudoElement.cpp; sourceTree = "<group>"; };
    1347413474                FF945ECA161F7F3600971BC8 /* PseudoElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PseudoElement.h; sourceTree = "<group>"; };
     13475                FFB698C91832F10B00158A31 /* BreakingContextInlineHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BreakingContextInlineHeaders.h; sourceTree = "<group>"; };
     13476                FFB698CA1833EC3800158A31 /* LineBreaker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LineBreaker.cpp; sourceTree = "<group>"; };
     13477                FFB698CB1833EC3800158A31 /* LineBreaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineBreaker.h; sourceTree = "<group>"; };
     13478                FFB698CD1833F17600158A31 /* LineInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LineInfo.cpp; sourceTree = "<group>"; };
     13479                FFB698CE1833F17600158A31 /* LineInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineInfo.h; sourceTree = "<group>"; };
    1347513480                FFD5B977135CC97800D5E92A /* PageVisibilityState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageVisibilityState.cpp; sourceTree = "<group>"; };
    1347613481                FFD5B978135CC97800D5E92A /* PageVisibilityState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageVisibilityState.h; sourceTree = "<group>"; };
     
    2090220907                        isa = PBXGroup;
    2090320908                        children = (
     20909                                FFB698C81832F10B00158A31 /* line */,
    2090420910                                CDE7FC42181904B1002BBB77 /* OrderIterator.cpp */,
    2090520911                                CDE7FC43181904B1002BBB77 /* OrderIterator.h */,
     
    2095020956                                2D9066040BE141D400956998 /* LayoutState.cpp */,
    2095120957                                2D9066050BE141D400956998 /* LayoutState.h */,
    20952                                 A06BFE2C17DFB433008302BB /* LineInfo.h */,
    2095320958                                A0718BE817E26F1600F6BF44 /* LineLayoutState.h */,
    2095420959                                A0CB002317DF81AC0017896B /* LineWidth.cpp */,
     
    2188821893                        );
    2188921894                        name = WebAudio;
     21895                        sourceTree = "<group>";
     21896                };
     21897                FFB698C81832F10B00158A31 /* line */ = {
     21898                        isa = PBXGroup;
     21899                        children = (
     21900                                FFB698CD1833F17600158A31 /* LineInfo.cpp */,
     21901                                FFB698CE1833F17600158A31 /* LineInfo.h */,
     21902                                FFB698CA1833EC3800158A31 /* LineBreaker.cpp */,
     21903                                FFB698CB1833EC3800158A31 /* LineBreaker.h */,
     21904                                FFB698C91832F10B00158A31 /* BreakingContextInlineHeaders.h */,
     21905                        );
     21906                        path = line;
    2189021907                        sourceTree = "<group>";
    2189121908                };
     
    2518325200                                BC10D76817D8EE71005E2626 /* RenderBlockFlow.h in Headers */,
    2518425201                                A0CB002517DF826C0017896B /* LineWidth.h in Headers */,
    25185                                 A06BFE2E17DFB43F008302BB /* LineInfo.h in Headers */,
    2518625202                                CD3E251C18046B0600E27F56 /* GridCoordinate.h in Headers */,
    2518725203                                CD3E252418046BCD00E27F56 /* CSSGridTemplateValue.h in Headers */,
     
    2576825784                                A80E6D050A1989CA007FB8C5 /* CSSPrimitiveValue.cpp in Sources */,
    2576925785                                A80E6CF70A1989CA007FB8C5 /* CSSProperty.cpp in Sources */,
     25786                                FFB698CC1833EE0D00158A31 /* LineBreaker.cpp in Sources */,
    2577025787                                78D02BC5154A18DF00B62D05 /* CSSPropertyAnimation.cpp in Sources */,
    2577125788                                1ABA76CA11D20E50004C201C /* CSSPropertyNames.cpp in Sources */,
     
    2657426591                                9392262F10321084006E7D5D /* JSCSSRuleListCustom.cpp in Sources */,
    2657526592                                142011B60A003133008303F9 /* JSCSSStyleDeclaration.cpp in Sources */,
     26593                                FFB698CF183402BB00158A31 /* LineInfo.cpp in Sources */,
    2657626594                                BC5825F30C0B89380053F1B5 /* JSCSSStyleDeclarationCustom.cpp in Sources */,
    2657726595                                BC46C2060C0DDCA10020CFC3 /* JSCSSStyleRule.cpp in Sources */,
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r159347 r159354  
    44 * Copyright (C) 2010 Google Inc. All rights reserved.
    55 * Copyright (C) 2013 ChangSeok Oh <shivamidow@gmail.com>
     6 * Copyright (C) 2013 Adobe Systems Inc. All right reserved.
    67 *
    78 * This library is free software; you can redistribute it and/or
     
    2627#include "AXObjectCache.h"
    2728#include "BidiResolver.h"
     29#include "BreakingContextInlineHeaders.h"
    2830#include "FloatingObjects.h"
    29 #include "Hyphenation.h"
    3031#include "InlineElementBox.h"
    3132#include "InlineIterator.h"
    3233#include "InlineTextBox.h"
    33 #include "LineInfo.h"
    3434#include "LineLayoutState.h"
    3535#include "Logging.h"
    3636#include "RenderBlockFlow.h"
    37 #include "RenderCombineText.h"
    38 #include "RenderCounter.h"
    3937#include "RenderFlowThread.h"
    40 #include "RenderInline.h"
    41 #include "RenderLayer.h"
    4238#include "RenderLineBreak.h"
    43 #include "RenderListMarker.h"
    4439#include "RenderRegion.h"
    45 #include "RenderRubyRun.h"
    4640#include "RenderView.h"
    4741#include "Settings.h"
     
    4943#include "TrailingFloatsRootInlineBox.h"
    5044#include "VerticalPositionCache.h"
    51 #include "break_lines.h"
    5245#include <wtf/RefCountedLeakCounter.h>
    5346#include <wtf/StdLibExtras.h>
    54 #include <wtf/Vector.h>
    55 #include <wtf/unicode/CharacterNames.h>
    56 
    57 #if ENABLE(CSS_SHAPES)
    58 #include "ShapeInsideInfo.h"
    59 #endif
    6047
    6148#if ENABLE(SVG)
    62 #include "RenderSVGInlineText.h"
    6349#include "SVGRootInlineBox.h"
    6450#endif
    6551
    66 using namespace WTF;
    67 using namespace Unicode;
    68 
    6952namespace WebCore {
    70 
    71 // We don't let our line box tree for a single line get any deeper than this.
    72 const unsigned cMaxLineDepth = 200;
    73 
    74 struct RenderTextInfo {
    75     // Destruction of m_layout requires TextLayout to be a complete type, so the constructor and destructor are made non-inline to avoid compilation errors.
    76     RenderTextInfo();
    77     ~RenderTextInfo();
    78 
    79     RenderText* m_text;
    80     OwnPtr<TextLayout> m_layout;
    81     LazyLineBreakIterator m_lineBreakIterator;
    82     const Font* m_font;
    83 };
    84 
    85 class LineBreaker {
    86 public:
    87     friend class BreakingContext;
    88     LineBreaker(RenderBlockFlow& block)
    89         : m_block(block)
    90     {
    91         reset();
    92     }
    93 
    94     InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
    95 
    96     bool lineWasHyphenated() { return m_hyphenated; }
    97     const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; }
    98     EClear clear() { return m_clear; }
    99 
    100 private:
    101     void reset();
    102 
    103     InlineIterator nextSegmentBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
    104     void skipTrailingWhitespace(InlineIterator&, const LineInfo&);
    105     void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
    106 
    107     RenderBlockFlow& m_block;
    108     bool m_hyphenated;
    109     EClear m_clear;
    110     Vector<RenderBox*> m_positionedObjects;
    111 };
    112 
    113 static inline LayoutUnit borderPaddingMarginStart(const RenderInline& child)
    114 {
    115     return child.marginStart() + child.paddingStart() + child.borderStart();
    116 }
    117 
    118 static inline LayoutUnit borderPaddingMarginEnd(const RenderInline& child)
    119 {
    120     return child.marginEnd() + child.paddingEnd() + child.borderEnd();
    121 }
    122 
    123 static inline bool shouldAddBorderPaddingMargin(RenderObject* child)
    124 {
    125     // When deciding whether we're at the edge of an inline, adjacent collapsed whitespace is the same as no sibling at all.
    126     return !child || (child->isText() && !toRenderText(child)->textLength());
    127 }
    128 
    129 static RenderObject* previousInFlowSibling(RenderObject* child)
    130 {
    131     child = child->previousSibling();
    132     while (child && child->isOutOfFlowPositioned())
    133         child = child->previousSibling();
    134     return child;
    135 }
    136 
    137 static LayoutUnit inlineLogicalWidth(RenderObject* child, bool checkStartEdge = true, bool checkEndEdge = true)
    138 {
    139     unsigned lineDepth = 1;
    140     LayoutUnit extraWidth = 0;
    141     RenderElement* parent = child->parent();
    142     while (parent->isRenderInline() && lineDepth++ < cMaxLineDepth) {
    143         const RenderInline& parentAsRenderInline = toRenderInline(*parent);
    144         if (!isEmptyInline(parentAsRenderInline)) {
    145             checkStartEdge = checkStartEdge && shouldAddBorderPaddingMargin(previousInFlowSibling(child));
    146             if (checkStartEdge)
    147                 extraWidth += borderPaddingMarginStart(parentAsRenderInline);
    148             checkEndEdge = checkEndEdge && shouldAddBorderPaddingMargin(child->nextSibling());
    149             if (checkEndEdge)
    150                 extraWidth += borderPaddingMarginEnd(parentAsRenderInline);
    151             if (!checkStartEdge && !checkEndEdge)
    152                 return extraWidth;
    153         }
    154         child = parent;
    155         parent = child->parent();
    156     }
    157     return extraWidth;
    158 }
    15953
    16054static void determineDirectionality(TextDirection& dir, InlineIterator iter)
     
    17872}
    17973
    180 static void checkMidpoints(LineMidpointState& lineMidpointState, InlineIterator& lBreak)
    181 {
    182     // Check to see if our last midpoint is a start point beyond the line break.  If so,
    183     // shave it off the list, and shave off a trailing space if the previous end point doesn't
    184     // preserve whitespace.
    185     if (lBreak.m_obj && lineMidpointState.numMidpoints && !(lineMidpointState.numMidpoints % 2)) {
    186         InlineIterator* midpoints = lineMidpointState.midpoints.data();
    187         InlineIterator& endpoint = midpoints[lineMidpointState.numMidpoints - 2];
    188         const InlineIterator& startpoint = midpoints[lineMidpointState.numMidpoints - 1];
    189         InlineIterator currpoint = endpoint;
    190         while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
    191             currpoint.increment();
    192         if (currpoint == lBreak) {
    193             // We hit the line break before the start point.  Shave off the start point.
    194             lineMidpointState.numMidpoints--;
    195             if (endpoint.m_obj->style().collapseWhiteSpace() && endpoint.m_obj->isText())
    196                 endpoint.m_pos--;
    197         }
    198     }
    199 }
    200 
    201 // Don't call this directly. Use one of the descriptive helper functions below.
    202 static void deprecatedAddMidpoint(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
    203 {
    204     if (lineMidpointState.midpoints.size() <= lineMidpointState.numMidpoints)
    205         lineMidpointState.midpoints.grow(lineMidpointState.numMidpoints + 10);
    206 
    207     InlineIterator* midpoints = lineMidpointState.midpoints.data();
    208     midpoints[lineMidpointState.numMidpoints++] = midpoint;
    209 }
    210 
    211 static inline void startIgnoringSpaces(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
    212 {
    213     ASSERT(!(lineMidpointState.numMidpoints % 2));
    214     deprecatedAddMidpoint(lineMidpointState, midpoint);
    215 }
    216 
    217 static inline void stopIgnoringSpaces(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
    218 {
    219     ASSERT(lineMidpointState.numMidpoints % 2);
    220     deprecatedAddMidpoint(lineMidpointState, midpoint);
    221 }
    222 
    223 // When ignoring spaces, this needs to be called for objects that need line boxes such as RenderInlines or
    224 // hard line breaks to ensure that they're not ignored.
    225 static inline void ensureLineBoxInsideIgnoredSpaces(LineMidpointState& lineMidpointState, RenderObject* renderer)
    226 {
    227     InlineIterator midpoint(0, renderer, 0);
    228     stopIgnoringSpaces(lineMidpointState, midpoint);
    229     startIgnoringSpaces(lineMidpointState, midpoint);
    230 }
    231 
    232 // Adding a pair of midpoints before a character will split it out into a new line box.
    233 static inline void ensureCharacterGetsLineBox(LineMidpointState& lineMidpointState, InlineIterator& textParagraphSeparator)
    234 {
    235     InlineIterator midpoint(0, textParagraphSeparator.m_obj, textParagraphSeparator.m_pos);
    236     startIgnoringSpaces(lineMidpointState, InlineIterator(0, textParagraphSeparator.m_obj, textParagraphSeparator.m_pos - 1));
    237     stopIgnoringSpaces(lineMidpointState, InlineIterator(0, textParagraphSeparator.m_obj, textParagraphSeparator.m_pos));
    238 }
    239 
    240 static inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
     74inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
    24175{
    24276    ASSERT(obj);
     
    304138}
    305139
    306 
    307140static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false)
    308141{
     
    328161
    329162    return toRenderInline(obj)->createAndAppendInlineFlowBox();
    330 }
    331 
    332 // FIXME: Don't let counters mark themselves as needing pref width recalcs during layout
    333 // so we don't need this hack.
    334 static inline void updateCounterIfNeeded(RenderText& renderText)
    335 {
    336     if (!renderText.preferredLogicalWidthsDirty() || !renderText.isCounter())
    337         return;
    338     toRenderCounter(renderText).updateCounter();
    339163}
    340164
     
    604428    setMarginStartForChild(renderer, -startOverhang);
    605429    setMarginEndForChild(renderer, -endOverhang);
    606 }
    607 
    608 static inline float measureHyphenWidth(RenderText* renderer, const Font& font, HashSet<const SimpleFontData*>* fallbackFonts = 0)
    609 {
    610     const RenderStyle& style = renderer->style();
    611     return font.width(RenderBlock::constructTextRun(renderer, font, style.hyphenString().string(), style), fallbackFonts);
    612 }
    613 
    614 class WordMeasurement {
    615 public:
    616     WordMeasurement()
    617         : renderer(0)
    618         , width(0)
    619         , startOffset(0)
    620         , endOffset(0)
    621     {
    622     }
    623    
    624     RenderText* renderer;
    625     float width;
    626     int startOffset;
    627     int endOffset;
    628     HashSet<const SimpleFontData*> fallbackFonts;
    629 };
    630 
    631 static inline const RenderStyle& lineStyle(const RenderElement& renderer, const LineInfo& lineInfo)
    632 {
    633     return lineInfo.isFirstLine() ? renderer.firstLineStyle() : renderer.style();
    634430}
    635431
     
    998794}
    999795
    1000 
    1001 static void setStaticPositions(RenderBlockFlow& block, RenderBox& child)
    1002 {
    1003     // FIXME: The math here is actually not really right. It's a best-guess approximation that
    1004     // will work for the common cases
    1005     RenderElement* containerBlock = child.container();
    1006     LayoutUnit blockHeight = block.logicalHeight();
    1007     if (containerBlock->isRenderInline()) {
    1008         // A relative positioned inline encloses us. In this case, we also have to determine our
    1009         // position as though we were an inline. Set |staticInlinePosition| and |staticBlockPosition| on the relative positioned
    1010         // inline so that we can obtain the value later.
    1011         toRenderInline(containerBlock)->layer()->setStaticInlinePosition(block.startAlignedOffsetForLine(blockHeight, false));
    1012         toRenderInline(containerBlock)->layer()->setStaticBlockPosition(blockHeight);
    1013     }
    1014     block.updateStaticInlinePositionForChild(child, blockHeight);
    1015     child.layer()->setStaticBlockPosition(blockHeight);
    1016 }
    1017 
    1018796template <typename CharacterType>
    1019797static inline int findFirstTrailingSpace(const RenderText& lastText, const CharacterType* characters, int start, int stop)
     
    14651243    if (currentRegion->isLastRegion())
    14661244        pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
    1467 }
    1468 
    1469 static inline float firstPositiveWidth(const WordMeasurements& wordMeasurements)
    1470 {
    1471     for (size_t i = 0; i < wordMeasurements.size(); ++i) {
    1472         if (wordMeasurements[i].width > 0)
    1473             return wordMeasurements[i].width;
    1474     }
    1475     return 0;
    14761245}
    14771246
     
    22261995}
    22271996
    2228 static inline bool skipNonBreakingSpace(const InlineIterator& it, const LineInfo& lineInfo)
    2229 {
    2230     if (it.m_obj->style().nbspMode() != SPACE || it.current() != noBreakSpace)
    2231         return false;
    2232 
    2233     // FIXME: This is bad.  It makes nbsp inconsistent with space and won't work correctly
    2234     // with m_minWidth/m_maxWidth.
    2235     // Do not skip a non-breaking space if it is the first character
    2236     // on a line after a clean line break (or on the first line, since previousLineBrokeCleanly starts off
    2237     // |true|).
    2238     if (lineInfo.isEmpty() && lineInfo.previousLineBrokeCleanly())
    2239         return false;
    2240 
    2241     return true;
    2242 }
    2243 
    2244 enum WhitespacePosition { LeadingWhitespace, TrailingWhitespace };
    2245 static inline bool shouldCollapseWhiteSpace(const RenderStyle* style, const LineInfo& lineInfo, WhitespacePosition whitespacePosition)
    2246 {
    2247     // CSS2 16.6.1
    2248     // If a space (U+0020) at the beginning of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is removed.
    2249     // If a space (U+0020) at the end of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is also removed.
    2250     // If spaces (U+0020) or tabs (U+0009) at the end of a line have 'white-space' set to 'pre-wrap', UAs may visually collapse them.
    2251     return style->collapseWhiteSpace()
    2252         || (whitespacePosition == TrailingWhitespace && style->whiteSpace() == PRE_WRAP && (!lineInfo.isEmpty() || !lineInfo.previousLineBrokeCleanly()));
    2253 }
    2254 
    2255 static bool requiresLineBoxForContent(const RenderInline& flow, const LineInfo& lineInfo)
    2256 {
    2257     RenderElement* parent = flow.parent();
    2258     if (flow.document().inNoQuirksMode()) {
    2259         const RenderStyle& flowStyle = lineStyle(flow, lineInfo);
    2260         const RenderStyle& parentStyle = lineStyle(*parent, lineInfo);
    2261         if (flowStyle.lineHeight() != parentStyle.lineHeight()
    2262             || flowStyle.verticalAlign() != parentStyle.verticalAlign()
    2263             || !parentStyle.font().fontMetrics().hasIdenticalAscentDescentAndLineGap(flowStyle.font().fontMetrics()))
    2264         return true;
    2265     }
    2266     return false;
    2267 }
    2268 
    2269 static bool hasInlineDirectionBordersPaddingOrMargin(const RenderInline& flow)
    2270 {
    2271     // Where an empty inline is split across anonymous blocks we should only give lineboxes to the 'sides' of the
    2272     // inline that have borders, padding or margin.
    2273     bool shouldApplyStartBorderPaddingOrMargin = !flow.parent()->isAnonymousBlock() || !flow.isInlineElementContinuation();
    2274     if (shouldApplyStartBorderPaddingOrMargin && (flow.borderStart() || flow.marginStart() || flow.paddingStart()))
    2275         return true;
    2276 
    2277     bool shouldApplyEndBorderPaddingOrMargin = !flow.parent()->isAnonymousBlock() || flow.isInlineElementContinuation() || !flow.inlineElementContinuation();
    2278     return shouldApplyEndBorderPaddingOrMargin && (flow.borderEnd() || flow.marginEnd() || flow.paddingEnd());
    2279 }
    2280 
    2281 static bool alwaysRequiresLineBox(const RenderInline& flow)
    2282 {
    2283     // FIXME: Right now, we only allow line boxes for inlines that are truly empty.
    2284     // We need to fix this, though, because at the very least, inlines containing only
    2285     // ignorable whitespace should should also have line boxes.
    2286     return isEmptyInline(flow) && hasInlineDirectionBordersPaddingOrMargin(flow);
    2287 }
    2288 
    2289 static bool requiresLineBox(const InlineIterator& it, const LineInfo& lineInfo = LineInfo(), WhitespacePosition whitespacePosition = LeadingWhitespace)
    2290 {
    2291     if (it.m_obj->isFloatingOrOutOfFlowPositioned())
    2292         return false;
    2293 
    2294     if (it.m_obj->isBR())
    2295         return true;
    2296 
    2297     bool rendererIsEmptyInline = false;
    2298     if (it.m_obj->isRenderInline()) {
    2299         const RenderInline& inlineRenderer = toRenderInline(*it.m_obj);
    2300         if (!alwaysRequiresLineBox(inlineRenderer) && !requiresLineBoxForContent(inlineRenderer, lineInfo))
    2301             return false;
    2302         rendererIsEmptyInline = isEmptyInline(inlineRenderer);
    2303     }
    2304 
    2305     if (!shouldCollapseWhiteSpace(&it.m_obj->style(), lineInfo, whitespacePosition))
    2306         return true;
    2307 
    2308     UChar current = it.current();
    2309     bool notJustWhitespace = current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || it.m_obj->preservesNewline()) && !skipNonBreakingSpace(it, lineInfo);
    2310     return notJustWhitespace || rendererIsEmptyInline;
    2311 }
    2312 
    23131997bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
    23141998{
     
    23212005
    23222006    return !it.atEnd();
    2323 }
    2324 
    2325 // FIXME: The entire concept of the skipTrailingWhitespace function is flawed, since we really need to be building
    2326 // line boxes even for containers that may ultimately collapse away. Otherwise we'll never get positioned
    2327 // elements quite right. In other words, we need to build this function's work into the normal line
    2328 // object iteration process.
    2329 // NB. this function will insert any floating elements that would otherwise
    2330 // be skipped but it will not position them.
    2331 void LineBreaker::skipTrailingWhitespace(InlineIterator& iterator, const LineInfo& lineInfo)
    2332 {
    2333     while (!iterator.atEnd() && !requiresLineBox(iterator, lineInfo, TrailingWhitespace)) {
    2334         RenderObject& object = *iterator.m_obj;
    2335         if (object.isOutOfFlowPositioned())
    2336             setStaticPositions(m_block, toRenderBox(object));
    2337         else if (object.isFloating())
    2338             m_block.insertFloatingObject(toRenderBox(object));
    2339         iterator.increment();
    2340     }
    2341 }
    2342 
    2343 void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo, FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
    2344 {
    2345     while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) {
    2346         RenderObject& object = *resolver.position().m_obj;
    2347         if (object.isOutOfFlowPositioned()) {
    2348             setStaticPositions(m_block, toRenderBox(object));
    2349             if (object.style().isOriginalDisplayInlineType()) {
    2350                 resolver.runs().addRun(createRun(0, 1, &object, resolver));
    2351                 lineInfo.incrementRunsFromLeadingWhitespace();
    2352             }
    2353         } else if (object.isFloating()) {
    2354             // The top margin edge of a self-collapsing block that clears a float intrudes up into it by the height of the margin,
    2355             // so in order to place this first child float at the top content edge of the self-collapsing block add the margin back in before placement.
    2356             LayoutUnit marginOffset = (!object.previousSibling() && m_block.isSelfCollapsingBlock() && m_block.style().clear() && m_block.getClearDelta(m_block, LayoutUnit())) ? m_block.collapsedMarginBeforeForChild(m_block) : LayoutUnit();
    2357             LayoutUnit oldLogicalHeight = m_block.logicalHeight();
    2358             m_block.setLogicalHeight(oldLogicalHeight + marginOffset);
    2359             m_block.positionNewFloatOnLine(m_block.insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, lineInfo, width);
    2360             m_block.setLogicalHeight(oldLogicalHeight);
    2361         } else if (object.isText() && object.style().hasTextCombine() && object.isCombineText() && !toRenderCombineText(object).isCombined()) {
    2362             toRenderCombineText(object).combineText();
    2363             if (toRenderCombineText(object).isCombined())
    2364                 continue;
    2365         }
    2366         resolver.increment();
    2367     }
    2368     resolver.commitExplicitEmbedding();
    2369 }
    2370 
    2371 // This is currently just used for list markers and inline flows that have line boxes. Neither should
    2372 // have an effect on whitespace at the start of the line.
    2373 static bool shouldSkipWhitespaceAfterStartObject(RenderBlockFlow& block, RenderObject* o, LineMidpointState& lineMidpointState)
    2374 {
    2375     RenderObject* next = bidiNextSkippingEmptyInlines(block, o);
    2376     while (next && next->isFloatingOrOutOfFlowPositioned())
    2377         next = bidiNextSkippingEmptyInlines(block, next);
    2378 
    2379     if (next && next->isText() && toRenderText(next)->textLength() > 0) {
    2380         RenderText* nextText = toRenderText(next);
    2381         UChar nextChar = nextText->characterAt(0);
    2382         if (nextText->style().isCollapsibleWhiteSpace(nextChar)) {
    2383             startIgnoringSpaces(lineMidpointState, InlineIterator(0, o, 0));
    2384             return true;
    2385         }
    2386     }
    2387 
    2388     return false;
    2389 }
    2390 
    2391 static ALWAYS_INLINE float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<const SimpleFontData*>& fallbackFonts, TextLayout* layout = 0)
    2392 {
    2393     const RenderStyle& style = text->style();
    2394 
    2395     GlyphOverflow glyphOverflow;
    2396     if (isFixedPitch || (!from && len == text->textLength()) || style.hasTextCombine())
    2397         return text->width(from, len, font, xPos, &fallbackFonts, &glyphOverflow);
    2398 
    2399     if (layout)
    2400         return Font::width(*layout, from, len, &fallbackFonts);
    2401 
    2402     TextRun run = RenderBlock::constructTextRun(text, font, text, from, len, style);
    2403     run.setCharactersLength(text->textLength() - from);
    2404     ASSERT(run.charactersLength() >= run.length());
    2405 
    2406     run.setCharacterScanForCodePath(!text->canUseSimpleFontCodePath());
    2407     run.setTabSize(!collapseWhiteSpace, style.tabSize());
    2408     run.setXPos(xPos);
    2409     return font.width(run, &fallbackFonts, &glyphOverflow);
    2410 }
    2411 
    2412 static void tryHyphenating(RenderText* text, const Font& font, const AtomicString& localeIdentifier, unsigned consecutiveHyphenatedLines, int consecutiveHyphenatedLinesLimit, int minimumPrefixLimit, int minimumSuffixLimit, unsigned lastSpace, unsigned pos, float xPos, int availableWidth, bool isFixedPitch, bool collapseWhiteSpace, int lastSpaceWordSpacing, InlineIterator& lineBreak, int nextBreakable, bool& hyphenated)
    2413 {
    2414     // Map 'hyphenate-limit-{before,after}: auto;' to 2.
    2415     unsigned minimumPrefixLength;
    2416     unsigned minimumSuffixLength;
    2417 
    2418     if (minimumPrefixLimit < 0)
    2419         minimumPrefixLength = 2;
    2420     else
    2421         minimumPrefixLength = static_cast<unsigned>(minimumPrefixLimit);
    2422 
    2423     if (minimumSuffixLimit < 0)
    2424         minimumSuffixLength = 2;
    2425     else
    2426         minimumSuffixLength = static_cast<unsigned>(minimumSuffixLimit);
    2427 
    2428     if (pos - lastSpace <= minimumSuffixLength)
    2429         return;
    2430 
    2431     if (consecutiveHyphenatedLinesLimit >= 0 && consecutiveHyphenatedLines >= static_cast<unsigned>(consecutiveHyphenatedLinesLimit))
    2432         return;
    2433 
    2434     int hyphenWidth = measureHyphenWidth(text, font);
    2435 
    2436     float maxPrefixWidth = availableWidth - xPos - hyphenWidth - lastSpaceWordSpacing;
    2437     // If the maximum width available for the prefix before the hyphen is small, then it is very unlikely
    2438     // that an hyphenation opportunity exists, so do not bother to look for it.
    2439     if (maxPrefixWidth <= font.pixelSize() * 5 / 4)
    2440         return;
    2441 
    2442     const RenderStyle& style = text->style();
    2443     TextRun run = RenderBlock::constructTextRun(text, font, text, lastSpace, pos - lastSpace, style);
    2444     run.setCharactersLength(text->textLength() - lastSpace);
    2445     ASSERT(run.charactersLength() >= run.length());
    2446 
    2447     run.setTabSize(!collapseWhiteSpace, style.tabSize());
    2448     run.setXPos(xPos + lastSpaceWordSpacing);
    2449 
    2450     unsigned prefixLength = font.offsetForPosition(run, maxPrefixWidth, false);
    2451     if (prefixLength < minimumPrefixLength)
    2452         return;
    2453 
    2454     prefixLength = lastHyphenLocation(text->characters() + lastSpace, pos - lastSpace, std::min(prefixLength, pos - lastSpace - minimumSuffixLength) + 1, localeIdentifier);
    2455     if (!prefixLength || prefixLength < minimumPrefixLength)
    2456         return;
    2457 
    2458     // When lastSapce is a space, which it always is except sometimes at the beginning of a line or after collapsed
    2459     // space, it should not count towards hyphenate-limit-before.
    2460     if (prefixLength == minimumPrefixLength) {
    2461         UChar characterAtLastSpace = text->characterAt(lastSpace);
    2462         if (characterAtLastSpace == ' ' || characterAtLastSpace == '\n' || characterAtLastSpace == '\t' || characterAtLastSpace == noBreakSpace)
    2463             return;
    2464     }
    2465 
    2466     ASSERT(pos - lastSpace - prefixLength >= minimumSuffixLength);
    2467 
    2468 #if !ASSERT_DISABLED
    2469     HashSet<const SimpleFontData*> fallbackFonts;
    2470     float prefixWidth = hyphenWidth + textWidth(text, lastSpace, prefixLength, font, xPos, isFixedPitch, collapseWhiteSpace, fallbackFonts) + lastSpaceWordSpacing;
    2471     ASSERT(xPos + prefixWidth <= availableWidth);
    2472 #else
    2473     UNUSED_PARAM(isFixedPitch);
    2474 #endif
    2475 
    2476     lineBreak.moveTo(text, lastSpace + prefixLength, nextBreakable);
    2477     hyphenated = true;
    2478 }
    2479 
    2480 class TrailingObjects {
    2481 public:
    2482     TrailingObjects();
    2483     void setTrailingWhitespace(RenderText*);
    2484     void clear();
    2485     void appendBoxIfNeeded(RenderBoxModelObject*);
    2486 
    2487     enum CollapseFirstSpaceOrNot { DoNotCollapseFirstSpace, CollapseFirstSpace };
    2488 
    2489     void updateMidpointsForTrailingBoxes(LineMidpointState&, const InlineIterator& lBreak, CollapseFirstSpaceOrNot);
    2490 
    2491 private:
    2492     RenderText* m_whitespace;
    2493     Vector<RenderBoxModelObject*, 4> m_boxes;
    2494 };
    2495 
    2496 TrailingObjects::TrailingObjects()
    2497     : m_whitespace(0)
    2498 {
    2499 }
    2500 
    2501 inline void TrailingObjects::setTrailingWhitespace(RenderText* whitespace)
    2502 {
    2503     ASSERT(whitespace);
    2504     m_whitespace = whitespace;
    2505 }
    2506 
    2507 inline void TrailingObjects::clear()
    2508 {
    2509     m_whitespace = 0;
    2510     m_boxes.shrink(0); // Use shrink(0) instead of clear() to retain our capacity.
    2511 }
    2512 
    2513 inline void TrailingObjects::appendBoxIfNeeded(RenderBoxModelObject* box)
    2514 {
    2515     if (m_whitespace)
    2516         m_boxes.append(box);
    2517 }
    2518 
    2519 void TrailingObjects::updateMidpointsForTrailingBoxes(LineMidpointState& lineMidpointState, const InlineIterator& lBreak, CollapseFirstSpaceOrNot collapseFirstSpace)
    2520 {
    2521     if (!m_whitespace)
    2522         return;
    2523 
    2524     // This object is either going to be part of the last midpoint, or it is going to be the actual endpoint.
    2525     // In both cases we just decrease our pos by 1 level to exclude the space, allowing it to - in effect - collapse into the newline.
    2526     if (lineMidpointState.numMidpoints % 2) {
    2527         // Find the trailing space object's midpoint.
    2528         int trailingSpaceMidpoint = lineMidpointState.numMidpoints - 1;
    2529         for ( ; trailingSpaceMidpoint > 0 && lineMidpointState.midpoints[trailingSpaceMidpoint].m_obj != m_whitespace; --trailingSpaceMidpoint) { }
    2530         ASSERT(trailingSpaceMidpoint >= 0);
    2531         if (collapseFirstSpace == CollapseFirstSpace)
    2532             lineMidpointState.midpoints[trailingSpaceMidpoint].m_pos--;
    2533 
    2534         // Now make sure every single trailingPositionedBox following the trailingSpaceMidpoint properly stops and starts
    2535         // ignoring spaces.
    2536         size_t currentMidpoint = trailingSpaceMidpoint + 1;
    2537         for (size_t i = 0; i < m_boxes.size(); ++i) {
    2538             if (currentMidpoint >= lineMidpointState.numMidpoints) {
    2539                 // We don't have a midpoint for this box yet.
    2540                 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]);
    2541             } else {
    2542                 ASSERT(lineMidpointState.midpoints[currentMidpoint].m_obj == m_boxes[i]);
    2543                 ASSERT(lineMidpointState.midpoints[currentMidpoint + 1].m_obj == m_boxes[i]);
    2544             }
    2545             currentMidpoint += 2;
    2546         }
    2547     } else if (!lBreak.m_obj) {
    2548         ASSERT(m_whitespace->isText());
    2549         ASSERT(collapseFirstSpace == CollapseFirstSpace);
    2550         // Add a new end midpoint that stops right at the very end.
    2551         unsigned length = m_whitespace->textLength();
    2552         unsigned pos = length >= 2 ? length - 2 : UINT_MAX;
    2553         InlineIterator endMid(0, m_whitespace, pos);
    2554         startIgnoringSpaces(lineMidpointState, endMid);
    2555         for (size_t i = 0; i < m_boxes.size(); ++i) {
    2556             ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]);
    2557         }
    2558     }
    2559 }
    2560 
    2561 void LineBreaker::reset()
    2562 {
    2563     m_positionedObjects.clear();
    2564     m_hyphenated = false;
    2565     m_clear = CNONE;
    25662007}
    25672008
     
    26182059    return end;
    26192060#endif
    2620 }
    2621 
    2622 static inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator& iter, RenderCombineText& renderer)
    2623 {
    2624     return iter.m_obj == &renderer && iter.m_pos >= renderer.textLength();
    2625 }
    2626 
    2627 #if ENABLE(CSS_SHAPES)
    2628 static void updateSegmentsForShapes(RenderBlockFlow& block, const FloatingObject* lastFloatFromPreviousLine, const WordMeasurements& wordMeasurements, LineWidth& width, bool isFirstLine)
    2629 {
    2630     ASSERT(lastFloatFromPreviousLine);
    2631 
    2632     ShapeInsideInfo* shapeInsideInfo = block.layoutShapeInsideInfo();
    2633     if (!lastFloatFromPreviousLine->isPlaced() || !shapeInsideInfo)
    2634         return;
    2635 
    2636     bool isHorizontalWritingMode = block.isHorizontalWritingMode();
    2637     LayoutUnit logicalOffsetFromShapeContainer = block.logicalOffsetFromShapeAncestorContainer(shapeInsideInfo->owner()).height();
    2638 
    2639     LayoutUnit lineLogicalTop = block.logicalHeight() + logicalOffsetFromShapeContainer;
    2640     LayoutUnit lineLogicalHeight = block.lineHeight(isFirstLine, isHorizontalWritingMode ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
    2641     LayoutUnit lineLogicalBottom = lineLogicalTop + lineLogicalHeight;
    2642 
    2643     LayoutUnit floatLogicalTop = block.logicalTopForFloat(lastFloatFromPreviousLine);
    2644     LayoutUnit floatLogicalBottom = block.logicalBottomForFloat(lastFloatFromPreviousLine);
    2645 
    2646     bool lineOverlapsWithFloat = (floatLogicalTop < lineLogicalBottom) && (lineLogicalTop < floatLogicalBottom);
    2647     if (!lineOverlapsWithFloat)
    2648         return;
    2649 
    2650     float minSegmentWidth = firstPositiveWidth(wordMeasurements);
    2651 
    2652     LayoutUnit floatLogicalWidth = block.logicalWidthForFloat(lastFloatFromPreviousLine);
    2653     LayoutUnit availableLogicalWidth = block.logicalWidth() - block.logicalRightForFloat(lastFloatFromPreviousLine);
    2654     if (availableLogicalWidth < minSegmentWidth)
    2655         block.setLogicalHeight(floatLogicalBottom);
    2656 
    2657     if (block.logicalHeight() < floatLogicalTop) {
    2658         shapeInsideInfo->adjustLogicalLineTop(minSegmentWidth + floatLogicalWidth);
    2659         block.setLogicalHeight(shapeInsideInfo->logicalLineTop() - logicalOffsetFromShapeContainer);
    2660     }
    2661 
    2662     lineLogicalTop = block.logicalHeight() + logicalOffsetFromShapeContainer;
    2663 
    2664     shapeInsideInfo->updateSegmentsForLine(lineLogicalTop, lineLogicalHeight);
    2665     width.updateCurrentShapeSegment();
    2666     width.updateAvailableWidth();
    2667 }
    2668 #endif
    2669 
    2670 class BreakingContext {
    2671 public:
    2672     BreakingContext(LineBreaker& lineBreaker, InlineBidiResolver& resolver, LineInfo& inLineInfo, LineWidth& lineWidth, RenderTextInfo& inRenderTextInfo, FloatingObject* inLastFloatFromPreviousLine, bool appliedStartWidth, RenderBlockFlow& block)
    2673         : m_lineBreaker(lineBreaker)
    2674         , m_resolver(resolver)
    2675         , m_current(resolver.position())
    2676         , m_lineBreak(resolver.position())
    2677         , m_block(block)
    2678         , m_lastObject(m_current.m_obj)
    2679         , m_nextObject(0)
    2680         , m_currentStyle(0)
    2681         , m_blockStyle(block.style())
    2682         , m_lineInfo(inLineInfo)
    2683         , m_renderTextInfo(inRenderTextInfo)
    2684         , m_lastFloatFromPreviousLine(inLastFloatFromPreviousLine)
    2685         , m_width(lineWidth)
    2686         , m_currWS(NORMAL)
    2687         , m_lastWS(NORMAL)
    2688         , m_preservesNewline(false)
    2689         , m_atStart(true)
    2690         , m_ignoringSpaces(false)
    2691         , m_currentCharacterIsSpace(false)
    2692         , m_currentCharacterIsWS(false)
    2693         , m_appliedStartWidth(appliedStartWidth)
    2694         , m_includeEndWidth(true)
    2695         , m_autoWrap(false)
    2696         , m_autoWrapWasEverTrueOnLine(false)
    2697         , m_floatsFitOnLine(true)
    2698         , m_collapseWhiteSpace(false)
    2699         , m_startingNewParagraph(m_lineInfo.previousLineBrokeCleanly())
    2700         , m_allowImagesToBreak(!block.document().inQuirksMode() || !block.isTableCell() || !m_blockStyle.logicalWidth().isIntrinsicOrAuto())
    2701         , m_atEnd(false)
    2702         , m_hadUncommittedWidthBeforeCurrent(false)
    2703         , m_lineMidpointState(resolver.midpointState())
    2704     {
    2705         m_lineInfo.setPreviousLineBrokeCleanly(false);
    2706     }
    2707 
    2708     RenderObject* currentObject() { return m_current.m_obj; }
    2709     InlineIterator lineBreak() { return m_lineBreak; }
    2710     InlineIterator& lineBreakRef() {return m_lineBreak; }
    2711     LineWidth& lineWidth() { return m_width; }
    2712     bool atEnd() { return m_atEnd; }
    2713 
    2714     void initializeForCurrentObject();
    2715 
    2716     void increment();
    2717 
    2718     void handleBR(EClear&);
    2719     void handleOutOfFlowPositioned(Vector<RenderBox*>& positionedObjects);
    2720     void handleFloat();
    2721     void handleEmptyInline();
    2722     void handleReplaced();
    2723     bool handleText(WordMeasurements&, bool& hyphenated, unsigned& consecutiveHyphenatedLines);
    2724     bool canBreakAtThisPosition();
    2725     void commitAndUpdateLineBreakIfNeeded();
    2726     InlineIterator handleEndOfLine();
    2727 
    2728     void clearLineBreakIfFitsOnLine(bool ignoringTrailingSpace = false)
    2729     {
    2730         if (m_width.fitsOnLine(ignoringTrailingSpace) || m_lastWS == NOWRAP)
    2731             m_lineBreak.clear();
    2732     }
    2733 
    2734     void commitLineBreakAtCurrentWidth(RenderObject* object, unsigned offset = 0, int nextBreak = -1)
    2735     {
    2736         m_width.commit();
    2737         m_lineBreak.moveTo(object, offset, nextBreak);
    2738     }
    2739 
    2740 private:
    2741     LineBreaker& m_lineBreaker;
    2742     InlineBidiResolver& m_resolver;
    2743 
    2744     InlineIterator m_current;
    2745     InlineIterator m_lineBreak;
    2746     InlineIterator m_startOfIgnoredSpaces;
    2747 
    2748     RenderBlockFlow& m_block;
    2749     RenderObject* m_lastObject;
    2750     RenderObject* m_nextObject;
    2751 
    2752     RenderStyle* m_currentStyle;
    2753 
    2754     // Firefox and Opera will allow a table cell to grow to fit an image inside it under
    2755     // very specific circumstances (in order to match common WinIE renderings).
    2756     // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
    2757     RenderStyle& m_blockStyle;
    2758 
    2759     LineInfo& m_lineInfo;
    2760 
    2761     RenderTextInfo& m_renderTextInfo;
    2762 
    2763     FloatingObject* m_lastFloatFromPreviousLine;
    2764 
    2765     LineWidth m_width;
    2766 
    2767     EWhiteSpace m_currWS;
    2768     EWhiteSpace m_lastWS;
    2769 
    2770     bool m_preservesNewline;
    2771     bool m_atStart;
    2772 
    2773     // This variable is used only if whitespace isn't set to PRE, and it tells us whether
    2774     // or not we are currently ignoring whitespace.
    2775     bool m_ignoringSpaces;
    2776 
    2777     // This variable tracks whether the very last character we saw was a space.  We use
    2778     // this to detect when we encounter a second space so we know we have to terminate
    2779     // a run.
    2780     bool m_currentCharacterIsSpace;
    2781     bool m_currentCharacterIsWS;
    2782     bool m_appliedStartWidth;
    2783     bool m_includeEndWidth;
    2784     bool m_autoWrap;
    2785     bool m_autoWrapWasEverTrueOnLine;
    2786     bool m_floatsFitOnLine;
    2787     bool m_collapseWhiteSpace;
    2788     bool m_startingNewParagraph;
    2789     bool m_allowImagesToBreak;
    2790     bool m_atEnd;
    2791     bool m_hadUncommittedWidthBeforeCurrent;
    2792 
    2793     LineMidpointState& m_lineMidpointState;
    2794 
    2795     TrailingObjects m_trailingObjects;
    2796 };
    2797 
    2798 inline void BreakingContext::initializeForCurrentObject()
    2799 {
    2800     m_hadUncommittedWidthBeforeCurrent = !!m_width.uncommittedWidth();
    2801 
    2802     m_currentStyle = &m_current.m_obj->style();
    2803 
    2804     ASSERT(m_currentStyle);
    2805 
    2806     m_nextObject = bidiNextSkippingEmptyInlines(m_block, m_current.m_obj);
    2807     if (m_nextObject && m_nextObject->parent() && !m_nextObject->parent()->isDescendantOf(m_current.m_obj->parent()))
    2808         m_includeEndWidth = true;
    2809 
    2810     m_currWS = m_current.m_obj->isReplaced() ? m_current.m_obj->parent()->style().whiteSpace() : m_currentStyle->whiteSpace();
    2811     m_lastWS = m_lastObject->isReplaced() ? m_lastObject->parent()->style().whiteSpace() : m_lastObject->style().whiteSpace();
    2812 
    2813     m_autoWrap = RenderStyle::autoWrap(m_currWS);
    2814     m_autoWrapWasEverTrueOnLine = m_autoWrapWasEverTrueOnLine || m_autoWrap;
    2815 
    2816 #if ENABLE(SVG)
    2817     m_preservesNewline = m_current.m_obj->isSVGInlineText() ? false : RenderStyle::preserveNewline(m_currWS);
    2818 #else
    2819     m_preservesNewline = RenderStyle::preserveNewline(m_currWS);
    2820 #endif
    2821 
    2822     m_collapseWhiteSpace = RenderStyle::collapseWhiteSpace(m_currWS);
    2823 }
    2824 
    2825 inline void BreakingContext::increment()
    2826 {
    2827     // Clear out our character space bool, since inline <pre>s don't collapse whitespace
    2828     // with adjacent inline normal/nowrap spans.
    2829     if (!m_collapseWhiteSpace)
    2830         m_currentCharacterIsSpace = false;
    2831 
    2832     m_current.moveToStartOf(m_nextObject);
    2833     m_atStart = false;
    2834 }
    2835 
    2836 inline void BreakingContext::handleBR(EClear& clear)
    2837 {
    2838     if (m_width.fitsOnLine()) {
    2839         RenderObject* br = m_current.m_obj;
    2840         m_lineBreak.moveToStartOf(br);
    2841         m_lineBreak.increment();
    2842 
    2843         // A <br> always breaks a line, so don't let the line be collapsed
    2844         // away. Also, the space at the end of a line with a <br> does not
    2845         // get collapsed away. It only does this if the previous line broke
    2846         // cleanly. Otherwise the <br> has no effect on whether the line is
    2847         // empty or not.
    2848         if (m_startingNewParagraph)
    2849             m_lineInfo.setEmpty(false, &m_block, &m_width);
    2850         m_trailingObjects.clear();
    2851         m_lineInfo.setPreviousLineBrokeCleanly(true);
    2852 
    2853         // A <br> with clearance always needs a linebox in case the lines below it get dirtied later and
    2854         // need to check for floats to clear - so if we're ignoring spaces, stop ignoring them and add a
    2855         // run for this object.
    2856         if (m_ignoringSpaces && m_currentStyle->clear() != CNONE)
    2857             ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, br);
    2858         // If we were preceded by collapsing space and are in a right-aligned container we need to ensure the space gets
    2859         // collapsed away so that it doesn't push the text out from the container's right-hand edge.
    2860         // FIXME: Do this regardless of the container's alignment - will require rebaselining a lot of test results.
    2861         else if (m_ignoringSpaces && (m_blockStyle.textAlign() == RIGHT || m_blockStyle.textAlign() == WEBKIT_RIGHT))
    2862             stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.m_obj, m_current.m_pos));
    2863 
    2864         if (!m_lineInfo.isEmpty())
    2865             clear = m_currentStyle->clear();
    2866     }
    2867     m_atEnd = true;
    2868 }
    2869 
    2870 inline void BreakingContext::handleOutOfFlowPositioned(Vector<RenderBox*>& positionedObjects)
    2871 {
    2872     // If our original display wasn't an inline type, then we can
    2873     // go ahead and determine our static inline position now.
    2874     RenderBox* box = toRenderBox(m_current.m_obj);
    2875     bool isInlineType = box->style().isOriginalDisplayInlineType();
    2876     if (!isInlineType)
    2877         m_block.setStaticInlinePositionForChild(*box, m_block.logicalHeight(), m_block.startOffsetForContent(m_block.logicalHeight()));
    2878     else {
    2879         // If our original display was an INLINE type, then we can go ahead
    2880         // and determine our static y position now.
    2881         box->layer()->setStaticBlockPosition(m_block.logicalHeight());
    2882     }
    2883 
    2884     // If we're ignoring spaces, we have to stop and include this object and
    2885     // then start ignoring spaces again.
    2886     if (isInlineType || box->container()->isRenderInline()) {
    2887         if (m_ignoringSpaces)
    2888             ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, box);
    2889         m_trailingObjects.appendBoxIfNeeded(box);
    2890     } else
    2891         positionedObjects.append(box);
    2892 
    2893     m_width.addUncommittedWidth(inlineLogicalWidth(box));
    2894     // Reset prior line break context characters.
    2895     m_renderTextInfo.m_lineBreakIterator.resetPriorContext();
    2896 }
    2897 
    2898 inline void BreakingContext::handleFloat()
    2899 {
    2900     RenderBox& floatBox = toRenderBox(*m_current.m_obj);
    2901     FloatingObject* floatingObject = m_block.insertFloatingObject(floatBox);
    2902     // check if it fits in the current line.
    2903     // If it does, position it now, otherwise, position
    2904     // it after moving to next line (in newLine() func)
    2905     // FIXME: Bug 110372: Properly position multiple stacked floats with non-rectangular shape outside.
    2906     if (m_floatsFitOnLine && m_width.fitsOnLineExcludingTrailingWhitespace(m_block.logicalWidthForFloat(floatingObject))) {
    2907         m_block.positionNewFloatOnLine(floatingObject, m_lastFloatFromPreviousLine, m_lineInfo, m_width);
    2908         if (m_lineBreak.m_obj == m_current.m_obj) {
    2909             ASSERT(!m_lineBreak.m_pos);
    2910             m_lineBreak.increment();
    2911         }
    2912     } else
    2913         m_floatsFitOnLine = false;
    2914     // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for floating element.
    2915     m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
    2916 }
    2917 
    2918 inline void BreakingContext::handleEmptyInline()
    2919 {
    2920     RenderInline& flowBox = toRenderInline(*m_current.m_obj);
    2921 
    2922     // This should only end up being called on empty inlines
    2923     ASSERT(isEmptyInline(flowBox));
    2924 
    2925     // Now that some inline flows have line boxes, if we are already ignoring spaces, we need
    2926     // to make sure that we stop to include this object and then start ignoring spaces again.
    2927     // If this object is at the start of the line, we need to behave like list markers and
    2928     // start ignoring spaces.
    2929     bool requiresLineBox = alwaysRequiresLineBox(flowBox);
    2930     if (requiresLineBox || requiresLineBoxForContent(flowBox, m_lineInfo)) {
    2931         // An empty inline that only has line-height, vertical-align or font-metrics will only get a
    2932         // line box to affect the height of the line if the rest of the line is not empty.
    2933         if (requiresLineBox)
    2934             m_lineInfo.setEmpty(false, &m_block, &m_width);
    2935         if (m_ignoringSpaces) {
    2936             m_trailingObjects.clear();
    2937             ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, m_current.m_obj);
    2938         } else if (m_blockStyle.collapseWhiteSpace() && m_resolver.position().m_obj == m_current.m_obj
    2939             && shouldSkipWhitespaceAfterStartObject(m_block, m_current.m_obj, m_lineMidpointState)) {
    2940             // Like with list markers, we start ignoring spaces to make sure that any
    2941             // additional spaces we see will be discarded.
    2942             m_currentCharacterIsSpace = true;
    2943             m_currentCharacterIsWS = true;
    2944             m_ignoringSpaces = true;
    2945         } else
    2946             m_trailingObjects.appendBoxIfNeeded(&flowBox);
    2947     }
    2948 
    2949     m_width.addUncommittedWidth(inlineLogicalWidth(m_current.m_obj) + borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox));
    2950 }
    2951 
    2952 inline void BreakingContext::handleReplaced()
    2953 {
    2954     RenderBox& replacedBox = toRenderBox(*m_current.m_obj);
    2955 
    2956     if (m_atStart)
    2957         m_width.updateAvailableWidth(replacedBox.logicalHeight());
    2958 
    2959     // Break on replaced elements if either has normal white-space.
    2960     if ((m_autoWrap || RenderStyle::autoWrap(m_lastWS)) && (!m_current.m_obj->isImage() || m_allowImagesToBreak)) {
    2961         m_width.commit();
    2962         m_lineBreak.moveToStartOf(m_current.m_obj);
    2963     }
    2964 
    2965     if (m_ignoringSpaces)
    2966         stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.m_obj, 0));
    2967 
    2968     m_lineInfo.setEmpty(false, &m_block, &m_width);
    2969     m_ignoringSpaces = false;
    2970     m_currentCharacterIsSpace = false;
    2971     m_currentCharacterIsWS = false;
    2972     m_trailingObjects.clear();
    2973 
    2974     // Optimize for a common case. If we can't find whitespace after the list
    2975     // item, then this is all moot.
    2976     LayoutUnit replacedLogicalWidth = m_block.logicalWidthForChild(replacedBox) + m_block.marginStartForChild(replacedBox) + m_block.marginEndForChild(replacedBox) + inlineLogicalWidth(m_current.m_obj);
    2977     if (m_current.m_obj->isListMarker()) {
    2978         if (m_blockStyle.collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(m_block, m_current.m_obj, m_lineMidpointState)) {
    2979             // Like with inline flows, we start ignoring spaces to make sure that any
    2980             // additional spaces we see will be discarded.
    2981             m_currentCharacterIsSpace = true;
    2982             m_currentCharacterIsWS = false;
    2983             m_ignoringSpaces = true;
    2984         }
    2985         if (toRenderListMarker(*m_current.m_obj).isInside())
    2986             m_width.addUncommittedWidth(replacedLogicalWidth);
    2987     } else
    2988         m_width.addUncommittedWidth(replacedLogicalWidth);
    2989     if (m_current.m_obj->isRubyRun())
    2990         m_width.applyOverhang(toRenderRubyRun(m_current.m_obj), m_lastObject, m_nextObject);
    2991     // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for replaced element.
    2992     m_renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
    2993 }
    2994 
    2995 
    2996 static inline void nextCharacter(UChar& currentCharacter, UChar& lastCharacter, UChar& secondToLastCharacter)
    2997 {
    2998     secondToLastCharacter = lastCharacter;
    2999     lastCharacter = currentCharacter;
    3000 }
    3001 
    3002 inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool& hyphenated,  unsigned& consecutiveHyphenatedLines)
    3003 {
    3004     if (!m_current.m_pos)
    3005         m_appliedStartWidth = false;
    3006 
    3007     RenderText* renderText = toRenderText(m_current.m_obj);
    3008 
    3009 #if ENABLE(SVG)
    3010     bool isSVGText = renderText->isSVGInlineText();
    3011 #endif
    3012 
    3013     // If we have left a no-wrap inline and entered an autowrap inline while ignoring spaces
    3014     // then we need to mark the start of the autowrap inline as a potential linebreak now.
    3015     if (m_autoWrap && !RenderStyle::autoWrap(m_lastWS) && m_ignoringSpaces)
    3016         commitLineBreakAtCurrentWidth(m_current.m_obj);
    3017 
    3018     if (renderText->style().hasTextCombine() && m_current.m_obj->isCombineText() && !toRenderCombineText(*m_current.m_obj).isCombined()) {
    3019         RenderCombineText& combineRenderer = toRenderCombineText(*m_current.m_obj);
    3020         combineRenderer.combineText();
    3021         // The length of the renderer's text may have changed. Increment stale iterator positions
    3022         if (iteratorIsBeyondEndOfRenderCombineText(m_lineBreak, combineRenderer)) {
    3023             ASSERT(iteratorIsBeyondEndOfRenderCombineText(m_resolver.position(), combineRenderer));
    3024             m_lineBreak.increment();
    3025             m_resolver.increment();
    3026         }
    3027     }
    3028 
    3029     const RenderStyle& style = lineStyle(*renderText->parent(), m_lineInfo);
    3030     const Font& font = style.font();
    3031     bool isFixedPitch = font.isFixedPitch();
    3032     bool canHyphenate = style.hyphens() == HyphensAuto && WebCore::canHyphenate(style.locale());
    3033 
    3034     unsigned lastSpace = m_current.m_pos;
    3035     float wordSpacing = m_currentStyle->wordSpacing();
    3036     float lastSpaceWordSpacing = 0;
    3037     float wordSpacingForWordMeasurement = 0;
    3038 
    3039     float wrapW = m_width.uncommittedWidth() + inlineLogicalWidth(m_current.m_obj, !m_appliedStartWidth, true);
    3040     float charWidth = 0;
    3041     bool breakNBSP = m_autoWrap && m_currentStyle->nbspMode() == SPACE;
    3042     // Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word,
    3043     // which is only possible if the word is the first thing on the line, that is, if |w| is zero.
    3044     bool breakWords = m_currentStyle->breakWords() && ((m_autoWrap && !m_width.committedWidth()) || m_currWS == PRE);
    3045     bool midWordBreak = false;
    3046     bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap;
    3047     float hyphenWidth = 0;
    3048 #if ENABLE(SVG)
    3049     if (isSVGText) {
    3050         breakWords = false;
    3051         breakAll = false;
    3052     }
    3053 #endif
    3054 
    3055     if (m_renderTextInfo.m_text != renderText) {
    3056         updateCounterIfNeeded(*renderText);
    3057         m_renderTextInfo.m_text = renderText;
    3058         m_renderTextInfo.m_font = &font;
    3059         m_renderTextInfo.m_layout = font.createLayout(renderText, m_width.currentWidth(), m_collapseWhiteSpace);
    3060         m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText->text(), style.locale());
    3061     } else if (m_renderTextInfo.m_layout && m_renderTextInfo.m_font != &font) {
    3062         m_renderTextInfo.m_font = &font;
    3063         m_renderTextInfo.m_layout = font.createLayout(renderText, m_width.currentWidth(), m_collapseWhiteSpace);
    3064     }
    3065 
    3066     TextLayout* textLayout = m_renderTextInfo.m_layout.get();
    3067 
    3068     // Non-zero only when kerning is enabled and TextLayout isn't used, in which case we measure
    3069     // words with their trailing space, then subtract its width.
    3070     HashSet<const SimpleFontData*> fallbackFonts;
    3071     float wordTrailingSpaceWidth = (font.typesettingFeatures() & Kerning) && !textLayout ? font.width(RenderBlock::constructTextRun(renderText, font, &space, 1, style), &fallbackFonts) + wordSpacing : 0;
    3072 
    3073     UChar lastCharacter = m_renderTextInfo.m_lineBreakIterator.lastCharacter();
    3074     UChar secondToLastCharacter = m_renderTextInfo.m_lineBreakIterator.secondToLastCharacter();
    3075     for (; m_current.m_pos < renderText->textLength(); m_current.fastIncrementInTextNode()) {
    3076         bool previousCharacterIsSpace = m_currentCharacterIsSpace;
    3077         bool previousCharacterIsWS = m_currentCharacterIsWS;
    3078         UChar c = m_current.current();
    3079         m_currentCharacterIsSpace = c == ' ' || c == '\t' || (!m_preservesNewline && (c == '\n'));
    3080 
    3081         if (!m_collapseWhiteSpace || !m_currentCharacterIsSpace)
    3082             m_lineInfo.setEmpty(false, &m_block, &m_width);
    3083 
    3084         if (c == softHyphen && m_autoWrap && !hyphenWidth && style.hyphens() != HyphensNone) {
    3085             hyphenWidth = measureHyphenWidth(renderText, font, &fallbackFonts);
    3086             m_width.addUncommittedWidth(hyphenWidth);
    3087         }
    3088 
    3089         bool applyWordSpacing = false;
    3090 
    3091         m_currentCharacterIsWS = m_currentCharacterIsSpace || (breakNBSP && c == noBreakSpace);
    3092 
    3093         if ((breakAll || breakWords) && !midWordBreak && (!m_currentCharacterIsSpace || style.whiteSpace() != PRE_WRAP)) {
    3094             wrapW += charWidth;
    3095             bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current.m_pos + 1 < renderText->textLength() && U16_IS_TRAIL((*renderText)[m_current.m_pos + 1]);
    3096             charWidth = textWidth(renderText, m_current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + wrapW, isFixedPitch, m_collapseWhiteSpace, fallbackFonts, textLayout);
    3097             midWordBreak = m_width.committedWidth() + wrapW + charWidth > m_width.availableWidth();
    3098         }
    3099 
    3100         bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.m_pos, m_current.m_nextBreakablePosition, breakNBSP)
    3101             && (style.hyphens() != HyphensNone || (m_current.previousInSameNode() != softHyphen)));
    3102 
    3103         if (betweenWords || midWordBreak) {
    3104             bool stoppedIgnoringSpaces = false;
    3105             if (m_ignoringSpaces) {
    3106                 lastSpaceWordSpacing = 0;
    3107                 if (!m_currentCharacterIsSpace) {
    3108                     // Stop ignoring spaces and begin at this
    3109                     // new point.
    3110                     m_ignoringSpaces = false;
    3111                     wordSpacingForWordMeasurement = 0;
    3112                     lastSpace = m_current.m_pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
    3113                     stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.m_obj, m_current.m_pos));
    3114                     stoppedIgnoringSpaces = true;
    3115                 } else {
    3116                     // Just keep ignoring these spaces.
    3117                     nextCharacter(c, lastCharacter, secondToLastCharacter);
    3118                     continue;
    3119                 }
    3120             }
    3121 
    3122             wordMeasurements.grow(wordMeasurements.size() + 1);
    3123             WordMeasurement& wordMeasurement = wordMeasurements.last();
    3124 
    3125             wordMeasurement.renderer = renderText;
    3126             wordMeasurement.endOffset = m_current.m_pos;
    3127             wordMeasurement.startOffset = lastSpace;
    3128 
    3129             float additionalTempWidth;
    3130             if (wordTrailingSpaceWidth && c == ' ')
    3131                 additionalTempWidth = textWidth(renderText, lastSpace, m_current.m_pos + 1 - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth;
    3132             else
    3133                 additionalTempWidth = textWidth(renderText, lastSpace, m_current.m_pos - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout);
    3134 
    3135             if (wordMeasurement.fallbackFonts.isEmpty() && !fallbackFonts.isEmpty())
    3136                 wordMeasurement.fallbackFonts.swap(fallbackFonts);
    3137             fallbackFonts.clear();
    3138 
    3139             wordMeasurement.width = additionalTempWidth + wordSpacingForWordMeasurement;
    3140             additionalTempWidth += lastSpaceWordSpacing;
    3141             m_width.addUncommittedWidth(additionalTempWidth);
    3142 
    3143             if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharacterIsSpace && additionalTempWidth)
    3144                 m_width.setTrailingWhitespaceWidth(additionalTempWidth);
    3145 
    3146             if (!m_appliedStartWidth) {
    3147                 m_width.addUncommittedWidth(inlineLogicalWidth(m_current.m_obj, true, false));
    3148                 m_appliedStartWidth = true;
    3149             }
    3150 
    3151 #if ENABLE(CSS_SHAPES)
    3152             if (m_lastFloatFromPreviousLine)
    3153                 updateSegmentsForShapes(m_block, m_lastFloatFromPreviousLine, wordMeasurements, m_width, m_lineInfo.isFirstLine());
    3154 #endif
    3155             applyWordSpacing = wordSpacing && m_currentCharacterIsSpace;
    3156 
    3157             if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine())
    3158                 m_width.fitBelowFloats();
    3159 
    3160             if (m_autoWrap || breakWords) {
    3161                 // If we break only after white-space, consider the current character
    3162                 // as candidate width for this line.
    3163                 bool lineWasTooWide = false;
    3164                 if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
    3165                     float charWidth = textWidth(renderText, m_current.m_pos, 1, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0);
    3166                     // Check if line is too big even without the extra space
    3167                     // at the end of the line. If it is not, do nothing.
    3168                     // If the line needs the extra whitespace to be too long,
    3169                     // then move the line break to the space and skip all
    3170                     // additional whitespace.
    3171                     if (!m_width.fitsOnLineIncludingExtraWidth(charWidth)) {
    3172                         lineWasTooWide = true;
    3173                         m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m_nextBreakablePosition);
    3174                         m_lineBreaker.skipTrailingWhitespace(m_lineBreak, m_lineInfo);
    3175                     }
    3176                 }
    3177                 if (lineWasTooWide || !m_width.fitsOnLine()) {
    3178                     if (canHyphenate && !m_width.fitsOnLine()) {
    3179                         tryHyphenating(renderText, font, style.locale(), consecutiveHyphenatedLines, m_blockStyle.hyphenationLimitLines(), style.hyphenationLimitBefore(), style.hyphenationLimitAfter(), lastSpace, m_current.m_pos, m_width.currentWidth() - additionalTempWidth, m_width.availableWidth(), isFixedPitch, m_collapseWhiteSpace, lastSpaceWordSpacing, m_lineBreak, m_current.m_nextBreakablePosition, m_lineBreaker.m_hyphenated);
    3180                         if (m_lineBreaker.m_hyphenated) {
    3181                             m_atEnd = true;
    3182                             return false;
    3183                         }
    3184                     }
    3185                     if (m_lineBreak.atTextParagraphSeparator()) {
    3186                         if (!stoppedIgnoringSpaces && m_current.m_pos > 0)
    3187                             ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
    3188                         m_lineBreak.increment();
    3189                         m_lineInfo.setPreviousLineBrokeCleanly(true);
    3190                         wordMeasurement.endOffset = m_lineBreak.m_pos;
    3191                     }
    3192                     if (m_lineBreak.m_obj && m_lineBreak.m_pos && m_lineBreak.m_obj->isText() && toRenderText(m_lineBreak.m_obj)->textLength() && toRenderText(m_lineBreak.m_obj)->characterAt(m_lineBreak.m_pos - 1) == softHyphen && style.hyphens() != HyphensNone)
    3193                         hyphenated = true;
    3194                     if (m_lineBreak.m_pos && m_lineBreak.m_pos != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
    3195                         if (charWidth) {
    3196                             wordMeasurement.endOffset = m_lineBreak.m_pos;
    3197                             wordMeasurement.width = charWidth;
    3198                         }
    3199                     }
    3200                     // Didn't fit. Jump to the end unless there's still an opportunity to collapse whitespace.
    3201                     if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSpace || !previousCharacterIsSpace) {
    3202                         m_atEnd = true;
    3203                         return false;
    3204                     }
    3205                 } else {
    3206                     if (!betweenWords || (midWordBreak && !m_autoWrap))
    3207                         m_width.addUncommittedWidth(-additionalTempWidth);
    3208                     if (hyphenWidth) {
    3209                         // Subtract the width of the soft hyphen out since we fit on a line.
    3210                         m_width.addUncommittedWidth(-hyphenWidth);
    3211                         hyphenWidth = 0;
    3212                     }
    3213                 }
    3214             }
    3215 
    3216             if (c == '\n' && m_preservesNewline) {
    3217                 if (!stoppedIgnoringSpaces && m_current.m_pos > 0)
    3218                     ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
    3219                 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m_nextBreakablePosition);
    3220                 m_lineBreak.increment();
    3221                 m_lineInfo.setPreviousLineBrokeCleanly(true);
    3222                 return true;
    3223             }
    3224 
    3225             if (m_autoWrap && betweenWords) {
    3226                 m_width.commit();
    3227                 wrapW = 0;
    3228                 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m_nextBreakablePosition);
    3229                 // Auto-wrapping text should not wrap in the middle of a word once it has had an
    3230                 // opportunity to break after a word.
    3231                 breakWords = false;
    3232             }
    3233 
    3234             if (midWordBreak && !U16_IS_TRAIL(c) && !(U_GET_GC_MASK(c) & U_GC_M_MASK)) {
    3235                 // Remember this as a breakable position in case
    3236                 // adding the end width forces a break.
    3237                 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m_nextBreakablePosition);
    3238                 midWordBreak &= (breakWords || breakAll);
    3239             }
    3240 
    3241             if (betweenWords) {
    3242                 lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
    3243                 wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0;
    3244                 lastSpace = m_current.m_pos;
    3245             }
    3246 
    3247             if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) {
    3248                 // If we encounter a newline, or if we encounter a
    3249                 // second space, we need to go ahead and break up this
    3250                 // run and enter a mode where we start collapsing spaces.
    3251                 if (m_currentCharacterIsSpace && previousCharacterIsSpace) {
    3252                     m_ignoringSpaces = true;
    3253 
    3254                     // We just entered a mode where we are ignoring
    3255                     // spaces. Create a midpoint to terminate the run
    3256                     // before the second space.
    3257                     startIgnoringSpaces(m_lineMidpointState, m_startOfIgnoredSpaces);
    3258                     m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace);
    3259                 }
    3260             }
    3261         } else if (m_ignoringSpaces) {
    3262             // Stop ignoring spaces and begin at this
    3263             // new point.
    3264             m_ignoringSpaces = false;
    3265             lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
    3266             wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing : 0;
    3267             lastSpace = m_current.m_pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
    3268             stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.m_obj, m_current.m_pos));
    3269         }
    3270 #if ENABLE(SVG)
    3271         if (isSVGText && m_current.m_pos > 0) {
    3272             // Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
    3273             if (toRenderSVGInlineText(renderText)->characterStartsNewTextChunk(m_current.m_pos))
    3274                 ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
    3275         }
    3276 #endif
    3277 
    3278         if (m_currentCharacterIsSpace && !previousCharacterIsSpace) {
    3279             m_startOfIgnoredSpaces.m_obj = m_current.m_obj;
    3280             m_startOfIgnoredSpaces.m_pos = m_current.m_pos;
    3281             // Spaces after right-aligned text and before a line-break get collapsed away completely so that the trailing
    3282             // space doesn't seem to push the text out from the right-hand edge.
    3283             // FIXME: Do this regardless of the container's alignment - will require rebaselining a lot of test results.
    3284             if (m_nextObject && m_nextObject->isBR() && (m_blockStyle.textAlign() == RIGHT || m_blockStyle.textAlign() == WEBKIT_RIGHT)) {
    3285                 m_startOfIgnoredSpaces.m_pos--;
    3286                 // If there's just a single trailing space start ignoring it now so it collapses away.
    3287                 if (m_current.m_pos == renderText->textLength() - 1)
    3288                     startIgnoringSpaces(m_lineMidpointState, m_startOfIgnoredSpaces);
    3289             }
    3290         }
    3291 
    3292         if (!m_currentCharacterIsSpace && previousCharacterIsWS) {
    3293             if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace())
    3294                 m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos, m_current.m_nextBreakablePosition);
    3295         }
    3296 
    3297         if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces)
    3298             m_trailingObjects.setTrailingWhitespace(toRenderText(m_current.m_obj));
    3299         else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace)
    3300             m_trailingObjects.clear();
    3301 
    3302         m_atStart = false;
    3303         nextCharacter(c, lastCharacter, secondToLastCharacter);
    3304     }
    3305 
    3306     m_renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondToLastCharacter);
    3307 
    3308     wordMeasurements.grow(wordMeasurements.size() + 1);
    3309     WordMeasurement& wordMeasurement = wordMeasurements.last();
    3310     wordMeasurement.renderer = renderText;
    3311 
    3312     // IMPORTANT: current.m_pos is > length here!
    3313     float additionalTempWidth = m_ignoringSpaces ? 0 : textWidth(renderText, lastSpace, m_current.m_pos - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout);
    3314     wordMeasurement.startOffset = lastSpace;
    3315     wordMeasurement.endOffset = m_current.m_pos;
    3316     wordMeasurement.width = m_ignoringSpaces ? 0 : additionalTempWidth + wordSpacingForWordMeasurement;
    3317     additionalTempWidth += lastSpaceWordSpacing;
    3318 
    3319     float inlineLogicalTempWidth = inlineLogicalWidth(m_current.m_obj, !m_appliedStartWidth, m_includeEndWidth);
    3320     m_width.addUncommittedWidth(additionalTempWidth + inlineLogicalTempWidth);
    3321 
    3322     if (wordMeasurement.fallbackFonts.isEmpty() && !fallbackFonts.isEmpty())
    3323         wordMeasurement.fallbackFonts.swap(fallbackFonts);
    3324     fallbackFonts.clear();
    3325 
    3326     if (m_collapseWhiteSpace && m_currentCharacterIsSpace && additionalTempWidth)
    3327         m_width.setTrailingWhitespaceWidth(additionalTempWidth, inlineLogicalTempWidth);
    3328 
    3329     m_includeEndWidth = false;
    3330 
    3331     if (!m_width.fitsOnLine()) {
    3332         if (canHyphenate)
    3333             tryHyphenating(renderText, font, style.locale(), consecutiveHyphenatedLines, m_blockStyle.hyphenationLimitLines(), style.hyphenationLimitBefore(), style.hyphenationLimitAfter(), lastSpace, m_current.m_pos, m_width.currentWidth() - additionalTempWidth, m_width.availableWidth(), isFixedPitch, m_collapseWhiteSpace, lastSpaceWordSpacing, m_lineBreak, m_current.m_nextBreakablePosition, m_lineBreaker.m_hyphenated);
    3334 
    3335         if (!hyphenated && m_lineBreak.previousInSameNode() == softHyphen && style.hyphens() != HyphensNone) {
    3336             hyphenated = true;
    3337             m_atEnd = true;
    3338         }
    3339     }
    3340     return false;
    3341 }
    3342 
    3343 static bool textBeginsWithBreakablePosition(RenderObject* next)
    3344 {
    3345     ASSERT(next->isText());
    3346     RenderText* nextText = toRenderText(next);
    3347     if (!nextText->textLength())
    3348         return false;
    3349     UChar c = nextText->characterAt(0);
    3350     return c == ' ' || c == '\t' || (c == '\n' && !nextText->preservesNewline());
    3351 }
    3352 
    3353 inline bool BreakingContext::canBreakAtThisPosition()
    3354 {
    3355     // If we are no-wrap and have found a line-breaking opportunity already then we should take it.
    3356     if (m_width.committedWidth() && !m_width.fitsOnLine(m_currentCharacterIsSpace) && m_currWS == NOWRAP)
    3357         return true;
    3358 
    3359     // Avoid breaking before empty inlines.
    3360     if (m_nextObject && m_nextObject->isRenderInline() && isEmptyInline(toRenderInline(*m_nextObject)))
    3361         return false;
    3362 
    3363     // Return early if we autowrap and the current character is a space as we will always want to break at such a position.
    3364     if (m_autoWrap && m_currentCharacterIsSpace)
    3365         return true;
    3366 
    3367     if (m_nextObject && m_nextObject->isLineBreakOpportunity())
    3368         return m_autoWrap;
    3369 
    3370     bool nextIsAutoWrappingText = (m_nextObject && m_nextObject->isText() && (m_autoWrap || m_nextObject->style().autoWrap()));
    3371     if (!nextIsAutoWrappingText)
    3372         return m_autoWrap;
    3373     bool currentIsTextOrEmptyInline = m_current.m_obj->isText() || (m_current.m_obj->isRenderInline() && isEmptyInline(toRenderInline(*m_current.m_obj)));
    3374     if (!currentIsTextOrEmptyInline)
    3375         return m_autoWrap;
    3376 
    3377     bool canBreakHere = !m_currentCharacterIsSpace && textBeginsWithBreakablePosition(m_nextObject);
    3378 
    3379     // See if attempting to fit below floats creates more available width on the line.
    3380     if (!m_width.fitsOnLine() && !m_width.committedWidth())
    3381         m_width.fitBelowFloats();
    3382 
    3383     bool canPlaceOnLine = m_width.fitsOnLine() || !m_autoWrapWasEverTrueOnLine;
    3384 
    3385     if (canPlaceOnLine && canBreakHere)
    3386         commitLineBreakAtCurrentWidth(m_nextObject);
    3387 
    3388     return canBreakHere;
    3389 }
    3390 
    3391 inline void BreakingContext::commitAndUpdateLineBreakIfNeeded()
    3392 {
    3393     bool checkForBreak = canBreakAtThisPosition();
    3394 
    3395     if (checkForBreak && !m_width.fitsOnLine(m_ignoringSpaces)) {
    3396         // if we have floats, try to get below them.
    3397         if (m_currentCharacterIsSpace && !m_ignoringSpaces && m_currentStyle->collapseWhiteSpace())
    3398             m_trailingObjects.clear();
    3399 
    3400         if (m_width.committedWidth()) {
    3401             m_atEnd = true;
    3402             return;
    3403         }
    3404 
    3405         m_width.fitBelowFloats();
    3406 
    3407         // |width| may have been adjusted because we got shoved down past a float (thus
    3408         // giving us more room), so we need to retest, and only jump to
    3409         // the end label if we still don't fit on the line. -dwh
    3410         if (!m_width.fitsOnLine(m_ignoringSpaces)) {
    3411             m_atEnd = true;
    3412             return;
    3413         }
    3414     } else if (m_blockStyle.autoWrap() && !m_width.fitsOnLine() && !m_width.committedWidth()) {
    3415         // If the container autowraps but the current child does not then we still need to ensure that it
    3416         // wraps and moves below any floats.
    3417         m_width.fitBelowFloats();
    3418     }
    3419 
    3420     if (!m_current.m_obj->isFloatingOrOutOfFlowPositioned()) {
    3421         m_lastObject = m_current.m_obj;
    3422         if (m_lastObject->isReplaced() && m_autoWrap && (!m_lastObject->isImage() || m_allowImagesToBreak) && (!m_lastObject->isListMarker() || toRenderListMarker(*m_lastObject).isInside())) {
    3423             m_width.commit();
    3424             m_lineBreak.moveToStartOf(m_nextObject);
    3425         }
    3426     }
    3427 }
    3428 
    3429 InlineIterator BreakingContext::handleEndOfLine()
    3430 {
    3431 #if ENABLE(CSS_SHAPES)
    3432     ShapeInsideInfo* shapeInfo = m_block.layoutShapeInsideInfo();
    3433     bool segmentAllowsOverflow = !shapeInfo || !shapeInfo->hasSegments();
    3434 #else
    3435     bool segmentAllowsOverflow = true;
    3436 #endif
    3437     if (segmentAllowsOverflow) {
    3438         if (m_lineBreak == m_resolver.position()) {
    3439             if (!m_lineBreak.m_obj || !m_lineBreak.m_obj->isBR()) {
    3440                 // we just add as much as possible
    3441                 if (m_blockStyle.whiteSpace() == PRE && !m_current.m_pos) {
    3442                     m_lineBreak.moveTo(m_lastObject, m_lastObject->isText() ? m_lastObject->length() : 0);
    3443                 } else if (m_lineBreak.m_obj) {
    3444                     // Don't ever break in the middle of a word if we can help it.
    3445                     // There's no room at all. We just have to be on this line,
    3446                     // even though we'll spill out.
    3447                     m_lineBreak.moveTo(m_current.m_obj, m_current.m_pos);
    3448                 }
    3449             }
    3450             // make sure we consume at least one char/object.
    3451             if (m_lineBreak == m_resolver.position())
    3452                 m_lineBreak.increment();
    3453         } else if (!m_current.m_pos && !m_width.committedWidth() && m_width.uncommittedWidth() && !m_hadUncommittedWidthBeforeCurrent) {
    3454             // Do not push the current object to the next line, when this line has some content, but it is still considered empty.
    3455             // Empty inline elements like <span></span> can produce such lines and now we just ignore these break opportunities
    3456             // at the start of a line, if no width has been committed yet.
    3457             // Behave as if it was actually empty and consume at least one object.
    3458             m_lineBreak.increment();
    3459         }
    3460     }
    3461 
    3462     // Sanity check our midpoints.
    3463     checkMidpoints(m_lineMidpointState, m_lineBreak);
    3464 
    3465     m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, m_lineBreak, TrailingObjects::CollapseFirstSpace);
    3466 
    3467     // We might have made lineBreak an iterator that points past the end
    3468     // of the object. Do this adjustment to make it point to the start
    3469     // of the next object instead to avoid confusing the rest of the
    3470     // code.
    3471     if (m_lineBreak.m_pos > 0) {
    3472         m_lineBreak.m_pos--;
    3473         m_lineBreak.increment();
    3474     }
    3475 
    3476     return m_lineBreak;
    34772061}
    34782062
  • trunk/Source/WebCore/rendering/line/LineInfo.h

    r159353 r159354  
    3535namespace WebCore {
    3636
     37class RenderBlock;
     38
    3739class LineInfo {
    3840public:
     
    5759    void setFirstLine(bool firstLine) { m_isFirstLine = firstLine; }
    5860    void setLastLine(bool lastLine) { m_isLastLine = lastLine; }
    59     void setEmpty(bool empty, RenderBlock* block = 0, LineWidth* lineWidth = 0)
    60     {
    61         if (m_isEmpty == empty)
    62             return;
    63         m_isEmpty = empty;
    64         if (!empty && block && floatPaginationStrut()) {
    65             block->setLogicalHeight(block->logicalHeight() + floatPaginationStrut());
    66             setFloatPaginationStrut(0);
    67             lineWidth->updateAvailableWidth();
    68         }
    69     }
    70 
     61    void setEmpty(bool empty, RenderBlock* block = 0, LineWidth* lineWidth = 0);
    7162    void setPreviousLineBrokeCleanly(bool previousLineBrokeCleanly) { m_previousLineBrokeCleanly = previousLineBrokeCleanly; }
    7263    void setFloatPaginationStrut(LayoutUnit strut) { m_floatPaginationStrut = strut; }
Note: See TracChangeset for help on using the changeset viewer.