@@ -55,6 +55,7 @@ class ElementDefinition;
class ElementDocument;
class ElementScroll;
class ElementStyle;
+class LayoutBlockBox;
class PropertiesIteratorView;
class FontFaceHandleDefault;
class PropertyDictionary;
@@ -639,6 +640,7 @@ private:
void DirtyOffset();
void UpdateOffset();
+ void SetBaseline(float baseline);
void BuildLocalStackingContext();
void BuildStackingContext(ElementList* stacking_context);
@@ -715,6 +717,8 @@ private:
// Defines what box area represents the element's client area; this is usually padding, but may be content.
Box::Area client_area;
+ float baseline;
+
// True if the element is visible and active.
bool visible;
@@ -751,6 +755,7 @@ private:
friend class Context;
friend class ElementStyle;
friend class LayoutEngine;
+ friend class LayoutBlockBox;
friend class LayoutInlineBox;
friend class ElementScroll;
};
@@ -130,6 +130,8 @@ transform_state(), dirty_transform(false), dirty_perspective(false), dirty_anima
client_area = Box::PADDING;
+ baseline = 0.0f;
num_non_dom_children = 0;
visible = true;
@@ -542,7 +544,7 @@ int Element::GetNumBoxes()
// Returns the baseline of the element, in pixels offset from the bottom of the element's content area.
float Element::GetBaseline() const
{
- return 0;
+ return baseline;
}
// Gets the intrinsic dimensions of this element, if it is of a type that has an inherent size.
@@ -2165,6 +2167,11 @@ void Element::UpdateOffset()
+void Element::SetBaseline(float in_baseline)
+{
+ baseline = in_baseline;
+}
void Element::BuildLocalStackingContext()
stacking_context_dirty = false;
@@ -274,12 +274,48 @@ LayoutBlockBox::CloseResult LayoutBlockBox::Close()
return LAYOUT_PARENT;
- // If we represent a positioned element, then we can now (as we've been sized) act as the containing block for all
- // the absolutely-positioned elements of our descendants.
- if (context == BLOCK)
+ if (context == BLOCK && element)
- if (!element || element->GetPosition() != Style::Position::Static)
+ // If we represent a positioned element, then we can now (as we've been sized) act as the containing block for all
+ // the absolutely-positioned elements of our descendants.
+ if (element->GetPosition() != Style::Position::Static)
+ {
CloseAbsoluteElements();
+ }
+ // Set the baseline for inline-block elements to the baseline of the last line of the element.
+ // This is a special rule for inline-blocks (see CSS 2.1 §10.8.1).
+ if (element->GetDisplay() == Style::Display::InlineBlock)
+ bool found_baseline = false;
+ float baseline = 0;
+ for (int i = (int)block_boxes.size() - 1; i >= 0; i--)
+ if (block_boxes[i]->context == INLINE)
+ const LineBoxList& line_boxes = block_boxes[i]->line_boxes;
+ for (int j = (int)line_boxes.size() - 1; j >= 0; j--)
+ found_baseline = line_boxes[j]->GetBaselineOfLastLine(baseline);
+ if (found_baseline)
+ break;
+ if (baseline < 0 && overflow_x_property != Style::Overflow::Visible || overflow_x_property != Style::Overflow::Visible)
+ baseline = 0;
+ element->SetBaseline(baseline);
return OK;
@@ -47,8 +47,7 @@ LayoutInlineBox::LayoutInlineBox(Element* _element, const Box& _box) : position(
width = 0;
- // If this box has intrinsic dimensions, then we set our height to the total height of the element; otherwise, it
- // is zero height.
+ // If this box has intrinsic dimensions, then we set our height to the total height of the element; otherwise, it is zero height.
if (box.GetSize().y > 0)
height = box.GetSize(Box::MARGIN).y;
@@ -369,6 +369,14 @@ float LayoutLineBox::GetBoxCursor() const
return box_cursor;
+bool LayoutLineBox::GetBaselineOfLastLine(float& baseline) const
+ if (inline_boxes.empty())
+ return false;
+ baseline = inline_boxes.back()->GetBaseline();
+ return true;
void* LayoutLineBox::operator new(size_t size)
return LayoutEngine::AllocateLayoutChunk(size);
@@ -90,6 +90,8 @@ public:
float GetBoxCursor() const;
+ bool GetBaselineOfLastLine(float& baseline) const;
void* operator new(size_t size);
void operator delete(void* chunk);
@@ -9,9 +9,14 @@
color: #444;
.float {
- float: left;
color: #393;
+ .left {
+ float: left;
+ .right {
+ float: right;
.iblock {
display: inline-block;
color: #33c;
@@ -29,7 +34,7 @@
<hr/>
<div>Left filler text. <div class="iblock">An inline-block. <p>A paragraph</p> Filler text.</div> Right filler text.</div>
-<div>Left filler text. <div class="iblock">An inline-block. <div class="float">A float</div> Filler text.</div> Right filler text.</div>
+<div>Left filler text. <div class="iblock">An inline-block. <div class="float right">Float right</div><div class="float left">Float left</div> Filler text.</div> Right filler text.</div>
<div class="iblock">Nesting inline-blocks:
<div class="iblock">A<div class="iblock">B<div class="iblock">C</div></div></div>
@@ -1,4 +1,4 @@
-dl,dt,dd,ul,li,blockquote,address,h1,h2,h3,h4,h5,h6,p,pre,div {
+dl,dt,dd,ul,li,blockquote,address,h1,h2,h3,h4,h5,h6,p,pre,div,section {
display: block;