Skip to content

Commit

Permalink
Add baseline offset for inline-block elements.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikke89 committed Aug 11, 2020
1 parent db6509c commit 7c57bd3
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 10 deletions.
5 changes: 5 additions & 0 deletions Include/RmlUi/Core/Element.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class ElementDefinition;
class ElementDocument;
class ElementScroll;
class ElementStyle;
class LayoutBlockBox;
class PropertiesIteratorView;
class FontFaceHandleDefault;
class PropertyDictionary;
Expand Down Expand Up @@ -639,6 +640,7 @@ class RMLUICORE_API Element : public ScriptInterface, public EnableObserverPtr<E

void DirtyOffset();
void UpdateOffset();
void SetBaseline(float baseline);

void BuildLocalStackingContext();
void BuildStackingContext(ElementList* stacking_context);
Expand Down Expand Up @@ -715,6 +717,8 @@ class RMLUICORE_API Element : public ScriptInterface, public EnableObserverPtr<E
// 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;

Expand Down Expand Up @@ -751,6 +755,7 @@ class RMLUICORE_API Element : public ScriptInterface, public EnableObserverPtr<E
friend class Context;
friend class ElementStyle;
friend class LayoutEngine;
friend class LayoutBlockBox;
friend class LayoutInlineBox;
friend class ElementScroll;
};
Expand Down
9 changes: 8 additions & 1 deletion Source/Core/Element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -2165,6 +2167,11 @@ void Element::UpdateOffset()
}
}

void Element::SetBaseline(float in_baseline)
{
baseline = in_baseline;
}

void Element::BuildLocalStackingContext()
{
stacking_context_dirty = false;
Expand Down
44 changes: 40 additions & 4 deletions Source/Core/LayoutBlockBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 (found_baseline)
break;
}
}

if (found_baseline)
{
if (baseline < 0 && overflow_x_property != Style::Overflow::Visible || overflow_x_property != Style::Overflow::Visible)
{
baseline = 0;
}

element->SetBaseline(baseline);
}
}
}

return OK;
Expand Down
3 changes: 1 addition & 2 deletions Source/Core/LayoutInlineBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions Source/Core/LayoutLineBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/LayoutLineBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class LayoutLineBox

float GetBoxCursor() const;

bool GetBaselineOfLastLine(float& baseline) const;

void* operator new(size_t size);
void operator delete(void* chunk);

Expand Down
9 changes: 7 additions & 2 deletions Tests/Data/VisualTests/inline_block.rml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@
color: #444;
}
.float {
float: left;
color: #393;
}
.left {
float: left;
}
.right {
float: right;
}
.iblock {
display: inline-block;
color: #33c;
Expand All @@ -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>
<hr/>
<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>
<hr/>
<div class="iblock">Nesting inline-blocks:
<div class="iblock">A<div class="iblock">B<div class="iblock">C</div></div></div>
Expand Down
2 changes: 1 addition & 1 deletion Tests/Data/style.rcss
Original file line number Diff line number Diff line change
@@ -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;
}

Expand Down

0 comments on commit 7c57bd3

Please sign in to comment.