From 29ab28d922ec1fd46a5a11e9e26f4832048f5c83 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 10 Sep 2015 16:01:52 -0700 Subject: [PATCH] ParagraphBuilder should be able to build a paragraph This patch start down the road of implementing text layout and painting without the DOM. We can construct a basic paragraph consisting of a single run of text and we can get through layout without crashing. --- sky/engine/core/css/CSSFontSelector.cpp | 5 +- sky/engine/core/css/FontSize.cpp | 4 +- sky/engine/core/css/resolver/FontBuilder.cpp | 6 +-- sky/engine/core/css/resolver/FontBuilder.h | 2 +- .../core/css/resolver/StyleResolver.cpp | 6 +-- sky/engine/core/dom/Document.cpp | 2 +- sky/engine/core/rendering/RenderObject.cpp | 4 +- sky/engine/core/rendering/RenderObject.h | 2 +- sky/engine/core/rendering/RenderText.cpp | 2 +- sky/engine/core/rendering/RenderView.cpp | 6 +-- sky/engine/core/rendering/RenderView.h | 2 + .../core/rendering/SubtreeLayoutScope.cpp | 2 +- sky/engine/core/text/FontStyle.h | 3 +- sky/engine/core/text/FontWeight.h | 3 +- sky/engine/core/text/Paragraph.cpp | 15 ++++-- sky/engine/core/text/Paragraph.h | 37 ++++++++------ sky/engine/core/text/ParagraphBuilder.cpp | 51 ++++++++++++++++++- sky/engine/core/text/ParagraphBuilder.h | 5 ++ sky/engine/core/text/TextAlign.h | 3 +- sky/engine/core/text/TextBaseline.h | 3 +- .../paragraph_builder_test_disabled.dart | 13 +++++ 21 files changed, 127 insertions(+), 49 deletions(-) create mode 100644 sky/unit/test/engine/paragraph_builder_test_disabled.dart diff --git a/sky/engine/core/css/CSSFontSelector.cpp b/sky/engine/core/css/CSSFontSelector.cpp index 5ac763e18f9..fa87ec7a853 100644 --- a/sky/engine/core/css/CSSFontSelector.cpp +++ b/sky/engine/core/css/CSSFontSelector.cpp @@ -43,14 +43,13 @@ namespace blink { CSSFontSelector::CSSFontSelector(Document* document) : m_document(document) - , m_genericFontFamilySettings(document->frame()->settings()->genericFontFamilySettings()) { + if (m_document) + m_genericFontFamilySettings = document->frame()->settings()->genericFontFamilySettings(); // FIXME: An old comment used to say there was no need to hold a reference to m_document // because "we are guaranteed to be destroyed before the document". But there does not // seem to be any such guarantee. - ASSERT(m_document); - ASSERT(m_document->frame()); FontCache::fontCache()->addClient(this); } diff --git a/sky/engine/core/css/FontSize.cpp b/sky/engine/core/css/FontSize.cpp index c6318b61731..958eb83c1ca 100644 --- a/sky/engine/core/css/FontSize.cpp +++ b/sky/engine/core/css/FontSize.cpp @@ -53,7 +53,7 @@ float FontSize::getComputedSizeFromSpecifiedSize(const Document* document, bool // However we always allow the page to set an explicit pixel size that is smaller, // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum). - Settings* settings = document->settings(); + Settings* settings = document ? document->settings() : nullptr; if (!settings) return 1.0f; @@ -112,7 +112,7 @@ static int inline rowFromMediumFontSizeInRange(const Settings* settings, FixedPi float FontSize::fontSizeForKeyword(const Document* document, CSSValueID keyword, FixedPitchFontType fixedPitchFontType) { ASSERT(keyword >= CSSValueXxSmall && keyword <= CSSValueWebkitXxxLarge); - const Settings* settings = document->settings(); + const Settings* settings = document ? document->settings() : nullptr; if (!settings) return 1.0f; diff --git a/sky/engine/core/css/resolver/FontBuilder.cpp b/sky/engine/core/css/resolver/FontBuilder.cpp index 15379dfb081..bc1a1d7e3e7 100644 --- a/sky/engine/core/css/resolver/FontBuilder.cpp +++ b/sky/engine/core/css/resolver/FontBuilder.cpp @@ -67,10 +67,10 @@ FontBuilder::FontBuilder() { } -void FontBuilder::initForStyleResolve(const Document& document, RenderStyle* style) +void FontBuilder::initForStyleResolve(Document* document, RenderStyle* style) { - ASSERT(document.frame()); - m_document = &document; + ASSERT(!document || document->frame()); + m_document = document; m_style = style; m_fontDirty = false; } diff --git a/sky/engine/core/css/resolver/FontBuilder.h b/sky/engine/core/css/resolver/FontBuilder.h index 811b246952b..95b31f7297d 100644 --- a/sky/engine/core/css/resolver/FontBuilder.h +++ b/sky/engine/core/css/resolver/FontBuilder.h @@ -44,7 +44,7 @@ public: FontBuilder(); // FIXME: The name is probably wrong, but matches StyleResolverState callsite for consistency. - void initForStyleResolve(const Document&, RenderStyle*); + void initForStyleResolve(Document*, RenderStyle*); void setInitial(); diff --git a/sky/engine/core/css/resolver/StyleResolver.cpp b/sky/engine/core/css/resolver/StyleResolver.cpp index 98144daf50a..b4d9134521d 100644 --- a/sky/engine/core/css/resolver/StyleResolver.cpp +++ b/sky/engine/core/css/resolver/StyleResolver.cpp @@ -177,7 +177,7 @@ PassRefPtr StyleResolver::styleForElement(Element* element, RenderS state.setParentStyle(RenderStyle::clone(state.style())); } - state.fontBuilder().initForStyleResolve(state.document(), state.style()); + state.fontBuilder().initForStyleResolve(&state.document(), state.style()); { ElementRuleCollector collector(state.elementContext(), state.style()); @@ -204,7 +204,7 @@ PassRefPtr StyleResolver::defaultStyleForElement() { StyleResolverState state(m_document, nullptr); state.setStyle(RenderStyle::create()); - state.fontBuilder().initForStyleResolve(m_document, state.style()); + state.fontBuilder().initForStyleResolve(&m_document, state.style()); state.style()->setLineHeight(RenderStyle::initialLineHeight()); state.setLineHeightValue(0); state.fontBuilder().setInitial(); @@ -415,7 +415,7 @@ void StyleResolver::applyPropertiesToStyle(const CSSPropertyValue* properties, s StyleResolverState state(m_document, nullptr, style); state.setStyle(style); - state.fontBuilder().initForStyleResolve(m_document, style); + state.fontBuilder().initForStyleResolve(&m_document, style); for (size_t i = 0; i < count; ++i) { if (properties[i].value) { diff --git a/sky/engine/core/dom/Document.cpp b/sky/engine/core/dom/Document.cpp index d619b30be17..4287d39d16b 100644 --- a/sky/engine/core/dom/Document.cpp +++ b/sky/engine/core/dom/Document.cpp @@ -627,7 +627,7 @@ void Document::scheduleVisualUpdate() void Document::setupFontBuilder(RenderStyle* documentStyle) { FontBuilder fontBuilder; - fontBuilder.initForStyleResolve(*this, documentStyle); + fontBuilder.initForStyleResolve(this, documentStyle); RefPtr selector = m_styleEngine->fontSelector(); fontBuilder.createFontForDocument(selector, documentStyle); } diff --git a/sky/engine/core/rendering/RenderObject.cpp b/sky/engine/core/rendering/RenderObject.cpp index 7bb92f105f4..442cf18f0bd 100644 --- a/sky/engine/core/rendering/RenderObject.cpp +++ b/sky/engine/core/rendering/RenderObject.cpp @@ -186,7 +186,7 @@ bool RenderObject::isDescendantOf(const RenderObject* obj) const void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild) { - ASSERT(isAllowedToModifyRenderTreeStructure(document())); + ASSERT(!m_node || isAllowedToModifyRenderTreeStructure(document())); RenderObjectChildList* children = virtualChildren(); ASSERT(children); @@ -195,7 +195,7 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild) void RenderObject::removeChild(RenderObject* oldChild) { - ASSERT(isAllowedToModifyRenderTreeStructure(document())); + ASSERT(!m_node || isAllowedToModifyRenderTreeStructure(document())); RenderObjectChildList* children = virtualChildren(); ASSERT(children); diff --git a/sky/engine/core/rendering/RenderObject.h b/sky/engine/core/rendering/RenderObject.h index 54ed169cd5c..8111130f164 100644 --- a/sky/engine/core/rendering/RenderObject.h +++ b/sky/engine/core/rendering/RenderObject.h @@ -774,7 +774,7 @@ DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(RenderObject) inline bool RenderObject::documentBeingDestroyed() const { - return !document().isActive(); + return m_node && !document().isActive(); } // setNeedsLayout() won't cause full paint invalidations as diff --git a/sky/engine/core/rendering/RenderText.cpp b/sky/engine/core/rendering/RenderText.cpp index 163ec6feed9..6bed9cab947 100644 --- a/sky/engine/core/rendering/RenderText.cpp +++ b/sky/engine/core/rendering/RenderText.cpp @@ -76,7 +76,7 @@ RenderText::RenderText(Node* node, PassRefPtr str) , m_lastTextBox(0) { ASSERT(m_text); - ASSERT(node && !node->isDocumentNode()); + ASSERT(!node || !node->isDocumentNode()); m_isAllASCII = m_text.containsOnlyASCII(); m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath(); diff --git a/sky/engine/core/rendering/RenderView.cpp b/sky/engine/core/rendering/RenderView.cpp index 21a582ca485..04fe8603283 100644 --- a/sky/engine/core/rendering/RenderView.cpp +++ b/sky/engine/core/rendering/RenderView.cpp @@ -37,7 +37,7 @@ namespace blink { RenderView::RenderView(Document* document) : RenderFlexibleBox(document) - , m_frameView(document->view()) + , m_frameView(document ? document->view() : nullptr) , m_selectionStart(nullptr) , m_selectionEnd(nullptr) , m_selectionStartPos(-1) @@ -356,14 +356,14 @@ int RenderView::viewHeight() const { if (m_frameView) return m_frameView->layoutSize().height(); - return 0; + return m_frameViewSize.height(); } int RenderView::viewWidth() const { if (m_frameView) return m_frameView->layoutSize().width(); - return 0; + return m_frameViewSize.width(); } int RenderView::viewLogicalHeight() const diff --git a/sky/engine/core/rendering/RenderView.h b/sky/engine/core/rendering/RenderView.h index 2c46d2808af..6478858339d 100644 --- a/sky/engine/core/rendering/RenderView.h +++ b/sky/engine/core/rendering/RenderView.h @@ -77,6 +77,7 @@ public: virtual void absoluteQuads(Vector&) const override; virtual LayoutRect viewRect() const override; + void setFrameViewSize(const IntSize& frameViewSize) { m_frameViewSize = frameViewSize; } IntRect unscaledDocumentRect() const; LayoutRect backgroundRect(RenderBox* backgroundRenderer) const; @@ -95,6 +96,7 @@ private: void positionDialogs(); FrameView* m_frameView; + IntSize m_frameViewSize; RawPtr m_selectionStart; RawPtr m_selectionEnd; diff --git a/sky/engine/core/rendering/SubtreeLayoutScope.cpp b/sky/engine/core/rendering/SubtreeLayoutScope.cpp index 37d2f6a13f4..46e3db31085 100644 --- a/sky/engine/core/rendering/SubtreeLayoutScope.cpp +++ b/sky/engine/core/rendering/SubtreeLayoutScope.cpp @@ -38,7 +38,7 @@ namespace blink { SubtreeLayoutScope::SubtreeLayoutScope(RenderObject& root) : m_root(root) { - RELEASE_ASSERT(m_root.document().view()->isInPerformLayout()); + RELEASE_ASSERT(!m_root.node() || m_root.document().view()->isInPerformLayout()); } SubtreeLayoutScope::~SubtreeLayoutScope() diff --git a/sky/engine/core/text/FontStyle.h b/sky/engine/core/text/FontStyle.h index ad9d38a675b..eb7ee015f9f 100644 --- a/sky/engine/core/text/FontStyle.h +++ b/sky/engine/core/text/FontStyle.h @@ -6,11 +6,10 @@ #define SKY_ENGINE_CORE_TEXT_FONTSTYLE_H_ #include "sky/engine/tonic/dart_converter.h" +#include "sky/engine/platform/fonts/FontTraits.h" namespace blink { -class FontStyle {}; - template <> struct DartConverter : public DartConverterEnum {}; diff --git a/sky/engine/core/text/FontWeight.h b/sky/engine/core/text/FontWeight.h index 81401652113..dd7810261df 100644 --- a/sky/engine/core/text/FontWeight.h +++ b/sky/engine/core/text/FontWeight.h @@ -6,11 +6,10 @@ #define SKY_ENGINE_CORE_TEXT_FONTWEIGHT_H_ #include "sky/engine/tonic/dart_converter.h" +#include "sky/engine/platform/fonts/FontTraits.h" namespace blink { -class FontWeight {}; - template <> struct DartConverter : public DartConverterEnum {}; diff --git a/sky/engine/core/text/Paragraph.cpp b/sky/engine/core/text/Paragraph.cpp index 268eb7c30fc..573f2bc7174 100644 --- a/sky/engine/core/text/Paragraph.cpp +++ b/sky/engine/core/text/Paragraph.cpp @@ -4,9 +4,12 @@ #include "sky/engine/core/text/ParagraphBuilder.h" +#include "sky/engine/core/rendering/style/RenderStyle.h" + namespace blink { -Paragraph::Paragraph() +Paragraph::Paragraph(PassOwnPtr renderView) + : m_renderView(renderView) { } @@ -16,12 +19,12 @@ Paragraph::~Paragraph() double Paragraph::width() { - return 0.0; + return m_renderView->firstChildBox()->width(); } double Paragraph::height() { - return 0.0; + return m_renderView->firstChildBox()->height(); } double Paragraph::minIntrinsicWidth() @@ -46,6 +49,12 @@ double Paragraph::ideographicBaseline() void Paragraph::layout() { + LayoutUnit maxWidth = std::max(m_minWidth, m_maxWidth); + LayoutUnit maxHeight = std::max(m_minHeight, m_maxHeight); + IntSize maxSize(maxWidth, maxHeight); + + m_renderView->setFrameViewSize(maxSize); + m_renderView->layout(); } void Paragraph::paint(Canvas* canvas, const Offset& offset) diff --git a/sky/engine/core/text/Paragraph.h b/sky/engine/core/text/Paragraph.h index c0a4fc8430b..cf64407e65d 100644 --- a/sky/engine/core/text/Paragraph.h +++ b/sky/engine/core/text/Paragraph.h @@ -10,29 +10,30 @@ #include "sky/engine/wtf/RefCounted.h" #include "sky/engine/core/painting/Canvas.h" #include "sky/engine/core/painting/Offset.h" +#include "sky/engine/core/rendering/RenderView.h" namespace blink { class Paragraph : public RefCounted, public DartWrappable { DEFINE_WRAPPERTYPEINFO(); public: - static PassRefPtr create() { - return adoptRef(new Paragraph()); + static PassRefPtr create(PassOwnPtr renderView) { + return adoptRef(new Paragraph(renderView)); } ~Paragraph() override; - double minWidth() const { return m_minWidth; } - void setMinWidth(double value) { m_minWidth = value; } + LayoutUnit minWidth() const { return m_minWidth; } + void setMinWidth(LayoutUnit width) { m_minWidth = width; } - double maxWidth() const { return m_maxWidth; } - void setMaxWidth(double value) { m_maxWidth = value; } + LayoutUnit maxWidth() const { return m_maxWidth; } + void setMaxWidth(LayoutUnit width) { m_maxWidth = width; } - double minHeight() const { return m_minHeight; } - void setMinHeight(double value) { m_minHeight = value; } + LayoutUnit minHeight() const { return m_minHeight; } + void setMinHeight(LayoutUnit height) { m_minHeight = height; } - double maxHeight() const { return m_maxHeight; } - void setMaxHeight(double value) { m_maxHeight = value; } + LayoutUnit maxHeight() const { return m_maxHeight; } + void setMaxHeight(LayoutUnit height) { m_maxHeight = height; } double width(); double height(); @@ -44,13 +45,17 @@ public: void layout(); void paint(Canvas* canvas, const Offset& offset); -private: - double m_minWidth; - double m_maxWidth; - double m_minHeight; - double m_maxHeight; + RenderView* renderView() const { return m_renderView.get(); } - explicit Paragraph(); +private: + LayoutUnit m_minWidth; + LayoutUnit m_maxWidth; + LayoutUnit m_minHeight; + LayoutUnit m_maxHeight; + + explicit Paragraph(PassOwnPtr renderView); + + OwnPtr m_renderView; }; } // namespace blink diff --git a/sky/engine/core/text/ParagraphBuilder.cpp b/sky/engine/core/text/ParagraphBuilder.cpp index c0dc32d676f..cb5ed169b80 100644 --- a/sky/engine/core/text/ParagraphBuilder.cpp +++ b/sky/engine/core/text/ParagraphBuilder.cpp @@ -4,10 +4,52 @@ #include "sky/engine/core/text/ParagraphBuilder.h" +#include "sky/engine/core/css/CSSFontSelector.h" +#include "sky/engine/core/css/resolver/FontBuilder.h" +#include "sky/engine/core/rendering/RenderParagraph.h" +#include "sky/engine/core/rendering/RenderText.h" +#include "sky/engine/core/rendering/style/RenderStyle.h" + namespace blink { +namespace { + +PassOwnPtr createRenderView() +{ + RefPtr style = RenderStyle::create(); + style->setRTLOrdering(LogicalOrder); + style->setZIndex(0); + style->setUserModify(READ_ONLY); + + FontBuilder fontBuilder; + fontBuilder.initForStyleResolve(nullptr, style.get()); + RefPtr selector = CSSFontSelector::create(nullptr); + fontBuilder.createFontForDocument(selector.release(), style.get()); + + OwnPtr renderView = adoptPtr(new RenderView(nullptr)); + renderView->setStyle(style.release()); + return renderView.release(); +} + +RenderParagraph* createRenderParagraph(RenderStyle* parentStyle) +{ + RefPtr style = RenderStyle::create(); + style->inheritFrom(parentStyle); + style->setDisplay(PARAGRAPH); + + RenderParagraph* renderParagraph = new RenderParagraph(nullptr); + renderParagraph->setStyle(style.release()); + return renderParagraph; +} + +} // namespace ParagraphBuilder::ParagraphBuilder() { + m_renderView = createRenderView(); + m_parentStyle = RenderStyle::clone(m_renderView->style()); + m_renderParagraph = createRenderParagraph(m_parentStyle.get()); + m_parentStyle = RenderStyle::clone(m_renderParagraph->style()); + m_renderView->addChild(m_renderParagraph); } ParagraphBuilder::~ParagraphBuilder() @@ -24,11 +66,18 @@ void ParagraphBuilder::pop() void ParagraphBuilder::addText(const String& text) { + RenderText* renderText = new RenderText(nullptr, text.impl()); + RefPtr style = RenderStyle::create(); + style->inheritFrom(m_parentStyle.get()); + renderText->setStyle(style.release()); + m_renderParagraph->addChild(renderText); } PassRefPtr ParagraphBuilder::build(ParagraphStyle* style) { - return nullptr; + m_parentStyle = nullptr; + m_renderParagraph = nullptr; + return Paragraph::create(m_renderView.release()); } } // namespace blink diff --git a/sky/engine/core/text/ParagraphBuilder.h b/sky/engine/core/text/ParagraphBuilder.h index 4eaa86f790f..16628a558a3 100644 --- a/sky/engine/core/text/ParagraphBuilder.h +++ b/sky/engine/core/text/ParagraphBuilder.h @@ -32,6 +32,11 @@ public: private: explicit ParagraphBuilder(); + + OwnPtr m_renderView; + + RefPtr m_parentStyle; + RenderParagraph* m_renderParagraph; }; } // namespace blink diff --git a/sky/engine/core/text/TextAlign.h b/sky/engine/core/text/TextAlign.h index c1edb154420..637bc821d26 100644 --- a/sky/engine/core/text/TextAlign.h +++ b/sky/engine/core/text/TextAlign.h @@ -6,11 +6,10 @@ #define SKY_ENGINE_CORE_TEXT_TEXTALIGN_H_ #include "sky/engine/tonic/dart_converter.h" +#include "sky/engine/platform/graphics/GraphicsTypes.h" namespace blink { -class TextAlign {}; - template <> struct DartConverter : public DartConverterEnum {}; diff --git a/sky/engine/core/text/TextBaseline.h b/sky/engine/core/text/TextBaseline.h index 2e8040b6429..2f67b6c4ef4 100644 --- a/sky/engine/core/text/TextBaseline.h +++ b/sky/engine/core/text/TextBaseline.h @@ -6,11 +6,10 @@ #define SKY_ENGINE_CORE_TEXT_TEXTBASELINE_H_ #include "sky/engine/tonic/dart_converter.h" +#include "sky/engine/platform/graphics/GraphicsTypes.h" namespace blink { -class TextBaseline {}; - template <> struct DartConverter : public DartConverterEnum {}; diff --git a/sky/unit/test/engine/paragraph_builder_test_disabled.dart b/sky/unit/test/engine/paragraph_builder_test_disabled.dart new file mode 100644 index 00000000000..4e7d53b97dd --- /dev/null +++ b/sky/unit/test/engine/paragraph_builder_test_disabled.dart @@ -0,0 +1,13 @@ +import 'dart:sky'; + +import 'package:test/test.dart'; + +void main() { + test("Should be able to build and layout a paragraph", () { + ParagraphBuilder builder = new ParagraphBuilder(); + builder.addText('Hello'); + Paragraph paragraph = builder.build(new ParagraphStyle()); + expect(paragraph, isNotNull); + paragraph.layout(); + }); +}