2018-03-09 19:10:37 +00:00
/ *
* Copyright ( C ) 2018 Apple Inc . All Rights Reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC . ` ` AS IS '' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL APPLE INC . OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL ,
* EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO ,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR
* PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
class LayoutPoint {
constructor ( top , left ) {
this . m _top = top ;
this . m _left = left ;
}
setLeft ( left ) {
this . m _left = left ;
}
setTop ( top ) {
this . m _top = top ;
}
left ( ) {
return this . m _left ;
}
top ( ) {
return this . m _top ;
}
shiftLeft ( distance ) {
this . m _left += distance ;
}
shiftTop ( distance ) {
this . m _top += distance ;
}
moveBy ( distance ) {
if ( distance . top && distance . left ) {
this . m _top += distance . top ( ) ;
this . m _left += distance . left ( ) ;
}
else if ( distance . width && distance . height ) {
this . m _top += distance . height ( ) ;
this . m _left += distance . width ( ) ;
}
}
equal ( other ) {
return this . top ( ) == other . top ( ) && this . left ( ) == other . left ( ) ;
}
clone ( ) {
return new LayoutPoint ( this . top ( ) , this . left ( ) ) ;
}
}
class LayoutSize {
constructor ( width , height ) {
this . m _width = width ;
this . m _height = height ;
}
setWidth ( width ) {
this . m _width = width ;
}
setHeight ( height ) {
this . m _height = height ;
}
width ( ) {
return this . m _width ;
}
height ( ) {
return this . m _height ;
}
growBy ( distance ) {
this . m _width += distance . width ( ) ;
this . m _height += distance . height ( ) ;
}
shrinkBy ( distance ) {
this . m _width -= distance . width ( ) ;
this . m _height -= distance . height ( ) ;
}
isEmpty ( ) {
return this . m _width <= 0 || this . m _height <= 0 ;
}
equal ( other ) {
return this . width ( ) == other . width ( ) && this . height ( ) == other . height ( ) ;
}
clone ( ) {
return new LayoutSize ( this . width ( ) , this . height ( ) ) ;
}
}
class LayoutRect {
constructor ( topLeft , size ) {
this . m _topLeft = topLeft . clone ( ) ;
this . m _size = size . clone ( ) ;
}
setTop ( top ) {
this . m _topLeft . setTop ( top ) ;
}
setLeft ( left ) {
this . m _topLeft . setLeft ( left ) ;
}
setBottom ( bottom ) {
this . m _size . setHeight ( bottom - this . m _topLeft . top ( ) ) ;
}
setRight ( right ) {
this . m _size . setWidth ( right - this . m _topLeft . left ( ) ) ;
}
left ( ) {
return this . m _topLeft . left ( ) ;
}
top ( ) {
return this . m _topLeft . top ( ) ;
}
bottom ( ) {
return this . m _topLeft . top ( ) + this . m _size . height ( ) ;
}
right ( ) {
return this . m _topLeft . left ( ) + this . m _size . width ( ) ;
}
setTopLeft ( topLeft ) {
this . m _topLeft = topLeft . clone ( ) ;
}
topLeft ( ) {
return this . m _topLeft . clone ( ) ;
}
topRight ( ) {
return new LayoutPoint ( this . top ( ) , this . right ( ) ) ;
}
bottomRight ( ) {
return new LayoutPoint ( this . bottom ( ) , this . right ( ) ) ;
}
setWidth ( width ) {
this . m _size . setWidth ( width ) ;
}
setHeight ( height ) {
this . m _size . setHeight ( height ) ;
}
setSize ( newSize ) {
this . m _size = newSize . clone ( ) ;
}
size ( ) {
return this . m _size . clone ( ) ;
}
width ( ) {
return this . m _size . width ( ) ;
}
height ( ) {
return this . m _size . height ( ) ;
}
growBy ( distance ) {
this . m _size . growBy ( distance ) ;
}
shrinkBy ( distance ) {
this . m _size . shrinkBy ( distance ) ;
}
moveBy ( distance ) {
this . m _topLeft . moveBy ( distance ) ;
}
2018-04-06 02:12:26 +00:00
2018-04-10 01:53:00 +00:00
growHorizontally ( distance ) {
this . m _size . setWidth ( this . m _size . width ( ) + distance ) ;
}
2018-04-06 02:12:26 +00:00
moveHorizontally ( distance ) {
this . m _topLeft . shiftLeft ( distance ) ;
}
moveVertically ( distance ) {
this . m _topLeft . shiftTop ( distance ) ;
}
2018-03-09 19:10:37 +00:00
isEmpty ( ) {
return this . m _size . isEmpty ( ) ;
}
equal ( other ) {
return this . m _topLeft . equal ( other . topLeft ( ) ) && this . m _size . equal ( other . size ( ) ) ;
}
intersects ( other ) {
return ! this . isEmpty ( ) && ! other . isEmpty ( )
&& this . left ( ) < other . right ( ) && other . left ( ) < this . right ( )
&& this . top ( ) < other . bottom ( ) && other . top ( ) < this . bottom ( ) ;
}
contains ( other ) {
return this . left ( ) <= other . left ( ) && this . right ( ) >= other . right ( )
&& this . top ( ) <= other . top ( ) && this . bottom ( ) >= other . bottom ( ) ;
}
clone ( ) {
return new LayoutRect ( this . topLeft ( ) . clone ( ) , this . size ( ) . clone ( ) ) ;
}
}
function ASSERT _NOT _REACHED ( ) {
throw Error ( "Should not reach!" ) ;
}
function ASSERT ( statement ) {
if ( statement )
return ;
throw Error ( "Assertion failure" ) ;
}
class Utils {
static computedValue ( strValue , baseValue ) {
if ( strValue . indexOf ( "px" ) > - 1 )
return parseFloat ( strValue ) ;
if ( strValue . indexOf ( "%" ) > - 1 )
return parseFloat ( strValue ) * baseValue / 100 ;
return Number . NaN ;
}
static propertyIsAuto ( propertyName , box ) {
if ( box . isAnonymous ( ) )
return true ;
return window . getComputedStyle ( box . node ( ) ) . isPropertyValueInitial ( propertyName ) ;
}
static isWidthAuto ( box ) {
return Utils . propertyIsAuto ( "width" , box ) ;
}
static isHeightAuto ( box ) {
return Utils . propertyIsAuto ( "height" , box ) ;
}
static isTopAuto ( box ) {
return Utils . propertyIsAuto ( "top" , box ) ;
}
static isLeftAuto ( box ) {
return Utils . propertyIsAuto ( "left" , box ) ;
}
static isBottomAuto ( box ) {
return Utils . propertyIsAuto ( "bottom" , box ) ;
}
static isRightAuto ( box ) {
return Utils . propertyIsAuto ( "right" , box ) ;
}
static width ( box ) {
ASSERT ( ! Utils . isWidthAuto ( box ) ) ;
return parseFloat ( window . getComputedStyle ( box . node ( ) ) . width ) ;
}
static height ( box ) {
ASSERT ( ! Utils . isHeightAuto ( box ) ) ;
return parseFloat ( window . getComputedStyle ( box . node ( ) ) . height ) ;
}
static top ( box ) {
return parseFloat ( box . node ( ) . style . top ) ;
}
static bottom ( box ) {
return parseFloat ( box . node ( ) . style . bottom ) ;
}
static left ( box ) {
return parseFloat ( box . node ( ) . style . left ) ;
}
static right ( box ) {
return parseFloat ( box . node ( ) . style . right ) ;
}
static hasBorderTop ( box ) {
return window . getComputedStyle ( box . node ( ) ) . borderTopWidth != "0px" ;
}
static hasBorderBottom ( box ) {
return window . getComputedStyle ( box . node ( ) ) . borderBottomWidth != "0px" ;
}
static hasPaddingTop ( box ) {
return window . getComputedStyle ( box . node ( ) ) . paddingTop != "0px" ;
}
static hasPaddingBottom ( box ) {
return window . getComputedStyle ( box . node ( ) ) . paddingBottom != "0px" ;
}
2018-03-16 14:52:42 +00:00
static computedMarginTop ( node ) {
return Utils . computedValue ( window . getComputedStyle ( node ) . marginTop ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedMarginLeft ( node ) {
return Utils . computedValue ( window . getComputedStyle ( node ) . marginLeft ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedMarginBottom ( node ) {
return Utils . computedValue ( window . getComputedStyle ( node ) . marginBottom ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedMarginRight ( node ) {
return Utils . computedValue ( window . getComputedStyle ( node ) . marginRight ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedBorderTopLeft ( node ) {
2018-03-09 19:10:37 +00:00
return new LayoutSize ( Utils . computedValue ( window . getComputedStyle ( node ) . borderLeftWidth ) , Utils . computedValue ( window . getComputedStyle ( node ) . borderTopWidth ) ) ;
}
2018-03-16 14:52:42 +00:00
static computedBorderBottomRight ( node ) {
2018-03-09 19:10:37 +00:00
return new LayoutSize ( Utils . computedValue ( window . getComputedStyle ( node ) . borderRightWidth ) , Utils . computedValue ( window . getComputedStyle ( node ) . borderBottomWidth ) ) ;
}
2018-03-16 14:52:42 +00:00
static computedPaddingTopLeft ( node ) {
2018-03-09 19:10:37 +00:00
return new LayoutSize ( Utils . computedValue ( window . getComputedStyle ( node ) . paddingLeft ) , Utils . computedValue ( window . getComputedStyle ( node ) . paddingTop ) ) ;
}
2018-03-16 14:52:42 +00:00
static computedPaddingBottomRight ( node ) {
2018-03-09 19:10:37 +00:00
return new LayoutSize ( Utils . computedValue ( window . getComputedStyle ( node ) . paddingRight ) , Utils . computedValue ( window . getComputedStyle ( node ) . paddingBottom ) ) ;
}
2018-03-16 14:52:42 +00:00
static computedBorderAndPaddingTop ( node ) {
return Utils . computedBorderTopLeft ( node ) . height ( ) + Utils . computedPaddingTopLeft ( node ) . height ( ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedBorderAndPaddingLeft ( node ) {
return Utils . computedBorderTopLeft ( node ) . width ( ) + Utils . computedPaddingTopLeft ( node ) . width ( ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedBorderAndPaddingTop ( node ) {
return Utils . computedBorderTopLeft ( node ) . height ( ) + Utils . computedPaddingTopLeft ( node ) . height ( ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedBorderAndPaddingLeft ( node ) {
return Utils . computedBorderTopLeft ( node ) . width ( ) + Utils . computedPaddingTopLeft ( node ) . width ( ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedBorderAndPaddingBottom ( node ) {
return Utils . computedBorderBottomRight ( node ) . height ( ) + Utils . computedPaddingBottomRight ( node ) . height ( ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedBorderAndPaddingRight ( node ) {
return Utils . computedBorderBottomRight ( node ) . width ( ) + Utils . computedPaddingBottomRight ( node ) . width ( ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedHorizontalBorderAndPadding ( node ) {
return this . computedBorderAndPaddingLeft ( node ) + this . computedBorderAndPaddingRight ( node ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedVerticalBorderAndPadding ( node ) {
return this . computedBorderAndPaddingTop ( node ) + this . computedBorderAndPaddingBottom ( node ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-16 14:52:42 +00:00
static computedLineHeight ( node ) {
return Utils . computedValue ( window . getComputedStyle ( node ) . lineHeight ) ;
2018-03-14 14:48:39 +00:00
}
2018-03-09 19:10:37 +00:00
static hasClear ( box ) {
return Utils . hasClearLeft ( box ) || Utils . hasClearRight ( box ) || Utils . hasClearBoth ( box ) ;
}
static hasClearLeft ( box ) {
return window . getComputedStyle ( box . node ( ) ) . clear == "left" ;
}
static hasClearRight ( box ) {
return window . getComputedStyle ( box . node ( ) ) . clear == "right" ;
}
static hasClearBoth ( box ) {
return window . getComputedStyle ( box . node ( ) ) . clear == "both" ;
}
static isBlockLevelElement ( node ) {
if ( ! node )
return false ;
let display = window . getComputedStyle ( node ) . display ;
return display == "block" || display == "list-item" || display == "table" ;
}
static isBlockContainerElement ( node ) {
2018-04-10 01:53:00 +00:00
if ( ! node || node . nodeType != Node . ELEMENT _NODE )
2018-03-14 14:48:39 +00:00
return false ;
2018-03-09 19:10:37 +00:00
let display = window . getComputedStyle ( node ) . display ;
return display == "block" || display == "list-item" || display == "inline-block" || display == "table-cell" || display == "table-caption" ; //TODO && !replaced element
}
static isInlineLevelElement ( node ) {
let display = window . getComputedStyle ( node ) . display ;
return display == "inline" || display == "inline-block" || display == "inline-table" ;
}
static isTableElement ( node ) {
let display = window . getComputedStyle ( node ) . display ;
return display == "table" || display == "inline-table" ;
}
2018-04-10 01:53:00 +00:00
static isInlineBlockElement ( node ) {
if ( ! node || node . nodeType != Node . ELEMENT _NODE )
return false ;
let display = window . getComputedStyle ( node ) . display ;
return display == "inline-block" ;
}
2018-03-17 20:49:54 +00:00
static isRelativelyPositioned ( box ) {
2018-03-09 19:10:37 +00:00
if ( box . isAnonymous ( ) )
return false ;
let node = box . node ( ) ;
return window . getComputedStyle ( node ) . position == "relative" ;
}
2018-03-17 20:49:54 +00:00
static isAbsolutelyPositioned ( box ) {
2018-03-09 19:10:37 +00:00
if ( box . isAnonymous ( ) )
return false ;
let node = box . node ( ) ;
return window . getComputedStyle ( node ) . position == "absolute" ;
}
static isFixedPositioned ( box ) {
if ( box . isAnonymous ( ) )
return false ;
let node = box . node ( ) ;
return window . getComputedStyle ( node ) . position == "fixed" ;
}
2018-03-19 22:58:10 +00:00
static isStaticallyPositioned ( box ) {
if ( box . isAnonymous ( ) )
return true ;
let node = box . node ( ) ;
return ( Utils . propertyIsAuto ( "top" , box ) && Utils . propertyIsAuto ( "bottom" , box ) ) || ( Utils . propertyIsAuto ( "left" , box ) && Utils . propertyIsAuto ( "right" , box ) ) ;
}
2018-03-09 19:10:37 +00:00
static isOverflowVisible ( box ) {
return window . getComputedStyle ( box . node ( ) ) . overflow == "visible" ;
}
static isFloatingPositioned ( box ) {
if ( box . isAnonymous ( ) )
return false ;
let node = box . node ( ) ;
return window . getComputedStyle ( node ) . float != "none" ;
}
static isFloatingLeft ( box ) {
let node = box . node ( ) ;
return window . getComputedStyle ( node ) . float == "left" ;
}
2018-04-01 02:07:25 +00:00
static mapPosition ( position , box , container ) {
2018-04-01 01:12:13 +00:00
ASSERT ( box instanceof Display . Box ) ;
ASSERT ( container instanceof Display . Box ) ;
if ( box == container )
2018-04-01 02:07:25 +00:00
return position ;
2018-04-01 01:12:13 +00:00
for ( let ascendant = box . parent ( ) ; ascendant && ascendant != container ; ascendant = ascendant . parent ( ) )
2018-04-01 02:07:25 +00:00
position . moveBy ( ascendant . topLeft ( ) ) ;
return position ;
2018-04-01 01:12:13 +00:00
}
2018-04-01 02:07:25 +00:00
static marginBox ( box , container ) {
let marginBox = box . marginBox ( ) ;
let mappedPosition = Utils . mapPosition ( marginBox . topLeft ( ) , box , container ) ;
return new LayoutRect ( mappedPosition , marginBox . size ( ) ) ;
}
static borderBox ( box , container ) {
let borderBox = box . borderBox ( ) ;
let mappedPosition = Utils . mapPosition ( box . topLeft ( ) , box , container ) ;
mappedPosition . moveBy ( borderBox . topLeft ( ) ) ;
return new LayoutRect ( mappedPosition , borderBox . size ( ) ) ;
}
static contentBox ( box , container ) {
let contentBox = box . contentBox ( ) ;
let mappedPosition = Utils . mapPosition ( box . topLeft ( ) , box , container ) ;
mappedPosition . moveBy ( contentBox . topLeft ( ) ) ;
return new LayoutRect ( mappedPosition , contentBox . size ( ) ) ;
}
2018-04-01 01:12:13 +00:00
2018-03-28 04:52:54 +00:00
static textRuns ( text , container ) {
return window . collectTextRuns ( text , container . node ( ) ) ;
}
static textRunsForLine ( text , availableSpace , container ) {
return window . collectTextRuns ( text , container . node ( ) , availableSpace ) ;
}
2018-03-12 03:46:57 +00:00
static nextBreakingOpportunity ( textBox , currentPosition )
2018-03-09 19:10:37 +00:00
{
2018-03-12 03:46:57 +00:00
return window . nextBreakingOpportunity ( textBox . content ( ) , currentPosition ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-12 03:46:57 +00:00
static measureText ( texBox , start , end )
2018-03-09 19:10:37 +00:00
{
2018-03-12 03:46:57 +00:00
return texBox . node ( ) . textWidth ( start , end ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-14 14:48:39 +00:00
static textHeight ( textBox )
{
return textBox . text ( ) . node ( ) . textHeight ( ) ;
}
2018-04-14 03:21:59 +00:00
static layoutBoxById ( layoutBoxId , box ) {
if ( box . id ( ) == layoutBoxId )
return box ;
if ( ! box . isContainer ( ) )
return null ;
// Super inefficient but this is all temporary anyway.
for ( let child = box . firstChild ( ) ; child ; child = child . nextSibling ( ) ) {
if ( child . id ( ) == layoutBoxId )
return child ;
let foundIt = Utils . layoutBoxById ( layoutBoxId , child ) ;
if ( foundIt )
return foundIt ;
}
return null ;
}
2018-03-09 19:10:37 +00:00
// "RenderView at (0,0) size 1317x366\n HTML RenderBlock at (0,0) size 1317x116\n BODY RenderBody at (8,8) size 1301x100\n DIV RenderBlock at (0,0) size 100x100\n";
2018-04-13 05:27:52 +00:00
static layoutTreeDump ( layoutState ) {
return this . _dumpBox ( layoutState , layoutState . rootContainer ( ) , 1 ) + this . _dumpTree ( layoutState , layoutState . rootContainer ( ) , 2 ) ;
2018-03-09 19:10:37 +00:00
}
2018-03-21 04:42:32 +00:00
static _dumpBox ( layoutState , box , level ) {
2018-03-09 19:10:37 +00:00
// Skip anonymous boxes for now -This is the case where WebKit does not generate an anon inline container for text content where the text is a direct child
// of a block container.
let indentation = " " . repeat ( level ) ;
2018-04-08 05:27:36 +00:00
if ( box . isInlineBox ( ) ) {
2018-03-14 14:48:39 +00:00
if ( box . text ( ) )
return indentation + "#text RenderText\n" ;
}
2018-04-10 05:06:37 +00:00
if ( box . name ( ) == "RenderInline" ) {
if ( box . isInFlowPositioned ( ) ) {
2018-04-13 03:09:03 +00:00
let displayBox = layoutState . displayBox ( box ) ;
2018-04-10 05:06:37 +00:00
let boxRect = displayBox . rect ( ) ;
return indentation + box . node ( ) . tagName + " " + box . name ( ) + " (" + Utils . precisionRoundWithDecimals ( boxRect . left ( ) ) + ", " + Utils . precisionRoundWithDecimals ( boxRect . top ( ) ) + ")\n" ;
}
2018-04-08 05:27:36 +00:00
return indentation + box . node ( ) . tagName + " " + box . name ( ) + "\n" ;
2018-04-10 05:06:37 +00:00
}
2018-03-14 14:48:39 +00:00
if ( box . isAnonymous ( ) )
return "" ;
2018-04-13 03:09:03 +00:00
let displayBox = layoutState . displayBox ( box ) ;
2018-03-19 03:00:26 +00:00
let boxRect = displayBox . rect ( ) ;
2018-04-17 14:32:46 +00:00
return indentation + ( box . node ( ) . tagName ? ( box . node ( ) . tagName + " " ) : "" ) + box . name ( ) + " at (" + Utils . precisionRound ( boxRect . left ( ) ) + "," + Utils . precisionRound ( boxRect . top ( ) ) + ") size " + Utils . precisionRound ( boxRect . width ( ) ) + "x" + Utils . precisionRound ( boxRect . height ( ) ) + "\n" ;
2018-03-09 19:10:37 +00:00
}
2018-03-21 16:32:00 +00:00
static _dumpLines ( layoutState , root , level ) {
2018-03-14 14:48:39 +00:00
ASSERT ( root . establishesInlineFormattingContext ( ) ) ;
2018-04-01 03:07:26 +00:00
let inlineFormattingState = layoutState . establishedFormattingState ( root ) ;
2018-03-21 16:32:00 +00:00
let lines = inlineFormattingState . lines ( ) ;
2018-03-14 14:48:39 +00:00
let content = "" ;
let indentation = " " . repeat ( level ) ;
lines . forEach ( function ( line ) {
let lineRect = line . rect ( ) ;
2018-04-10 05:06:37 +00:00
content += indentation + "RootInlineBox at (" + lineRect . left ( ) + "," + lineRect . top ( ) + ") size " + Utils . precisionRound ( lineRect . width ( ) ) + "x" + lineRect . height ( ) + "\n" ;
2018-03-14 14:48:39 +00:00
line . lineBoxes ( ) . forEach ( function ( lineBox ) {
let indentation = " " . repeat ( level + 1 ) ;
2018-04-10 01:53:00 +00:00
let inlineBoxName = lineBox . startPosition === undefined ? "InlineBox" : "InlineTextBox" ;
2018-04-10 05:06:37 +00:00
content += indentation + inlineBoxName + " at (" + Utils . precisionRound ( lineBox . lineBoxRect . left ( ) ) + "," + Utils . precisionRound ( lineBox . lineBoxRect . top ( ) ) + ") size " + Utils . precisionRound ( lineBox . lineBoxRect . width ( ) ) + "x" + lineBox . lineBoxRect . height ( ) + "\n" ;
2018-03-14 14:48:39 +00:00
} ) ;
} ) ;
return content ;
}
2018-03-21 04:42:32 +00:00
static _dumpTree ( layoutState , root , level ) {
2018-03-09 19:10:37 +00:00
let content = "" ;
2018-03-14 14:48:39 +00:00
if ( root . isBlockContainerBox ( ) && root . establishesInlineFormattingContext ( ) )
2018-03-21 16:32:00 +00:00
content += this . _dumpLines ( layoutState , root , level ) ;
2018-03-09 19:10:37 +00:00
for ( let child = root . firstChild ( ) ; child ; child = child . nextSibling ( ) ) {
2018-03-21 04:42:32 +00:00
content += this . _dumpBox ( layoutState , child , level ) ;
2018-03-09 19:10:37 +00:00
if ( child . isContainer ( ) )
2018-03-21 04:42:32 +00:00
content += this . _dumpTree ( layoutState , child , level + 1 , content ) ;
2018-03-09 19:10:37 +00:00
}
return content ;
}
2018-03-14 14:48:39 +00:00
2018-04-10 05:06:37 +00:00
static precisionRoundWithDecimals ( number ) {
return number . toFixed ( 2 ) ;
}
static precisionRound ( number ) {
let factor = Math . pow ( 10 , 2 ) ;
2018-03-14 14:48:39 +00:00
return Math . round ( number * factor ) / factor ;
}
2018-03-09 19:10:37 +00:00
}