Skip to content

Commit

Permalink
Update content implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
sammycage committed Dec 6, 2024
1 parent 118077a commit 60f3ad0
Show file tree
Hide file tree
Showing 5 changed files with 7 additions and 213 deletions.
193 changes: 1 addition & 192 deletions source/htmldocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "cssrule.h"
#include "counters.h"
#include "textbox.h"
#include "contentbox.h"
#include "replacedbox.h"
#include "tablebox.h"
#include "formcontrolbox.h"
Expand Down Expand Up @@ -113,198 +114,6 @@ void HTMLElement::buildFirstLetterPseudoBox(Box* parent)
}
}

class ContentBoxBuilder {
public:
ContentBoxBuilder(Counters& counters, Element* element, Box* box);

void build();

private:
void addText(const HeapString& text);
void addLeaderText(const HeapString& text);
void addLeader(const RefPtr<CSSValue>& value);
void addTargetCounter(const RefPtr<CSSFunctionValue>& function);
void addImage(RefPtr<Image> image);
void addQuote(CSSValueID value);

Counters& m_counters;
Element* m_element;
Box* m_parentBox;
BoxStyle* m_parentStyle;
TextBox* m_lastTextBox{nullptr};
};

ContentBoxBuilder::ContentBoxBuilder(Counters& counters, Element* element, Box* box)
: m_counters(counters)
, m_element(element)
, m_parentBox(box)
, m_parentStyle(box->style())
{
}

void ContentBoxBuilder::addText(const HeapString& text)
{
if(text.empty())
return;
if(m_lastTextBox) {
m_lastTextBox->appendText(text);
return;
}

auto box = new (m_element->heap()) TextBox(nullptr, m_parentStyle);
box->setText(text);
m_parentBox->addChild(box);
m_lastTextBox = box;
}

void ContentBoxBuilder::addLeaderText(const HeapString& text)
{
if(text.empty())
return;
auto box = new (m_element->heap()) LeaderTextBox(m_parentStyle);
box->setText(text);
m_parentBox->addChild(box);
m_lastTextBox = nullptr;
}

void ContentBoxBuilder::addLeader(const RefPtr<CSSValue>& value)
{
static const GlobalString dotted(".");
static const GlobalString solid("_");
static const GlobalString space(" ");
if(auto string = to<CSSStringValue>(value)) {
addLeaderText(string->value());
return;
}

auto& ident = to<CSSIdentValue>(*value);
switch(ident.value()) {
case CSSValueID::Dotted:
addLeaderText(dotted);
break;
case CSSValueID::Solid:
addLeaderText(solid);
break;
case CSSValueID::Space:
addLeaderText(space);
break;
default:
assert(false);
}
}

void ContentBoxBuilder::addTargetCounter(const RefPtr<CSSFunctionValue>& function)
{
HeapString fragment;
GlobalString identifier;
HeapString seperator;
GlobalString listStyle;

size_t index = 0;

assert(function->id() == CSSValueID::TargetCounter || function->id() == CSSValueID::TargetCounters);
if(auto attr = to<CSSUnaryFunctionValue>(function->at(index))) {
assert(attr->id() == CSSValueID::Attr);
fragment = m_element->getAttribute(to<CSSCustomIdentValue>(*attr->value()).value());
} else {
fragment = to<CSSLocalUrlValue>(*function->at(index)).value();
}

++index;

identifier = to<CSSCustomIdentValue>(*function->at(index++)).value();
if(function->id() == CSSValueID::TargetCounters)
seperator = to<CSSStringValue>(*function->at(index++)).value();
if(index < function->size()) {
listStyle = to<CSSCustomIdentValue>(*function->at(index++)).value();
assert(index == function->size());
}

addText(m_element->document()->getTargetCounterText(fragment, identifier, listStyle, seperator));
}

void ContentBoxBuilder::addImage(RefPtr<Image> image)
{
if(image == nullptr)
return;
auto style = BoxStyle::create(*m_parentStyle, Display::Inline);
auto box = new (m_element->heap()) ImageBox(nullptr, style);
box->setImage(std::move(image));
m_parentBox->addChild(box);
m_lastTextBox = nullptr;
}

void ContentBoxBuilder::addQuote(CSSValueID value)
{
assert(value == CSSValueID::OpenQuote || value == CSSValueID::CloseQuote || value == CSSValueID::NoOpenQuote || value == CSSValueID::NoCloseQuote);
auto openquote = (value == CSSValueID::OpenQuote || value == CSSValueID::NoOpenQuote);
auto closequote = (value == CSSValueID::CloseQuote || value == CSSValueID::NoCloseQuote);
auto usequote = (value == CSSValueID::OpenQuote || value == CSSValueID::CloseQuote);
if(closequote && m_counters.quoteDepth())
m_counters.decreaseQuoteDepth();
if(usequote)
addText(m_parentStyle->getQuote(openquote, m_counters.quoteDepth()));
if(openquote) {
m_counters.increaseQuoteDepth();
}
}

void ContentBoxBuilder::build()
{
auto content = m_parentStyle->get(CSSPropertyID::Content);
if(content && content->id() == CSSValueID::None)
return;
if(content == nullptr || content->id() == CSSValueID::Normal) {
if(m_parentStyle->pseudoType() != PseudoType::Marker)
return;
if(auto image = m_parentStyle->listStyleImage()) {
addImage(std::move(image));
return;
}

auto listStyleType = m_parentStyle->get(CSSPropertyID::ListStyleType);
if(listStyleType == nullptr) {
static const GlobalString disc("disc");
addText(m_counters.markerText(disc));
return;
}

if(listStyleType->id() == CSSValueID::None)
return;
if(auto listStyle = to<CSSStringValue>(listStyleType)) {
addText(listStyle->value());
return;
}

auto& listStyle = to<CSSCustomIdentValue>(*listStyleType);
addText(m_counters.markerText(listStyle.value()));
return;
}

for(auto& value : to<CSSListValue>(*content)) {
if(auto string = to<CSSStringValue>(value)) {
addText(string->value());
} else if(auto image = to<CSSImageValue>(value)) {
addImage(image->fetch(m_element->document()));
} else if(auto counter = to<CSSCounterValue>(value)) {
addText(m_counters.counterText(counter->identifier(), counter->listStyle(), counter->separator()));
} else if(auto targetCounter = to<CSSFunctionValue>(value)) {
addTargetCounter(targetCounter);
} else if(auto ident = to<CSSIdentValue>(value)) {
addQuote(ident->value());
} else {
auto& function = to<CSSUnaryFunctionValue>(*value);
if(function.id() == CSSValueID::Attr) {
auto& name = to<CSSCustomIdentValue>(*function.value());
addText(m_element->getAttribute(name.value()));
} else {
assert(function.id() == CSSValueID::Leader);
addLeader(function.value());
}
}
}
}

void HTMLElement::buildPseudoBox(Counters& counters, Box* parent, PseudoType pseudoType)
{
if(pseudoType == PseudoType::Marker && !parent->isListItemBox())
Expand Down
6 changes: 5 additions & 1 deletion source/layout/box.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ class Box : public HeapMember {
virtual bool isTextBox() const { return false; }
virtual bool isLineBreakBox() const { return false; }
virtual bool isWordBreakBox() const { return false; }
virtual bool isLeaderTextBox() const { return false; }
virtual bool isContentBox() const { return false; }
virtual bool isLeaderBox() const { return false; }
virtual bool isTargetCounterBox() const { return false; }
virtual bool isPageCounterBox() const { return false; }
virtual bool isPagesCounterBox() const { return false; }
virtual bool isInlineBox() const { return false; }
virtual bool isBlockBox() const { return false; }
virtual bool isBlockFlowBox() const { return false; }
Expand Down
2 changes: 1 addition & 1 deletion source/layout/linelayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ void LineItemsBuilder::appendText(Box* box, const UString& text)
}

restoreTrailingCollapsibleSpaceIfRemoved();
if(box->isLeaderTextBox()) {
if(box->isLeaderBox()) {
appendTextItem(LineItem::Type::LeaderText, box, text);
return;
}
Expand Down
5 changes: 0 additions & 5 deletions source/layout/textbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,4 @@ WordBreakBox::WordBreakBox(Node* node, const RefPtr<BoxStyle>& style)
{
}

LeaderTextBox::LeaderTextBox(const RefPtr<BoxStyle>& style)
: TextBox(nullptr, style)
{
}

} // namespace plutobook
14 changes: 0 additions & 14 deletions source/layout/textbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,6 @@ struct is_a<WordBreakBox> {
static bool check(const Box& box) { return box.isWordBreakBox(); }
};

class LeaderTextBox final : public TextBox {
public:
LeaderTextBox(const RefPtr<BoxStyle>& style);

bool isLeaderTextBox() const final { return true; }

const char* name() const final { return "LeaderTextBox"; }
};

template<>
struct is_a<LeaderTextBox> {
static bool check(const Box& box) { return box.isLeaderTextBox(); }
};

} // namespace plutobook

#endif // PLUTOBOOK_TEXTBOX_H

0 comments on commit 60f3ad0

Please sign in to comment.