[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677
hyatt
hyatt at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 06:59:12 UTC 2009
The following commit has been merged in the debian/unstable branch:
commit 33f8d493f350dc23213996921ca2efdb08dfa0d9
Author: hyatt <hyatt at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Tue Nov 12 21:44:52 2002 +0000
This patch lands a rewrite of whitespace-handling in the
layout engine and adds support for the CSS2 white-space
property.
It also includes a rewrite of inlines' min/max width
calculations (for both flow inlines and raw text).
A problem with <form> margins has been fixed (this is a
regression I caused with my collapsing margin checkin).
* WebCore.pbproj/project.pbxproj:
* khtml/css/html4.css:
* khtml/html/dtd.cpp:
(DOM::checkChild):
* khtml/html/html_baseimpl.cpp:
(HTMLBodyElementImpl::attach):
(HTMLFrameElementImpl::attach):
(HTMLFrameSetElementImpl::attach):
(HTMLHtmlElementImpl::attach):
(HTMLIFrameElementImpl::attach):
* khtml/html/html_formimpl.cpp:
(HTMLFormElementImpl::HTMLFormElementImpl):
(HTMLInputElementImpl::attach):
(HTMLSelectElementImpl::attach):
(HTMLTextAreaElementImpl::attach):
* khtml/html/html_formimpl.h:
* khtml/html/html_imageimpl.cpp:
(HTMLImageElementImpl::attach):
* khtml/html/html_inlineimpl.cpp:
(HTMLBRElementImpl::attach):
* khtml/html/html_objectimpl.cpp:
(HTMLAppletElementImpl::attach):
(HTMLEmbedElementImpl::attach):
(HTMLObjectElementImpl::attach):
* khtml/html/htmlparser.cpp:
(KHTMLParser::reset):
(KHTMLParser::parseToken):
(KHTMLParser::insertNode):
(KHTMLParser::popBlock):
(KHTMLParser::popOneBlock):
* khtml/html/htmlparser.h:
* khtml/html/htmltokenizer.cpp:
(HTMLTokenizer::addPending):
(HTMLTokenizer::write):
* khtml/misc/arena.cpp: Added.
(CeilingLog2):
(InitArenaPool):
(ArenaAllocate):
(ArenaGrow):
(FreeArenaList):
(ArenaRelease):
(FreeArenaPool):
(FinishArenaPool):
(ArenaFinish):
* khtml/misc/arena.h: Added.
* khtml/rendering/bidi.cpp:
(BidiIterator::detach):
(throw):
(BidiIterator::operator delete):
(appendRunsForObject):
(appendRun):
(RenderFlow::bidiReorderLine):
(deleteMidpoints):
(RenderFlow::layoutInlineChildren):
(RenderFlow::findNextLineBreak):
* khtml/rendering/bidi.h:
* khtml/rendering/render_arena.cpp: Added.
(RenderArena::RenderArena):
(RenderArena::~RenderArena):
(RenderArena::allocate):
(RenderArena::free):
* khtml/rendering/render_arena.h: Added.
* khtml/rendering/render_box.cpp:
(RenderBox::setStyle):
(RenderBox::~RenderBox):
(RenderBox::detach):
* khtml/rendering/render_box.h:
* khtml/rendering/render_br.cpp:
(RenderBR::RenderBR):
* khtml/rendering/render_container.cpp:
(RenderContainer::~RenderContainer):
(RenderContainer::detach):
* khtml/rendering/render_container.h:
* khtml/rendering/render_flow.cpp:
(RenderFlow::setStyle):
(RenderFlow::layout):
(RenderFlow::calcInlineMinMaxWidth):
(RenderFlow::calcBlockMinMaxWidth):
(RenderFlow::calcMinMaxWidth):
(RenderFlow::addChild):
(RenderFlow::makeChildrenNonInline):
* khtml/rendering/render_flow.h:
* khtml/rendering/render_html.cpp:
(RenderHtml::RenderHtml):
* khtml/rendering/render_layer.cpp:
(RenderLayer::~RenderLayer):
(throw):
(RenderLayer::operator delete):
(RenderLayer::detach):
(RenderLayer::paint):
(RenderLayer::nodeAtPoint):
(RenderLayer::constructZTree):
(RenderLayer::RenderLayerElement::operator delete):
(RenderLayer::RenderLayerElement::detach):
(RenderLayer::RenderZTreeNode::operator delete):
(RenderLayer::RenderZTreeNode::detach):
* khtml/rendering/render_layer.h:
* khtml/rendering/render_list.cpp:
(RenderListItem::setStyle):
* khtml/rendering/render_object.cpp:
(throw):
(RenderObject::operator delete):
(RenderObject::createObject):
(RenderObject::renderArena):
(RenderObject::detach):
* khtml/rendering/render_object.h:
* khtml/rendering/render_replaced.cpp:
(RenderWidget::detach):
* khtml/rendering/render_replaced.h:
* khtml/rendering/render_root.cpp:
(RenderRoot::RenderRoot):
* khtml/rendering/render_table.cpp:
(RenderTable::addChild):
(RenderTable::calcWidth):
(RenderTable::setCellWidths):
(RenderTableSection::addChild):
(RenderTableRow::addChild):
* khtml/rendering/render_text.cpp:
(TextSlave::detach):
(throw):
(TextSlave::operator delete):
(TextSlaveArray::TextSlaveArray):
(RenderText::RenderText):
(RenderText::~RenderText):
(RenderText::detach):
(RenderText::deleteSlaves):
(RenderText::trimmedMinMaxWidth):
(RenderText::calcMinMaxWidth):
(RenderText::position):
* khtml/rendering/render_text.h:
* khtml/xml/dom_docimpl.cpp:
(DocumentImpl::DocumentImpl):
(DocumentImpl::~DocumentImpl):
(DocumentImpl::attach):
(DocumentImpl::detach):
* khtml/xml/dom_docimpl.h:
* khtml/xml/dom_nodeimpl.cpp:
(NodeImpl::detach):
(NodeImpl::isReadOnly):
(NodeImpl::previousRenderer):
* khtml/xml/dom_nodeimpl.h:
* khtml/xml/dom_stringimpl.cpp:
* khtml/xml/dom_stringimpl.h:
* khtml/xml/dom_textimpl.cpp:
(CharacterDataImpl::containsOnlyWhitespace):
(TextImpl::attach):
* khtml/xml/dom_textimpl.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2635 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog-2002-12-03 b/WebCore/ChangeLog-2002-12-03
index 47e20bd..247d964 100644
--- a/WebCore/ChangeLog-2002-12-03
+++ b/WebCore/ChangeLog-2002-12-03
@@ -1,3 +1,163 @@
+2002-11-12 David Hyatt <hyatt at apple.com>
+
+ This patch lands a rewrite of whitespace-handling in the
+ layout engine and adds support for the CSS2 white-space
+ property.
+
+ It also includes a rewrite of inlines' min/max width
+ calculations (for both flow inlines and raw text).
+
+ A problem with <form> margins has been fixed (this is a
+ regression I caused with my collapsing margin checkin).
+
+ * WebCore.pbproj/project.pbxproj:
+ * khtml/css/html4.css:
+ * khtml/html/dtd.cpp:
+ (DOM::checkChild):
+ * khtml/html/html_baseimpl.cpp:
+ (HTMLBodyElementImpl::attach):
+ (HTMLFrameElementImpl::attach):
+ (HTMLFrameSetElementImpl::attach):
+ (HTMLHtmlElementImpl::attach):
+ (HTMLIFrameElementImpl::attach):
+ * khtml/html/html_formimpl.cpp:
+ (HTMLFormElementImpl::HTMLFormElementImpl):
+ (HTMLInputElementImpl::attach):
+ (HTMLSelectElementImpl::attach):
+ (HTMLTextAreaElementImpl::attach):
+ * khtml/html/html_formimpl.h:
+ * khtml/html/html_imageimpl.cpp:
+ (HTMLImageElementImpl::attach):
+ * khtml/html/html_inlineimpl.cpp:
+ (HTMLBRElementImpl::attach):
+ * khtml/html/html_objectimpl.cpp:
+ (HTMLAppletElementImpl::attach):
+ (HTMLEmbedElementImpl::attach):
+ (HTMLObjectElementImpl::attach):
+ * khtml/html/htmlparser.cpp:
+ (KHTMLParser::reset):
+ (KHTMLParser::parseToken):
+ (KHTMLParser::insertNode):
+ (KHTMLParser::popBlock):
+ (KHTMLParser::popOneBlock):
+ * khtml/html/htmlparser.h:
+ * khtml/html/htmltokenizer.cpp:
+ (HTMLTokenizer::addPending):
+ (HTMLTokenizer::write):
+ * khtml/misc/arena.cpp: Added.
+ (CeilingLog2):
+ (InitArenaPool):
+ (ArenaAllocate):
+ (ArenaGrow):
+ (FreeArenaList):
+ (ArenaRelease):
+ (FreeArenaPool):
+ (FinishArenaPool):
+ (ArenaFinish):
+ * khtml/misc/arena.h: Added.
+ * khtml/rendering/bidi.cpp:
+ (BidiIterator::detach):
+ (throw):
+ (BidiIterator::operator delete):
+ (appendRunsForObject):
+ (appendRun):
+ (RenderFlow::bidiReorderLine):
+ (deleteMidpoints):
+ (RenderFlow::layoutInlineChildren):
+ (RenderFlow::findNextLineBreak):
+ * khtml/rendering/bidi.h:
+ * khtml/rendering/render_arena.cpp: Added.
+ (RenderArena::RenderArena):
+ (RenderArena::~RenderArena):
+ (RenderArena::allocate):
+ (RenderArena::free):
+ * khtml/rendering/render_arena.h: Added.
+ * khtml/rendering/render_box.cpp:
+ (RenderBox::setStyle):
+ (RenderBox::~RenderBox):
+ (RenderBox::detach):
+ * khtml/rendering/render_box.h:
+ * khtml/rendering/render_br.cpp:
+ (RenderBR::RenderBR):
+ * khtml/rendering/render_container.cpp:
+ (RenderContainer::~RenderContainer):
+ (RenderContainer::detach):
+ * khtml/rendering/render_container.h:
+ * khtml/rendering/render_flow.cpp:
+ (RenderFlow::setStyle):
+ (RenderFlow::layout):
+ (RenderFlow::calcInlineMinMaxWidth):
+ (RenderFlow::calcBlockMinMaxWidth):
+ (RenderFlow::calcMinMaxWidth):
+ (RenderFlow::addChild):
+ (RenderFlow::makeChildrenNonInline):
+ * khtml/rendering/render_flow.h:
+ * khtml/rendering/render_html.cpp:
+ (RenderHtml::RenderHtml):
+ * khtml/rendering/render_layer.cpp:
+ (RenderLayer::~RenderLayer):
+ (throw):
+ (RenderLayer::operator delete):
+ (RenderLayer::detach):
+ (RenderLayer::paint):
+ (RenderLayer::nodeAtPoint):
+ (RenderLayer::constructZTree):
+ (RenderLayer::RenderLayerElement::operator delete):
+ (RenderLayer::RenderLayerElement::detach):
+ (RenderLayer::RenderZTreeNode::operator delete):
+ (RenderLayer::RenderZTreeNode::detach):
+ * khtml/rendering/render_layer.h:
+ * khtml/rendering/render_list.cpp:
+ (RenderListItem::setStyle):
+ * khtml/rendering/render_object.cpp:
+ (throw):
+ (RenderObject::operator delete):
+ (RenderObject::createObject):
+ (RenderObject::renderArena):
+ (RenderObject::detach):
+ * khtml/rendering/render_object.h:
+ * khtml/rendering/render_replaced.cpp:
+ (RenderWidget::detach):
+ * khtml/rendering/render_replaced.h:
+ * khtml/rendering/render_root.cpp:
+ (RenderRoot::RenderRoot):
+ * khtml/rendering/render_table.cpp:
+ (RenderTable::addChild):
+ (RenderTable::calcWidth):
+ (RenderTable::setCellWidths):
+ (RenderTableSection::addChild):
+ (RenderTableRow::addChild):
+ * khtml/rendering/render_text.cpp:
+ (TextSlave::detach):
+ (throw):
+ (TextSlave::operator delete):
+ (TextSlaveArray::TextSlaveArray):
+ (RenderText::RenderText):
+ (RenderText::~RenderText):
+ (RenderText::detach):
+ (RenderText::deleteSlaves):
+ (RenderText::trimmedMinMaxWidth):
+ (RenderText::calcMinMaxWidth):
+ (RenderText::position):
+ * khtml/rendering/render_text.h:
+ * khtml/xml/dom_docimpl.cpp:
+ (DocumentImpl::DocumentImpl):
+ (DocumentImpl::~DocumentImpl):
+ (DocumentImpl::attach):
+ (DocumentImpl::detach):
+ * khtml/xml/dom_docimpl.h:
+ * khtml/xml/dom_nodeimpl.cpp:
+ (NodeImpl::detach):
+ (NodeImpl::isReadOnly):
+ (NodeImpl::previousRenderer):
+ * khtml/xml/dom_nodeimpl.h:
+ * khtml/xml/dom_stringimpl.cpp:
+ * khtml/xml/dom_stringimpl.h:
+ * khtml/xml/dom_textimpl.cpp:
+ (CharacterDataImpl::containsOnlyWhitespace):
+ (TextImpl::attach):
+ * khtml/xml/dom_textimpl.h:
+
2002-11-12 Darin Adler <darin at apple.com>
- fixed 3094819 -- Crash in -[KWQObjectTimerTarget timerFired]
diff --git a/WebCore/ChangeLog-2003-10-25 b/WebCore/ChangeLog-2003-10-25
index 47e20bd..247d964 100644
--- a/WebCore/ChangeLog-2003-10-25
+++ b/WebCore/ChangeLog-2003-10-25
@@ -1,3 +1,163 @@
+2002-11-12 David Hyatt <hyatt at apple.com>
+
+ This patch lands a rewrite of whitespace-handling in the
+ layout engine and adds support for the CSS2 white-space
+ property.
+
+ It also includes a rewrite of inlines' min/max width
+ calculations (for both flow inlines and raw text).
+
+ A problem with <form> margins has been fixed (this is a
+ regression I caused with my collapsing margin checkin).
+
+ * WebCore.pbproj/project.pbxproj:
+ * khtml/css/html4.css:
+ * khtml/html/dtd.cpp:
+ (DOM::checkChild):
+ * khtml/html/html_baseimpl.cpp:
+ (HTMLBodyElementImpl::attach):
+ (HTMLFrameElementImpl::attach):
+ (HTMLFrameSetElementImpl::attach):
+ (HTMLHtmlElementImpl::attach):
+ (HTMLIFrameElementImpl::attach):
+ * khtml/html/html_formimpl.cpp:
+ (HTMLFormElementImpl::HTMLFormElementImpl):
+ (HTMLInputElementImpl::attach):
+ (HTMLSelectElementImpl::attach):
+ (HTMLTextAreaElementImpl::attach):
+ * khtml/html/html_formimpl.h:
+ * khtml/html/html_imageimpl.cpp:
+ (HTMLImageElementImpl::attach):
+ * khtml/html/html_inlineimpl.cpp:
+ (HTMLBRElementImpl::attach):
+ * khtml/html/html_objectimpl.cpp:
+ (HTMLAppletElementImpl::attach):
+ (HTMLEmbedElementImpl::attach):
+ (HTMLObjectElementImpl::attach):
+ * khtml/html/htmlparser.cpp:
+ (KHTMLParser::reset):
+ (KHTMLParser::parseToken):
+ (KHTMLParser::insertNode):
+ (KHTMLParser::popBlock):
+ (KHTMLParser::popOneBlock):
+ * khtml/html/htmlparser.h:
+ * khtml/html/htmltokenizer.cpp:
+ (HTMLTokenizer::addPending):
+ (HTMLTokenizer::write):
+ * khtml/misc/arena.cpp: Added.
+ (CeilingLog2):
+ (InitArenaPool):
+ (ArenaAllocate):
+ (ArenaGrow):
+ (FreeArenaList):
+ (ArenaRelease):
+ (FreeArenaPool):
+ (FinishArenaPool):
+ (ArenaFinish):
+ * khtml/misc/arena.h: Added.
+ * khtml/rendering/bidi.cpp:
+ (BidiIterator::detach):
+ (throw):
+ (BidiIterator::operator delete):
+ (appendRunsForObject):
+ (appendRun):
+ (RenderFlow::bidiReorderLine):
+ (deleteMidpoints):
+ (RenderFlow::layoutInlineChildren):
+ (RenderFlow::findNextLineBreak):
+ * khtml/rendering/bidi.h:
+ * khtml/rendering/render_arena.cpp: Added.
+ (RenderArena::RenderArena):
+ (RenderArena::~RenderArena):
+ (RenderArena::allocate):
+ (RenderArena::free):
+ * khtml/rendering/render_arena.h: Added.
+ * khtml/rendering/render_box.cpp:
+ (RenderBox::setStyle):
+ (RenderBox::~RenderBox):
+ (RenderBox::detach):
+ * khtml/rendering/render_box.h:
+ * khtml/rendering/render_br.cpp:
+ (RenderBR::RenderBR):
+ * khtml/rendering/render_container.cpp:
+ (RenderContainer::~RenderContainer):
+ (RenderContainer::detach):
+ * khtml/rendering/render_container.h:
+ * khtml/rendering/render_flow.cpp:
+ (RenderFlow::setStyle):
+ (RenderFlow::layout):
+ (RenderFlow::calcInlineMinMaxWidth):
+ (RenderFlow::calcBlockMinMaxWidth):
+ (RenderFlow::calcMinMaxWidth):
+ (RenderFlow::addChild):
+ (RenderFlow::makeChildrenNonInline):
+ * khtml/rendering/render_flow.h:
+ * khtml/rendering/render_html.cpp:
+ (RenderHtml::RenderHtml):
+ * khtml/rendering/render_layer.cpp:
+ (RenderLayer::~RenderLayer):
+ (throw):
+ (RenderLayer::operator delete):
+ (RenderLayer::detach):
+ (RenderLayer::paint):
+ (RenderLayer::nodeAtPoint):
+ (RenderLayer::constructZTree):
+ (RenderLayer::RenderLayerElement::operator delete):
+ (RenderLayer::RenderLayerElement::detach):
+ (RenderLayer::RenderZTreeNode::operator delete):
+ (RenderLayer::RenderZTreeNode::detach):
+ * khtml/rendering/render_layer.h:
+ * khtml/rendering/render_list.cpp:
+ (RenderListItem::setStyle):
+ * khtml/rendering/render_object.cpp:
+ (throw):
+ (RenderObject::operator delete):
+ (RenderObject::createObject):
+ (RenderObject::renderArena):
+ (RenderObject::detach):
+ * khtml/rendering/render_object.h:
+ * khtml/rendering/render_replaced.cpp:
+ (RenderWidget::detach):
+ * khtml/rendering/render_replaced.h:
+ * khtml/rendering/render_root.cpp:
+ (RenderRoot::RenderRoot):
+ * khtml/rendering/render_table.cpp:
+ (RenderTable::addChild):
+ (RenderTable::calcWidth):
+ (RenderTable::setCellWidths):
+ (RenderTableSection::addChild):
+ (RenderTableRow::addChild):
+ * khtml/rendering/render_text.cpp:
+ (TextSlave::detach):
+ (throw):
+ (TextSlave::operator delete):
+ (TextSlaveArray::TextSlaveArray):
+ (RenderText::RenderText):
+ (RenderText::~RenderText):
+ (RenderText::detach):
+ (RenderText::deleteSlaves):
+ (RenderText::trimmedMinMaxWidth):
+ (RenderText::calcMinMaxWidth):
+ (RenderText::position):
+ * khtml/rendering/render_text.h:
+ * khtml/xml/dom_docimpl.cpp:
+ (DocumentImpl::DocumentImpl):
+ (DocumentImpl::~DocumentImpl):
+ (DocumentImpl::attach):
+ (DocumentImpl::detach):
+ * khtml/xml/dom_docimpl.h:
+ * khtml/xml/dom_nodeimpl.cpp:
+ (NodeImpl::detach):
+ (NodeImpl::isReadOnly):
+ (NodeImpl::previousRenderer):
+ * khtml/xml/dom_nodeimpl.h:
+ * khtml/xml/dom_stringimpl.cpp:
+ * khtml/xml/dom_stringimpl.h:
+ * khtml/xml/dom_textimpl.cpp:
+ (CharacterDataImpl::containsOnlyWhitespace):
+ (TextImpl::attach):
+ * khtml/xml/dom_textimpl.h:
+
2002-11-12 Darin Adler <darin at apple.com>
- fixed 3094819 -- Crash in -[KWQObjectTimerTarget timerFired]
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 47e20bd..247d964 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,163 @@
+2002-11-12 David Hyatt <hyatt at apple.com>
+
+ This patch lands a rewrite of whitespace-handling in the
+ layout engine and adds support for the CSS2 white-space
+ property.
+
+ It also includes a rewrite of inlines' min/max width
+ calculations (for both flow inlines and raw text).
+
+ A problem with <form> margins has been fixed (this is a
+ regression I caused with my collapsing margin checkin).
+
+ * WebCore.pbproj/project.pbxproj:
+ * khtml/css/html4.css:
+ * khtml/html/dtd.cpp:
+ (DOM::checkChild):
+ * khtml/html/html_baseimpl.cpp:
+ (HTMLBodyElementImpl::attach):
+ (HTMLFrameElementImpl::attach):
+ (HTMLFrameSetElementImpl::attach):
+ (HTMLHtmlElementImpl::attach):
+ (HTMLIFrameElementImpl::attach):
+ * khtml/html/html_formimpl.cpp:
+ (HTMLFormElementImpl::HTMLFormElementImpl):
+ (HTMLInputElementImpl::attach):
+ (HTMLSelectElementImpl::attach):
+ (HTMLTextAreaElementImpl::attach):
+ * khtml/html/html_formimpl.h:
+ * khtml/html/html_imageimpl.cpp:
+ (HTMLImageElementImpl::attach):
+ * khtml/html/html_inlineimpl.cpp:
+ (HTMLBRElementImpl::attach):
+ * khtml/html/html_objectimpl.cpp:
+ (HTMLAppletElementImpl::attach):
+ (HTMLEmbedElementImpl::attach):
+ (HTMLObjectElementImpl::attach):
+ * khtml/html/htmlparser.cpp:
+ (KHTMLParser::reset):
+ (KHTMLParser::parseToken):
+ (KHTMLParser::insertNode):
+ (KHTMLParser::popBlock):
+ (KHTMLParser::popOneBlock):
+ * khtml/html/htmlparser.h:
+ * khtml/html/htmltokenizer.cpp:
+ (HTMLTokenizer::addPending):
+ (HTMLTokenizer::write):
+ * khtml/misc/arena.cpp: Added.
+ (CeilingLog2):
+ (InitArenaPool):
+ (ArenaAllocate):
+ (ArenaGrow):
+ (FreeArenaList):
+ (ArenaRelease):
+ (FreeArenaPool):
+ (FinishArenaPool):
+ (ArenaFinish):
+ * khtml/misc/arena.h: Added.
+ * khtml/rendering/bidi.cpp:
+ (BidiIterator::detach):
+ (throw):
+ (BidiIterator::operator delete):
+ (appendRunsForObject):
+ (appendRun):
+ (RenderFlow::bidiReorderLine):
+ (deleteMidpoints):
+ (RenderFlow::layoutInlineChildren):
+ (RenderFlow::findNextLineBreak):
+ * khtml/rendering/bidi.h:
+ * khtml/rendering/render_arena.cpp: Added.
+ (RenderArena::RenderArena):
+ (RenderArena::~RenderArena):
+ (RenderArena::allocate):
+ (RenderArena::free):
+ * khtml/rendering/render_arena.h: Added.
+ * khtml/rendering/render_box.cpp:
+ (RenderBox::setStyle):
+ (RenderBox::~RenderBox):
+ (RenderBox::detach):
+ * khtml/rendering/render_box.h:
+ * khtml/rendering/render_br.cpp:
+ (RenderBR::RenderBR):
+ * khtml/rendering/render_container.cpp:
+ (RenderContainer::~RenderContainer):
+ (RenderContainer::detach):
+ * khtml/rendering/render_container.h:
+ * khtml/rendering/render_flow.cpp:
+ (RenderFlow::setStyle):
+ (RenderFlow::layout):
+ (RenderFlow::calcInlineMinMaxWidth):
+ (RenderFlow::calcBlockMinMaxWidth):
+ (RenderFlow::calcMinMaxWidth):
+ (RenderFlow::addChild):
+ (RenderFlow::makeChildrenNonInline):
+ * khtml/rendering/render_flow.h:
+ * khtml/rendering/render_html.cpp:
+ (RenderHtml::RenderHtml):
+ * khtml/rendering/render_layer.cpp:
+ (RenderLayer::~RenderLayer):
+ (throw):
+ (RenderLayer::operator delete):
+ (RenderLayer::detach):
+ (RenderLayer::paint):
+ (RenderLayer::nodeAtPoint):
+ (RenderLayer::constructZTree):
+ (RenderLayer::RenderLayerElement::operator delete):
+ (RenderLayer::RenderLayerElement::detach):
+ (RenderLayer::RenderZTreeNode::operator delete):
+ (RenderLayer::RenderZTreeNode::detach):
+ * khtml/rendering/render_layer.h:
+ * khtml/rendering/render_list.cpp:
+ (RenderListItem::setStyle):
+ * khtml/rendering/render_object.cpp:
+ (throw):
+ (RenderObject::operator delete):
+ (RenderObject::createObject):
+ (RenderObject::renderArena):
+ (RenderObject::detach):
+ * khtml/rendering/render_object.h:
+ * khtml/rendering/render_replaced.cpp:
+ (RenderWidget::detach):
+ * khtml/rendering/render_replaced.h:
+ * khtml/rendering/render_root.cpp:
+ (RenderRoot::RenderRoot):
+ * khtml/rendering/render_table.cpp:
+ (RenderTable::addChild):
+ (RenderTable::calcWidth):
+ (RenderTable::setCellWidths):
+ (RenderTableSection::addChild):
+ (RenderTableRow::addChild):
+ * khtml/rendering/render_text.cpp:
+ (TextSlave::detach):
+ (throw):
+ (TextSlave::operator delete):
+ (TextSlaveArray::TextSlaveArray):
+ (RenderText::RenderText):
+ (RenderText::~RenderText):
+ (RenderText::detach):
+ (RenderText::deleteSlaves):
+ (RenderText::trimmedMinMaxWidth):
+ (RenderText::calcMinMaxWidth):
+ (RenderText::position):
+ * khtml/rendering/render_text.h:
+ * khtml/xml/dom_docimpl.cpp:
+ (DocumentImpl::DocumentImpl):
+ (DocumentImpl::~DocumentImpl):
+ (DocumentImpl::attach):
+ (DocumentImpl::detach):
+ * khtml/xml/dom_docimpl.h:
+ * khtml/xml/dom_nodeimpl.cpp:
+ (NodeImpl::detach):
+ (NodeImpl::isReadOnly):
+ (NodeImpl::previousRenderer):
+ * khtml/xml/dom_nodeimpl.h:
+ * khtml/xml/dom_stringimpl.cpp:
+ * khtml/xml/dom_stringimpl.h:
+ * khtml/xml/dom_textimpl.cpp:
+ (CharacterDataImpl::containsOnlyWhitespace):
+ (TextImpl::attach):
+ * khtml/xml/dom_textimpl.h:
+
2002-11-12 Darin Adler <darin at apple.com>
- fixed 3094819 -- Crash in -[KWQObjectTimerTarget timerFired]
diff --git a/WebCore/WebCore.pbproj/project.pbxproj b/WebCore/WebCore.pbproj/project.pbxproj
index fec0c5d..2d604e9 100644
--- a/WebCore/WebCore.pbproj/project.pbxproj
+++ b/WebCore/WebCore.pbproj/project.pbxproj
@@ -473,6 +473,8 @@
93386B92037045B3008635CE,
517FA6B30370BD6100CA2D3A,
931C8A180380288B008635CE,
+ BC7294FA03804B3C00A80166,
+ BC7294FE03804B5600A80166,
);
isa = PBXHeadersBuildPhase;
runOnlyForDeploymentPostprocessing = 0;
@@ -705,6 +707,8 @@
93386B93037045B3008635CE,
517FA6B70370C7ED00CA2D3A,
931C8A190380288B008635CE,
+ BC7294F903804B3C00A80166,
+ BC7294FD03804B5600A80166,
);
isa = PBXSourcesBuildPhase;
runOnlyForDeploymentPostprocessing = 0;
@@ -981,6 +985,64 @@
//932
//933
//934
+//BC0
+//BC1
+//BC2
+//BC3
+//BC4
+ BC7294F703804B3C00A80166 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ path = arena.cpp;
+ refType = 4;
+ };
+ BC7294F803804B3C00A80166 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ path = arena.h;
+ refType = 4;
+ };
+ BC7294F903804B3C00A80166 = {
+ fileRef = BC7294F703804B3C00A80166;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ BC7294FA03804B3C00A80166 = {
+ fileRef = BC7294F803804B3C00A80166;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ BC7294FB03804B5600A80166 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ path = render_arena.cpp;
+ refType = 4;
+ };
+ BC7294FC03804B5600A80166 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ path = render_arena.h;
+ refType = 4;
+ };
+ BC7294FD03804B5600A80166 = {
+ fileRef = BC7294FB03804B5600A80166;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ BC7294FE03804B5600A80166 = {
+ fileRef = BC7294FC03804B5600A80166;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+//BC0
+//BC1
+//BC2
+//BC3
+//BC4
//F50
//F51
//F52
@@ -3149,6 +3211,8 @@
F523D28702DE43D7018635CA,
F523D28802DE43D7018635CA,
F523D28902DE43D7018635CA,
+ BC7294F703804B3C00A80166,
+ BC7294F803804B3C00A80166,
);
isa = PBXGroup;
path = misc;
@@ -3699,6 +3763,8 @@
F523D2C402DE4438018635CA,
F523D2C702DE4438018635CA,
F523D2C602DE4438018635CA,
+ BC7294FB03804B5600A80166,
+ BC7294FC03804B5600A80166,
);
isa = PBXGroup;
path = rendering;
diff --git a/WebCore/khtml/css/html4.css b/WebCore/khtml/css/html4.css
index 3fc497b..2d1b85a 100644
--- a/WebCore/khtml/css/html4.css
+++ b/WebCore/khtml/css/html4.css
@@ -54,7 +54,7 @@ script {
@media screen {
body {
display: block;
- margin: 10px;
+ margin: 8px;
}
}
@@ -353,16 +353,6 @@ OL OL {
margin-bottom: auto;
}
-LI > P {
- margin-top: auto;
- margin-bottom: auto;
-}
-
-LI > DIV {
- margin-top: auto;
- margin-bottom: auto;
-}
-
/*
* form elements
*/
@@ -397,6 +387,10 @@ INPUT, TEXTAREA {
margin: 3px;
}
+input[type="image"] {
+ margin: 0px;
+}
+
INPUT[type="hidden"] {
display: none;
}
diff --git a/WebCore/khtml/html/dtd.cpp b/WebCore/khtml/html/dtd.cpp
index 671f784..fdf7e8d 100644
--- a/WebCore/khtml/html/dtd.cpp
+++ b/WebCore/khtml/html/dtd.cpp
@@ -308,6 +308,7 @@ static const ushort tag_list_0[] = {
};
static const ushort tag_list_1[] = {
+ ID_TEXT,
ID_P,
ID_H1,
ID_H2,
@@ -334,7 +335,6 @@ static const ushort tag_list_1[] = {
ID_TABLE,
ID_FIELDSET,
ID_ADDRESS,
- ID_TEXT,
ID_TT,
ID_I,
ID_B,
@@ -393,6 +393,7 @@ static const ushort tag_list_2[] = {
};
static const ushort tag_list_3[] = {
+ ID_TEXT,
ID_P,
ID_H1,
ID_H2,
@@ -428,6 +429,7 @@ static const ushort tag_list_3[] = {
};
static const ushort tag_list_4[] = {
+ ID_TEXT,
ID_PARAM,
ID_P,
ID_H1,
@@ -503,6 +505,7 @@ static const ushort tag_list_4[] = {
};
static const ushort tag_list_6[] = {
+ ID_TEXT,
ID_DT,
ID_DD,
ID_COMMENT,
@@ -510,6 +513,7 @@ static const ushort tag_list_6[] = {
};
static const ushort tag_list_7[] = {
+ ID_TEXT,
ID_OPTGROUP,
ID_OPTION,
ID_COMMENT,
@@ -532,6 +536,7 @@ static const ushort tag_list_10[] = {
};
static const ushort tag_list_11[] = {
+ ID_TEXT,
ID_SCRIPT,
ID_STYLE,
ID_META,
@@ -726,6 +731,8 @@ bool DOM::checkChild(ushort tagID, ushort childID)
case ID_THEAD:
case ID_TFOOT:
case ID_TBODY:
+ case ID_TEXT:
+ case ID_COMMENT:
return true;
default:
return false;
@@ -734,11 +741,11 @@ bool DOM::checkChild(ushort tagID, ushort childID)
case ID_TFOOT:
case ID_TBODY:
// THEAD: TR +
- if(childID == ID_TR) return true;
+ if(childID == ID_TR || childID == ID_TEXT || childID == ID_COMMENT) return true;
return false;
case ID_COLGROUP:
// COLGROUP: COL *
- if(childID == ID_COL) return true;
+ if(childID == ID_COL || childID == ID_TEXT || childID == ID_COMMENT) return true;
return false;
case ID_TR:
// TR: _9 +
diff --git a/WebCore/khtml/html/html_baseimpl.cpp b/WebCore/khtml/html/html_baseimpl.cpp
index ba9484d..a7be8c5 100644
--- a/WebCore/khtml/html/html_baseimpl.cpp
+++ b/WebCore/khtml/html/html_baseimpl.cpp
@@ -193,7 +193,7 @@ void HTMLBodyElementImpl::attach()
RenderStyle* style = getDocument()->styleSelector()->styleForElement(this);
style->ref();
if (style->display() != NONE) {
- m_render = new RenderBody(this);
+ m_render = new (getDocument()->renderArena()) RenderBody(this);
m_render->setStyle(style);
parentNode()->renderer()->addChild(m_render, nextRenderer());
}
@@ -311,7 +311,7 @@ void HTMLFrameElementImpl::attach()
}
if (!selfreference) {
- m_render = new RenderFrame(this);
+ m_render = new (getDocument()->renderArena()) RenderFrame(this);
m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
parentNode()->renderer()->addChild(m_render, nextRenderer());
}
@@ -477,7 +477,7 @@ void HTMLFrameSetElementImpl::attach()
assert(parentNode()->renderer());
// ignore display: none
- m_render = new RenderFrameSet(this);
+ m_render = new (getDocument()->renderArena()) RenderFrameSet(this);
m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
parentNode()->renderer()->addChild(m_render, nextRenderer());
@@ -535,7 +535,7 @@ void HTMLHtmlElementImpl::attach()
assert(parentNode());
assert(parentNode()->renderer());
- m_render = new RenderHtml(this);
+ m_render = new (getDocument()->renderArena()) RenderHtml(this);
m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
parentNode()->renderer()->addChild(m_render, nextRenderer());
@@ -623,7 +623,7 @@ void HTMLIFrameElementImpl::attach()
_style->ref();
if (!selfreference && !(w->part()->onlyLocalReferences() && u.protocol() != "file") &&
parentNode()->renderer() && _style->display() != NONE) {
- m_render = new RenderPartObject(this);
+ m_render = new (getDocument()->renderArena()) RenderPartObject(this);
m_render->setStyle(_style);
parentNode()->renderer()->addChild(m_render, nextRenderer());
}
diff --git a/WebCore/khtml/html/html_formimpl.cpp b/WebCore/khtml/html/html_formimpl.cpp
index 7a6396f..cf77981 100644
--- a/WebCore/khtml/html/html_formimpl.cpp
+++ b/WebCore/khtml/html/html_formimpl.cpp
@@ -74,6 +74,7 @@ HTMLFormElementImpl::HTMLFormElementImpl(DocumentPtr *doc)
m_enctype = "application/x-www-form-urlencoded";
m_boundary = "----------0xKhTmLbOuNdArY";
m_acceptcharset = "UNKNOWN";
+ m_malformed = false;
}
HTMLFormElementImpl::~HTMLFormElementImpl()
@@ -1076,18 +1077,19 @@ void HTMLInputElementImpl::attach()
RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
_style->ref();
if (parentNode()->renderer() && _style->display() != NONE) {
+ RenderArena* arena = getDocument()->renderArena();
switch(m_type)
{
case TEXT:
case PASSWORD:
- case ISINDEX: m_render = new RenderLineEdit(this); break;
- case CHECKBOX: m_render = new RenderCheckBox(this); break;
- case RADIO: m_render = new RenderRadioButton(this); break;
- case SUBMIT: m_render = new RenderSubmitButton(this); break;
- case IMAGE: m_render = new RenderImageButton(this); break;
- case RESET: m_render = new RenderResetButton(this); break;
- case FILE: m_render = new RenderFileButton(this); break;
- case BUTTON: m_render = new RenderPushButton(this);
+ case ISINDEX: m_render = new (arena) RenderLineEdit(this); break;
+ case CHECKBOX: m_render = new (arena) RenderCheckBox(this); break;
+ case RADIO: m_render = new (arena) RenderRadioButton(this); break;
+ case SUBMIT: m_render = new (arena) RenderSubmitButton(this); break;
+ case IMAGE: m_render = new (arena) RenderImageButton(this); break;
+ case RESET: m_render = new (arena) RenderResetButton(this); break;
+ case FILE: m_render = new (arena) RenderFileButton(this); break;
+ case BUTTON: m_render = new (arena) RenderPushButton(this);
case HIDDEN: break;
}
}
@@ -1697,7 +1699,7 @@ void HTMLSelectElementImpl::attach()
RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
_style->ref();
if (parentNode()->renderer() && _style->display() != NONE) {
- m_render = new RenderSelect(this);
+ m_render = new (getDocument()->renderArena()) RenderSelect(this);
m_render->setStyle(_style);
}
@@ -2188,7 +2190,7 @@ void HTMLTextAreaElementImpl::attach()
RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
_style->ref();
if (parentNode()->renderer() && _style->display() != NONE) {
- m_render = new RenderTextArea(this);
+ m_render = new (getDocument()->renderArena()) RenderTextArea(this);
m_render->setStyle(_style);
}
diff --git a/WebCore/khtml/html/html_formimpl.h b/WebCore/khtml/html/html_formimpl.h
index 4b75c53..a49b059 100644
--- a/WebCore/khtml/html/html_formimpl.h
+++ b/WebCore/khtml/html/html_formimpl.h
@@ -90,6 +90,9 @@ public:
void submit();
void reset();
+ void setMalformed(bool malformed) { m_malformed = malformed; }
+ virtual bool isMalformed() { return m_malformed; }
+
static void i18nData();
friend class HTMLFormElement;
@@ -108,6 +111,7 @@ public:
bool m_insubmit : 1;
bool m_doingsubmit : 1;
bool m_inreset : 1;
+ bool m_malformed : 1;
};
// -------------------------------------------------------------------------
diff --git a/WebCore/khtml/html/html_imageimpl.cpp b/WebCore/khtml/html/html_imageimpl.cpp
index f937d14..ad330e1 100644
--- a/WebCore/khtml/html/html_imageimpl.cpp
+++ b/WebCore/khtml/html/html_imageimpl.cpp
@@ -171,7 +171,7 @@ void HTMLImageElementImpl::attach()
RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
_style->ref();
if (parentNode()->renderer() && _style->display() != NONE) {
- m_render = new RenderImage(this);
+ m_render = new (getDocument()->renderArena()) RenderImage(this);
m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
parentNode()->renderer()->addChild(m_render, nextRenderer());
m_render->updateFromElement();
diff --git a/WebCore/khtml/html/html_inlineimpl.cpp b/WebCore/khtml/html/html_inlineimpl.cpp
index fd7f984..42c2374 100644
--- a/WebCore/khtml/html/html_inlineimpl.cpp
+++ b/WebCore/khtml/html/html_inlineimpl.cpp
@@ -212,7 +212,7 @@ void HTMLBRElementImpl::attach()
assert(parentNode());
if (parentNode()->renderer()) {
- m_render = new RenderBR(this);
+ m_render = new (getDocument()->renderArena()) RenderBR(this);
m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
parentNode()->renderer()->addChild(m_render, nextRenderer());
}
diff --git a/WebCore/khtml/html/html_objectimpl.cpp b/WebCore/khtml/html/html_objectimpl.cpp
index b77572e..6c244eb 100644
--- a/WebCore/khtml/html/html_objectimpl.cpp
+++ b/WebCore/khtml/html/html_objectimpl.cpp
@@ -116,12 +116,12 @@ void HTMLAppletElementImpl::attach()
args.insert( "archive", archive.string() );
args.insert( "baseURL", getDocument()->baseURL() );
- m_render = new RenderApplet(this, args);
+ m_render = new (getDocument()->renderArena()) RenderApplet(this, args);
}
else
// ### remove me. we should never show an empty applet, instead
// render the alternative content given by the webpage
- m_render = new RenderEmptyApplet(this);
+ m_render = new (getDocument()->renderArena()) RenderEmptyApplet(this);
#endif
if (m_render) {
@@ -246,7 +246,7 @@ void HTMLEmbedElementImpl::attach()
KHTMLView* w = getDocument()->view();
if (w->part()->pluginsEnabled()) {
if (parentNode()->id() != ID_OBJECT)
- m_render = new RenderPartObject(this);
+ m_render = new (getDocument()->renderArena()) RenderPartObject(this);
}
if (m_render) {
@@ -355,7 +355,7 @@ void HTMLObjectElementImpl::attach()
// render tree construction caused by stylesheet loads. -dwh
if (loadplugin && parentNode()->renderer()) {
needWidgetUpdate = false;
- m_render = new RenderPartObject(this);
+ m_render = new (getDocument()->renderArena()) RenderPartObject(this);
m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
parentNode()->renderer()->addChild(m_render, nextRenderer());
}
diff --git a/WebCore/khtml/html/htmlparser.cpp b/WebCore/khtml/html/htmlparser.cpp
index ef7cfde..30540aa 100644
--- a/WebCore/khtml/html/htmlparser.cpp
+++ b/WebCore/khtml/html/htmlparser.cpp
@@ -174,8 +174,7 @@ void KHTMLParser::reset()
haveFrameSet = false;
haveContent = false;
inSelect = false;
- m_inline = false;
-
+
form = 0;
map = 0;
head = 0;
@@ -209,7 +208,7 @@ void KHTMLParser::parseToken(Token *t)
#ifdef PARSER_DEBUG
kdDebug( 6035 ) << "\n\n==> parser: processing token " << getTagName(t->id).string() << "(" << t->id << ")"
<< " current = " << getTagName(current->id()).string() << "(" << current->id() << ")" << endl;
- kdDebug(6035) << "inline=" << m_inline << " inBody=" << inBody << " haveFrameSet=" << haveFrameSet << endl;
+ kdDebug(6035) << " inBody=" << inBody << " haveFrameSet=" << haveFrameSet << endl;
#endif
// holy shit. apparently some sites use </br> instead of <br>
@@ -225,7 +224,10 @@ void KHTMLParser::parseToken(Token *t)
// ignore spaces, if we're not inside a paragraph or other inline code
if( t->id == ID_TEXT && t->text ) {
- if(inBody && !skipMode() && t->text->l > 2) haveContent = true;
+ if(inBody && !skipMode() && current->id() != ID_STYLE
+ && current->id() != ID_TITLE && current->id() != ID_SCRIPT &&
+ !t->text->containsOnlyWhitespace())
+ haveContent = true;
#ifdef PARSER_DEBUG
kdDebug(6035) << "length="<< t->text->l << " text='" << QConstString(t->text->s, t->text->l).string() << "'" << endl;
#endif
@@ -331,8 +333,6 @@ bool KHTMLParser::insertNode(NodeImpl *n, bool flat)
n->renderer()->setBlockBidi();
}
#endif
- //_inline = current->isInline();
- if(current->isInline()) m_inline = true;
}
else {
#if SPEED_DEBUG < 2
@@ -1199,6 +1199,12 @@ void KHTMLParser::popBlock( int _id )
}
else
{
+ if (Elem->id == ID_FORM && form)
+ // A <form> is being closed prematurely (and this is
+ // malformed HTML). Set an attribute on the form to clear out its
+ // bottom margin.
+ form->setMalformed(true);
+
popOneBlock();
Elem = blockStack;
}
@@ -1230,10 +1236,6 @@ void KHTMLParser::popOneBlock()
removeForbidden(Elem->id, forbiddenTag);
blockStack = Elem->next;
- // we only set inline to false, if the element we close is a block level element.
- // This helps getting cases as <p><b>bla</b> <b>bla</b> right.
- if(!current->isInline())
- m_inline = false;
current = Elem->node;
delete Elem;
diff --git a/WebCore/khtml/html/htmlparser.h b/WebCore/khtml/html/htmlparser.h
index dbb8193..c68fdb3 100644
--- a/WebCore/khtml/html/htmlparser.h
+++ b/WebCore/khtml/html/htmlparser.h
@@ -84,7 +84,7 @@ public:
void reset();
bool skipMode() const { return (discard_until != 0); }
- bool noSpaces() const { return (!m_inline || !inBody); }
+ bool noSpaces() const { return !inBody; }
bool selectMode() const { return inSelect; }
DOM::HTMLDocumentImpl *doc() const { return static_cast<DOM::HTMLDocumentImpl *>(document->document()); }
@@ -160,7 +160,6 @@ protected:
bool inBody;
bool haveContent;
bool haveFrameSet;
- bool m_inline;
bool end;
bool haveKonqBlock;
bool inSelect;
diff --git a/WebCore/khtml/html/htmltokenizer.cpp b/WebCore/khtml/html/htmltokenizer.cpp
index 23584f6..e672556 100644
--- a/WebCore/khtml/html/htmltokenizer.cpp
+++ b/WebCore/khtml/html/htmltokenizer.cpp
@@ -1274,7 +1274,7 @@ void HTMLTokenizer::addPending()
assert(0);
}
}
- else if ( pre )
+ else
{
int p;
@@ -1308,11 +1308,7 @@ void HTMLTokenizer::addPending()
break;
}
}
- else
- {
- *dest++ = ' ';
- }
-
+
pending = NonePending;
}
@@ -1434,20 +1430,19 @@ void HTMLTokenizer::write( const QString &str, bool appendData )
if ( pending ) {
// pre context always gets its spaces/linefeeds
- if ( pre )
+ if ( pre || (!parser->selectMode() &&
+ (!parser->noSpaces() || dest > buffer ))) {
addPending();
- // only add in existing inline context or if
- // we just started one, i.e. we're about to insert real text
- else if ( !parser->selectMode() &&
- ( !parser->noSpaces() || dest > buffer )) {
- addPending();
- discard = AllDiscard;
+ discard = AllDiscard; // So we discard the first LF after the open tag.
}
// just forget it
else
pending = NonePending;
}
+ if (cc == '/' && discard == AllDiscard)
+ discard = NoneDiscard; // A close tag. No need to discard LF.
+
processToken();
cBufferPos = 0;
@@ -1469,38 +1464,38 @@ void HTMLTokenizer::write( const QString &str, bool appendData )
}
else if (( cc == '\n' ) || ( cc == '\r' ))
{
- if ( pre || textarea)
+ if (select)
{
- if (discard == LFDiscard || discard == AllDiscard)
+ if (discard == LFDiscard)
{
// Ignore this LF
discard = NoneDiscard; // We have discarded 1 LF
}
- else
+ else if(discard == AllDiscard)
{
- // Process this LF
- if (pending)
- addPending();
- pending = LFPending;
+ }
+ else
+ {
+ // Process this LF
+ if (pending == NonePending)
+ pending = LFPending;
}
}
- else
- {
- if (discard == LFDiscard)
+ else {
+ if (discard == LFDiscard || discard == AllDiscard)
{
// Ignore this LF
discard = NoneDiscard; // We have discarded 1 LF
}
- else if(discard == AllDiscard)
- {
- }
else
{
// Process this LF
- if (pending == NonePending)
- pending = LFPending;
+ if (pending)
+ addPending();
+ pending = LFPending;
}
}
+
/* Check for MS-DOS CRLF sequence */
if (cc == '\r')
{
@@ -1510,8 +1505,19 @@ void HTMLTokenizer::write( const QString &str, bool appendData )
}
else if (( cc == ' ' ) || ( cc == '\t' ))
{
- if ( pre || textarea)
- {
+ if (select) {
+ if(discard == SpaceDiscard)
+ discard = NoneDiscard;
+ else if(discard == AllDiscard)
+ { }
+ else
+ pending = SpacePending;
+
+ }
+ else {
+ if (discard == AllDiscard)
+ discard = NoneDiscard;
+
if (pending)
addPending();
if (cc == ' ')
@@ -1519,15 +1525,7 @@ void HTMLTokenizer::write( const QString &str, bool appendData )
else
pending = TabPending;
}
- else
- {
- if(discard == SpaceDiscard)
- discard = NoneDiscard;
- else if(discard == AllDiscard)
- { }
- else
- pending = SpacePending;
- }
+
++src;
}
else
diff --git a/WebCore/khtml/misc/arena.cpp b/WebCore/khtml/misc/arena.cpp
new file mode 100644
index 0000000..013624f
--- /dev/null
+++ b/WebCore/khtml/misc/arena.cpp
@@ -0,0 +1,246 @@
+/* This is a direct port of Gecko's PLArena code. It is based on lifetime-based fast allocation, inspired by much prior art, including
+ "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "arena.h"
+
+//#define DEBUG_ARENA_MALLOC
+#ifdef DEBUG_ARENA_MALLOC
+static int i = 0;
+#endif
+
+#define FREELIST_MAX 30
+static Arena *arena_freelist;
+static int freelist_count = 0;
+
+#define ARENA_DEFAULT_ALIGN sizeof(double)
+#define BIT(n) ((unsigned int)1 << (n))
+#define BITMASK(n) (BIT(n) - 1)
+#define CEILING_LOG2(_log2,_n) \
+ unsigned int j_ = (unsigned int)(_n); \
+ (_log2) = 0; \
+ if ((j_) & ((j_)-1)) \
+ (_log2) += 1; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1;
+
+int CeilingLog2(unsigned int i) {
+ int log2;
+ CEILING_LOG2(log2,i);
+ return log2;
+}
+
+void InitArenaPool(ArenaPool *pool, const char *name,
+ unsigned int size, unsigned int align)
+{
+ if (align == 0)
+ align = ARENA_DEFAULT_ALIGN;
+ pool->mask = BITMASK(CeilingLog2(align));
+ pool->first.next = NULL;
+ pool->first.base = pool->first.avail = pool->first.limit =
+ (uword)ARENA_ALIGN(pool, &pool->first + 1);
+ pool->current = &pool->first;
+ pool->arenasize = size;
+}
+
+
+/*
+ ** ArenaAllocate() -- allocate space from an arena pool
+ **
+ ** Description: ArenaAllocate() allocates space from an arena
+ ** pool.
+ **
+ ** First try to satisfy the request from arenas starting at
+ ** pool->current.
+ **
+ ** If there is not enough space in the arena pool->current, try
+ ** to claim an arena, on a first fit basis, from the global
+ ** freelist (arena_freelist).
+ **
+ ** If no arena in arena_freelist is suitable, then try to
+ ** allocate a new arena from the heap.
+ **
+ ** Returns: pointer to allocated space or NULL
+ **
+ */
+void* ArenaAllocate(ArenaPool *pool, unsigned int nb)
+{
+ Arena *a;
+ char *rp; /* returned pointer */
+
+ assert((nb & pool->mask) == 0);
+
+ nb = (uword)ARENA_ALIGN(pool, nb); /* force alignment */
+
+ /* attempt to allocate from arenas at pool->current */
+ {
+ a = pool->current;
+ do {
+ if ( a->avail +nb <= a->limit ) {
+ pool->current = a;
+ rp = (char *)a->avail;
+ a->avail += nb;
+ return rp;
+ }
+ } while( NULL != (a = a->next) );
+ }
+
+ /* attempt to allocate from arena_freelist */
+ {
+ Arena *p; /* previous pointer, for unlinking from freelist */
+
+ for ( a = p = arena_freelist; a != NULL ; p = a, a = a->next ) {
+ if ( a->base +nb <= a->limit ) {
+ if ( p == arena_freelist )
+ arena_freelist = a->next;
+ else
+ p->next = a->next;
+ a->avail = a->base;
+ rp = (char *)a->avail;
+ a->avail += nb;
+ /* the newly allocated arena is linked after pool->current
+ * and becomes pool->current */
+ a->next = pool->current->next;
+ pool->current->next = a;
+ pool->current = a;
+ if ( 0 == pool->first.next )
+ pool->first.next = a;
+ freelist_count--;
+ return(rp);
+ }
+ }
+ }
+
+ /* attempt to allocate from the heap */
+ {
+ unsigned int sz = MAX(pool->arenasize, nb);
+ sz += sizeof *a + pool->mask; /* header and alignment slop */
+#ifdef DEBUG_ARENA_MALLOC
+ i++;
+ printf("Malloc: %d\n", i);
+#endif
+ a = (Arena*)malloc(sz);
+ if (a) {
+ a->limit = (uword)a + sz;
+ a->base = a->avail = (uword)ARENA_ALIGN(pool, a + 1);
+ rp = (char *)a->avail;
+ a->avail += nb;
+ /* the newly allocated arena is linked after pool->current
+ * and becomes pool->current */
+ a->next = pool->current->next;
+ pool->current->next = a;
+ pool->current = a;
+ if ( !pool->first.next )
+ pool->first.next = a;
+ return(rp);
+ }
+ }
+
+ /* we got to here, and there's no memory to allocate */
+ return(0);
+} /* --- end ArenaAllocate() --- */
+
+void* ArenaGrow(ArenaPool *pool, void *p, unsigned int size, unsigned int incr)
+{
+ void *newp;
+
+ ARENA_ALLOCATE(newp, pool, size + incr);
+ if (newp)
+ memcpy(newp, p, size);
+ return newp;
+}
+
+/*
+ * Free tail arenas linked after head, which may not be the true list head.
+ * Reset pool->current to point to head in case it pointed at a tail arena.
+ */
+static void FreeArenaList(ArenaPool *pool, Arena *head, bool reallyFree)
+{
+ Arena **ap, *a;
+
+ ap = &head->next;
+ a = *ap;
+ if (!a)
+ return;
+
+#ifdef DEBUG
+ do {
+ assert(a->base <= a->avail && a->avail <= a->limit);
+ a->avail = a->base;
+ CLEAR_UNUSED(a);
+ } while ((a = a->next) != 0);
+ a = *ap;
+#endif
+
+ if (freelist_count >= FREELIST_MAX)
+ reallyFree = true;
+
+ if (reallyFree) {
+ do {
+ *ap = a->next;
+ CLEAR_ARENA(a);
+#ifdef DEBUG_ARENA_MALLOC
+ if (a) {
+ i--;
+ printf("Free: %d\n", i);
+ }
+#endif
+ free(a); a = 0;
+ } while ((a = *ap) != 0);
+ } else {
+ /* Insert the whole arena chain at the front of the freelist. */
+ do {
+ ap = &(*ap)->next;
+ freelist_count++;
+ } while (*ap);
+ *ap = arena_freelist;
+ arena_freelist = a;
+ head->next = 0;
+ }
+ pool->current = head;
+}
+
+void ArenaRelease(ArenaPool *pool, char *mark)
+{
+ Arena *a;
+
+ for (a = pool->first.next; a; a = a->next) {
+ if (UPTRDIFF(mark, a->base) < UPTRDIFF(a->avail, a->base)) {
+ a->avail = (uword)ARENA_ALIGN(pool, mark);
+ FreeArenaList(pool, a, false);
+ return;
+ }
+ }
+}
+
+void FreeArenaPool(ArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first, false);
+}
+
+void FinishArenaPool(ArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first, true);
+}
+
+void ArenaFinish(void)
+{
+ Arena *a, *next;
+
+ for (a = arena_freelist; a; a = next) {
+ next = a->next;
+ free(a); a = 0;
+ }
+ arena_freelist = NULL;
+}
diff --git a/WebCore/khtml/misc/arena.h b/WebCore/khtml/misc/arena.h
new file mode 100644
index 0000000..d20f5b0
--- /dev/null
+++ b/WebCore/khtml/misc/arena.h
@@ -0,0 +1,91 @@
+#ifndef ARENA_H
+#define ARENA_H
+
+// This code is a more-or-less direct port of the PLArena code found in the NSPR (the runtime
+// used by Gecko). This version is not thread safe. It sacrifices thread safety for speed
+// (no lock overhead when allocing out of the arena). -dwh
+
+#define ARENA_ALIGN_MASK 3
+
+typedef unsigned long uword;
+
+struct Arena {
+ Arena* next; // next arena
+ uword base; // aligned base address
+ uword limit; // end of arena (1+last byte)
+ uword avail; // points to next available byte in arena
+};
+
+struct ArenaPool {
+ Arena first; // first arena in pool list.
+ Arena* current; // current arena.
+ unsigned int arenasize;
+ uword mask; // Mask (power-of-2 - 1)
+};
+
+void InitArenaPool(ArenaPool *pool, const char *name,
+ unsigned int size, unsigned int align);
+void FinishArenaPool(ArenaPool *pool);
+void FreeArenaPool(ArenaPool *pool);
+void* ArenaAllocate(ArenaPool *pool, unsigned int nb);
+
+#define ARENA_ALIGN(pool, n) (((uword)(n) + ARENA_ALIGN_MASK) & ~ARENA_ALIGN_MASK)
+#define INIT_ARENA_POOL(pool, name, size) \
+ InitArenaPool(pool, name, size, ARENA_ALIGN_MASK + 1)
+
+#define ARENA_ALLOCATE(p, pool, nb) \
+ Arena *_a = (pool)->current; \
+ unsigned int _nb = ARENA_ALIGN(pool, nb); \
+ uword _p = _a->avail; \
+ uword _q = _p + _nb; \
+ if (_q > _a->limit) \
+ _p = (uword)ArenaAllocate(pool, _nb); \
+ else \
+ _a->avail = _q; \
+ p = (void *)_p;
+
+#define ARENA_GROW(p, pool, size, incr) \
+ Arena *_a = (pool)->current; \
+ unsigned int _incr = ARENA_ALIGN(pool, incr); \
+ uword _p = _a->avail; \
+ uword _q = _p + _incr; \
+ if (_p == (uword)(p) + ARENA_ALIGN(pool, size) && \
+ _q <= _a->limit) { \
+ _a->avail = _q; \
+ } else { \
+ p = ArenaGrow(pool, p, size, incr); \
+ }
+
+#define ARENA_MARK(pool) ((void *) (pool)->current->avail)
+#define UPTRDIFF(p,q) ((uword)(p) - (uword)(q))
+
+#ifdef DEBUG
+#define FREE_PATTERN 0xDA
+#define CLEAR_UNUSED(a) (assert((a)->avail <= (a)->limit), \
+ memset((void*)(a)->avail, FREE_PATTERN, \
+ (a)->limit - (a)->avail))
+#define CLEAR_ARENA(a) memset((void*)(a), FREE_PATTERN, \
+ (a)->limit - (PRUword)(a))
+#else
+#define CLEAR_UNUSED(a)
+#define CLEAR_ARENA(a)
+#endif
+
+#define ARENA_RELEASE(pool, mark) \
+ char *_m = (char *)(mark); \
+ Arena *_a = (pool)->current; \
+ if (UPTRDIFF(_m, _a->base) <= UPTRDIFF(_a->avail, _a->base)) { \
+ _a->avail = (uword)ARENA_ALIGN(pool, _m); \
+ CLEAR_UNUSED(_a); \
+ } else { \
+ ArenaRelease(pool, _m); \
+ }
+
+#define ARENA_DESTROY(pool, a, pnext) \
+ if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
+ *(pnext) = (a)->next; \
+ CLEAR_ARENA(a); \
+ free(a); \
+ (a) = 0;
+
+#endif ARENA_H
diff --git a/WebCore/khtml/rendering/bidi.cpp b/WebCore/khtml/rendering/bidi.cpp
index 04a0d06..4fa5b47 100644
--- a/WebCore/khtml/rendering/bidi.cpp
+++ b/WebCore/khtml/rendering/bidi.cpp
@@ -23,6 +23,9 @@
#include "break_lines.h"
#include "render_flow.h"
#include "render_text.h"
+#include "render_arena.h"
+#include "xml/dom_docimpl.h"
+
using namespace khtml;
#include "kdebug.h"
@@ -40,6 +43,9 @@ static BidiIterator current;
static BidiContext *context;
static BidiStatus status;
static QPtrList<BidiRun> *sruns = 0;
+static QPtrList<BidiIterator> *smidpoints = 0;
+static bool betweenMidpoints = false;
+static bool isLineEmpty = true;
static QChar::Direction dir;
static bool adjustEmbeddding = false;
static bool emptyRun = true;
@@ -48,6 +54,25 @@ static int numSpaces;
static void embed( QChar::Direction d );
static void appendRun();
+void BidiIterator::detach(RenderArena* renderArena)
+{
+ delete this;
+
+ // Now perform the destroy.
+ size_t* sz = (size_t*)this;
+ renderArena->free(*sz, (void*)this);
+}
+
+void* BidiIterator::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ return renderArena->allocate(sz);
+}
+
+void BidiIterator::operator delete(void* ptr, size_t sz) {
+ size_t* szPtr = (size_t*)ptr;
+ *szPtr = sz;
+}
+
// ---------------------------------------------------------------------
/* a small helper class used internally to resolve Bidi embedding levels.
@@ -224,6 +249,36 @@ inline QChar::Direction BidiIterator::direction() const
// -------------------------------------------------------------------------------------------------
+static void appendRunsForObject(int start, int end, RenderObject* obj)
+{
+ BidiIterator* nextMidpoint = (smidpoints && smidpoints->count()) ? smidpoints->at(0) : 0;
+ if (betweenMidpoints) {
+ if (!(nextMidpoint && nextMidpoint->obj == obj))
+ return;
+ // This is a new start point. Stop ignoring objects and
+ // adjust our start.
+ betweenMidpoints = false;
+ start = nextMidpoint->pos;
+ smidpoints->removeFirst(); // Delete the midpoint.
+ if (start < end)
+ return appendRunsForObject(start, end, obj);
+ }
+ else {
+ if (!smidpoints || !nextMidpoint || (obj != nextMidpoint->obj)) {
+ sruns->append( new BidiRun(start, end, obj, context, dir) );
+ return;
+ }
+
+ // An end midpoint has been encounted within our object. We
+ // need to go ahead and append a run with our endpoint.
+ sruns->append( new BidiRun(start, nextMidpoint->pos+1, obj, context, dir) );
+ betweenMidpoints = true;
+ int nextPos = nextMidpoint->pos+1;
+ smidpoints->removeFirst();
+ return appendRunsForObject(nextPos, end, obj);
+ }
+}
+
static void appendRun()
{
if ( emptyRun ) return;
@@ -237,18 +292,12 @@ static void appendRun()
int start = sor.pos;
RenderObject *obj = sor.obj;
while( obj && obj != eor.obj ) {
- if(!obj->isHidden()) {
- //kdDebug(6041) << "appendRun: "<< start << "/" << obj->length() <<endl;
- sruns->append( new BidiRun(start, obj->length(), obj, context, dir) );
- }
+ appendRunsForObject(start, obj->length(), obj);
start = 0;
obj = Bidinext( sor.par, obj );
}
- if( obj && !obj->isHidden()) {
- //kdDebug(6041) << "appendRun: "<< start << "/" << eor.pos <<endl;
- sruns->append( new BidiRun(start, eor.pos + 1, obj, context, dir) );
- }
-
+ appendRunsForObject(start, eor.pos+1, obj);
+
++eor;
sor = eor;
dir = QChar::DirON;
@@ -332,10 +381,10 @@ static void embed( QChar::Direction d )
void RenderFlow::bidiReorderLine(const BidiIterator &start, const BidiIterator &end)
{
if ( start == end ) {
- if ( start.current() == '\n' ) {
- m_height += lineHeight( firstLine );
- }
- return;
+ if ( start.current() == '\n' ) {
+ m_height += lineHeight( firstLine );
+ }
+ return;
}
#if BIDI_DEBUG > 1
kdDebug(6041) << "reordering Line from " << start.obj << "/" << start.pos << " to " << end.obj << "/" << end.pos << endl;
@@ -358,16 +407,16 @@ void RenderFlow::bidiReorderLine(const BidiIterator &start, const BidiIterator &
while( 1 ) {
QChar::Direction dirCurrent;
- if(atEnd ) {
+ if (atEnd) {
//kdDebug(6041) << "atEnd" << endl;
BidiContext *c = context;
- if ( current.atEnd())
- while ( c->parent )
- c = c->parent;
+ if ( current.atEnd())
+ while ( c->parent )
+ c = c->parent;
dirCurrent = c->dir;
} else {
dirCurrent = current.direction();
- }
+ }
#ifndef QT_NO_UNICODETABLES
@@ -383,9 +432,9 @@ void RenderFlow::bidiReorderLine(const BidiIterator &start, const BidiIterator &
case QChar::DirRLO:
case QChar::DirLRO:
case QChar::DirPDF:
- eor = last;
- embed( dirCurrent );
- break;
+ eor = last;
+ embed( dirCurrent );
+ break;
// strong types
case QChar::DirL:
@@ -918,6 +967,20 @@ void RenderFlow::bidiReorderLine(const BidiIterator &start, const BidiIterator &
}
+static void deleteMidpoints(RenderArena* arena, QPtrList<BidiIterator>* midpoints)
+{
+ if (!midpoints)
+ return;
+
+ unsigned int len = midpoints->count();
+ for(unsigned int i=0; i < len; i++) {
+ BidiIterator* s = midpoints->at(i);
+ if (s)
+ s->detach(arena);
+ midpoints->remove(i);
+ }
+}
+
void RenderFlow::layoutInlineChildren()
{
invalidateVerticalPositions();
@@ -937,6 +1000,7 @@ void RenderFlow::layoutInlineChildren()
m_height += paddingTop();
toAdd += paddingBottom();
}
+
if(firstChild()) {
// layout replaced elements
RenderObject *o = first( this );
@@ -967,35 +1031,48 @@ void RenderFlow::layoutInlineChildren()
startEmbed->ref();
context = startEmbed;
- adjustEmbeddding = true;
+ adjustEmbeddding = true;
BidiIterator start(this);
- adjustEmbeddding = false;
+ adjustEmbeddding = false;
BidiIterator end(this);
firstLine = true;
+
+ if (!smidpoints) {
+ smidpoints = new QPtrList<BidiIterator>;
+ smidpoints->setAutoDelete(false);
+ }
+
while( !end.atEnd() ) {
start = end;
-
- end = findNextLineBreak(start);
+ betweenMidpoints = false;
+ isLineEmpty = true;
+ end = findNextLineBreak(start, *smidpoints);
if( start.atEnd() ) break;
- bidiReorderLine(start, end);
-
- if( end == start || (end.obj && end.obj->isBR() && !start.obj->isBR() ) ) {
- adjustEmbeddding = true;
- ++end;
- adjustEmbeddding = false;
- } else if(m_pre && end.current() == QChar('\n') ) {
- adjustEmbeddding = true;
- ++end;
- adjustEmbeddding = false;
+ if (!isLineEmpty) {
+ bidiReorderLine(start, end);
+
+ if( end == start || (end.obj && end.obj->isBR() && !start.obj->isBR() ) ) {
+ adjustEmbeddding = true;
+ ++end;
+ adjustEmbeddding = false;
+ } else if(m_pre && end.current() == QChar('\n') ) {
+ adjustEmbeddding = true;
+ ++end;
+ adjustEmbeddding = false;
+ }
+
+ newLine();
}
-
- newLine();
firstLine = false;
+ deleteMidpoints(renderArena(), smidpoints);
}
startEmbed->deref();
//embed->deref();
}
+
+ deleteMidpoints(renderArena(), smidpoints);
+
m_height += toAdd;
// in case we have a float on the last line, it might not be positioned up to now.
@@ -1008,7 +1085,7 @@ void RenderFlow::layoutInlineChildren()
//kdDebug(6040) << "height = " << m_height <<endl;
}
-BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
+BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start, QPtrList<BidiIterator>& midpoints)
{
int width = lineWidth(m_height);
int w = 0;
@@ -1018,42 +1095,55 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
kdDebug(6041) << "sol: " << start.obj << " " << start.pos << endl;
#endif
-
// eliminate spaces at beginning of line
if(!m_pre) {
- // remove leading spaces
- while(!start.atEnd() &&
+ // remove leading spaces
+ while(!start.atEnd() &&
#ifndef QT_NO_UNICODETABLES
- ( start.direction() == QChar::DirWS || start.obj->isSpecial() )
+ ( start.direction() == QChar::DirWS || start.obj->isSpecial() )
#else
- ( start.current() == ' ' || start.obj->isSpecial() )
+ ( start.current() == ' ' || start.obj->isSpecial() )
#endif
- ) {
- if( start.obj->isSpecial() ) {
- RenderObject *o = start.obj;
- // add to special objects...
- if(o->isFloating()) {
- insertSpecialObject(o);
- // check if it fits in the current line.
- // If it does, position it now, otherwise, position
- // it after moving to next line (in newLine() func)
- if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
- positionNewFloats();
- width = lineWidth(m_height);
- }
- } else if(o->isPositioned()) {
- static_cast<RenderFlow*>(o->containingBlock())->insertSpecialObject(o);
- }
- }
-
- adjustEmbeddding = true;
- ++start;
- adjustEmbeddding = false;
- }
+ ) {
+ if( start.obj->isSpecial() ) {
+ RenderObject *o = start.obj;
+ // add to special objects...
+ if(o->isFloating()) {
+ insertSpecialObject(o);
+ // check if it fits in the current line.
+ // If it does, position it now, otherwise, position
+ // it after moving to next line (in newLine() func)
+ if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
+ positionNewFloats();
+ width = lineWidth(m_height);
+ }
+ } else if(o->isPositioned()) {
+ static_cast<RenderFlow*>(o->containingBlock())->insertSpecialObject(o);
+ }
+ }
+
+ adjustEmbeddding = true;
+ ++start;
+ adjustEmbeddding = false;
+ }
}
if ( start.atEnd() )
return start;
+ // This variable is used only if whitespace isn't set to PRE, and it tells us whether
+ // or not we are currently ignoring whitespace.
+ bool ignoringSpaces = false;
+
+ // This variable tracks whether the very last character we saw was a space. We use
+ // this to detect when we encounter a second space so we know we have to terminate
+ // a run.
+ bool sawSpace = false;
+ RenderObject* trailingSpaceObject = 0;
+
+ // The pos of the last whitespace char we saw, not to be confused with the lastSpace
+ // variable below, which is really the last breakable char.
+ int lastSpacePos = 0;
+
BidiIterator lBreak = start;
RenderObject *o = start.obj;
@@ -1068,6 +1158,13 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
if( w + tmpW <= width ) {
lBreak.obj = o;
lBreak.pos = 0;
+
+ // A <br> always breaks a line, so don't let the line be collapsed
+ // away. Also, the space at the end of a line with a <br> does not
+ // get collapsed away. -dwh
+ isLineEmpty = false;
+ trailingSpaceObject = 0;
+
//check the clear status
EClear clear = o->style()->clear();
if(clear != CNONE) {
@@ -1078,109 +1175,171 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
}
if( o->isSpecial() ) {
// add to special objects...
- if(o->isFloating()) {
- insertSpecialObject(o);
- // check if it fits in the current line.
- // If it does, position it now, otherwise, position
- // it after moving to next line (in newLine() func)
- if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
- positionNewFloats();
- width = lineWidth(m_height);
- }
- } else if(o->isPositioned()) {
- static_cast<RenderFlow*>(o->containingBlock())->insertSpecialObject(o);
- }
+ if(o->isFloating()) {
+ insertSpecialObject(o);
+ // check if it fits in the current line.
+ // If it does, position it now, otherwise, position
+ // it after moving to next line (in newLine() func)
+ if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
+ positionNewFloats();
+ width = lineWidth(m_height);
+ }
+ } else if(o->isPositioned()) {
+ static_cast<RenderFlow*>(o->containingBlock())->insertSpecialObject(o);
+ }
} else if ( o->isReplaced() ) {
tmpW += o->width()+o->marginLeft()+o->marginRight();
+ if (ignoringSpaces) {
+ BidiIterator* startMid = new (o->renderArena()) BidiIterator();
+ startMid->obj = o;
+ startMid->pos = 0;
+ midpoints.append(startMid);
+ }
+ isLineEmpty = false;
+ ignoringSpaces = false;
+ sawSpace = false;
+ lastSpacePos = 0;
+ trailingSpaceObject = 0;
} else if ( o->isText() ) {
- RenderText *t = static_cast<RenderText *>(o);
- int strlen = t->stringLength();
- int len = strlen - pos;
- QChar *str = t->text();
-#if 0
- if ( ( !firstLine || !t->firstLine() ) && !t->hasReturn() && t->maxWidth() + w + tmpW < width ) {
- // the rest of the object fits completely
-// kdDebug() << "RenderFlow::findNextLineBreak object fits completely, max=" << t->maxWidth()
-// << " width =" << w << " avail = " << width <<" tmp=" << tmpW << endl;
- //search backwards for last possible linebreak
- int lastSpace = strlen-1;
- while( lastSpace >= pos && !isBreakable( str, lastSpace, strlen ) )
- lastSpace--;
- lastSpace++;
- if ( lastSpace > pos ) {
- w += tmpW + t->width( pos, lastSpace-pos, firstLine);
- tmpW = 0;
- lBreak.obj = o;
- lBreak.pos = lastSpace;
- }
- tmpW += t->width( lastSpace, strlen-lastSpace, firstLine);
-// kdDebug() << "--> width=" << t->width( pos, strlen-pos, firstLine)
-// <<" first=" << t->width( pos, lastSpace-pos, firstLine)
-// <<" end=" << t->width( lastSpace, strlen-lastSpace, firstLine)
-// << endl;
- } else {
-#endif
- if (style()->whiteSpace() == NOWRAP || t->style()->whiteSpace() == NOWRAP ) {
- tmpW += t->maxWidth();
- pos = len;
- len = 0;
- } else {
- const Font *f = t->htmlFont( firstLine );
- // proportional font, needs a bit more work.
- int lastSpace = pos;
- bool isPre = style()->whiteSpace() == PRE;
- while(len) {
- if( (isPre && str[pos] == '\n') ||
- (!isPre && isBreakable( str, pos, strlen ) ) ) {
- tmpW += t->width(lastSpace, pos - lastSpace, f);
+ RenderText *t = static_cast<RenderText *>(o);
+ int strlen = t->stringLength();
+ int len = strlen - pos;
+ QChar *str = t->text();
+
+ const Font *f = t->htmlFont( firstLine );
+ // proportional font, needs a bit more work.
+ int lastSpace = pos;
+ bool isPre = o->style()->whiteSpace() == PRE;
+ //QChar space[1]; space[0] = ' ';
+ //int spaceWidth = f->width(space, 1, 0);
+ while(len) {
+ //XXXdwh This is wrong. Still mutating the DOM
+ // string for newlines... will fix in second stage.
+ if (!isPre && str[pos] == '\n')
+ str[pos] = ' ';
+
+ bool oldSawSpace = sawSpace;
+ sawSpace = (str[pos].direction() == QChar::DirWS);
+
+ if (isPre || !sawSpace)
+ isLineEmpty = false;
+
+ if( (isPre && str[pos] == '\n') ||
+ (!isPre && isBreakable( str, pos, strlen ) ) ) {
+
+ if (ignoringSpaces) {
+ if (!sawSpace) {
+ // Stop ignoring spaces and begin at this
+ // new point.
+ BidiIterator* startMid = new (o->renderArena()) BidiIterator();
+ startMid->obj = o;
+ startMid->pos = pos;
+ midpoints.append(startMid);
+ }
+ else {
+ // Just keep ignoring these spaces.
+ pos++;
+ len--;
+ continue;
+ }
+ }
+ else {
+ if (sawSpace && !oldSawSpace)
+ lastSpacePos = pos;
+ tmpW += t->width(lastSpace, pos - lastSpace, f);
+ }
+
#ifdef DEBUG_LINEBREAKS
- kdDebug(6041) << "found space at " << pos << " in string '" << QString( str, strlen ).latin1() << "' adding " << tmpW << " new width = " << w << endl;
+ kdDebug(6041) << "found space at " << pos << " in string '" << QString( str, strlen ).latin1() << "' adding " << tmpW << " new width = " << w << endl;
#endif
- if ( !isPre && w + tmpW > width && w == 0 ) {
- int fb = floatBottom();
- int newLineWidth = lineWidth(fb);
- if(!w && m_height < fb && width < newLineWidth) {
- m_height = fb;
- width = newLineWidth;
+ if ( !isPre && w + tmpW > width && w == 0 ) {
+ int fb = floatBottom();
+ int newLineWidth = lineWidth(fb);
+ if(!w && m_height < fb && width < newLineWidth) {
+ m_height = fb;
+ width = newLineWidth;
#ifdef DEBUG_LINEBREAKS
- kdDebug() << "RenderFlow::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
+ kdDebug() << "RenderFlow::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
#endif
- }
- }
- if ( !isPre && w + tmpW > width )
- goto end;
-
- lBreak.obj = o;
- lBreak.pos = pos;
+ }
+ }
+
+ if ( !isPre && w + tmpW > width )
+ goto end;
- if( *(str+pos) == '\n' ) {
+ lBreak.obj = o;
+ lBreak.pos = pos;
+
+ if( *(str+pos) == '\n' && isPre) {
#ifdef DEBUG_LINEBREAKS
- kdDebug(6041) << "forced break sol: " << start.obj << " " << start.pos << " end: " << lBreak.obj << " " << lBreak.pos << " width=" << w << endl;
+ kdDebug(6041) << "forced break sol: " << start.obj << " " << start.pos << " end: " << lBreak.obj << " " << lBreak.pos << " width=" << w << endl;
#endif
- return lBreak;
- }
- w += tmpW;
- tmpW = 0;
- lastSpace = pos;
- }
- pos++;
- len--;
- }
- // IMPORTANT: pos is > length here!
- tmpW += t->width(lastSpace, pos - lastSpace, f);
- }
-#if 0
+ return lBreak;
+ }
+
+ w += tmpW;
+ tmpW = 0;
+ lastSpace = pos;
+
+ if (!ignoringSpaces && !isPre) {
+ // If we encounter a newline, or if we encounter a
+ // second space, we need to go ahead and break up this
+ // run and enter a mode where we start collapsing spaces.
+ if (sawSpace && oldSawSpace)
+ ignoringSpaces = true;
+
+ if (ignoringSpaces) {
+ // We just entered a mode where we are ignoring
+ // spaces. Create a midpoint to terminate the run
+ // before the second space.
+ BidiIterator* endMid = new (o->renderArena()) BidiIterator();
+ if (trailingSpaceObject) {
+ endMid->obj = trailingSpaceObject;
+ }
+ else
+ endMid->obj = o;
+ endMid->pos = lastSpacePos;
+ midpoints.append(endMid);
+ lastSpace = pos;
+ }
+ }
+ }
+ else if (ignoringSpaces) {
+ // Stop ignoring spaces and begin at this
+ // new point.
+ ignoringSpaces = false;
+ lastSpacePos = 0;
+ lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
+ BidiIterator* startMid = new (o->renderArena()) BidiIterator();
+ startMid->obj = o;
+ startMid->pos = pos;
+ midpoints.append(startMid);
+ }
+
+ if (!isPre && sawSpace && !ignoringSpaces)
+ trailingSpaceObject = o;
+ else if (isPre || !sawSpace)
+ trailingSpaceObject = 0;
+
+ pos++;
+ len--;
}
-#endif
+
+ // IMPORTANT: pos is > length here!
+ if (!ignoringSpaces)
+ tmpW += t->width(lastSpace, pos - lastSpace, f);
} else
KHTMLAssert( false );
if( w + tmpW > width+1 && style()->whiteSpace() != NOWRAP && o->style()->whiteSpace() != NOWRAP ) {
//kdDebug() << " too wide w=" << w << " tmpW = " << tmpW << " width = " << width << endl;
- //kdDebug() << "start=" << start.obj << " current=" << o << endl;
+ //kdDebug() << "start=" << start.obj << " current=" << o << endl;
// if we have floats, try to get below them.
+ if (sawSpace && !ignoringSpaces && o->style()->whiteSpace() != PRE)
+ trailingSpaceObject = 0;
+
int fb = floatBottom();
- int newLineWidth = lineWidth(fb);
+ int newLineWidth = lineWidth(fb);
if( !w && m_height < fb && width < newLineWidth ) {
m_height = fb;
width = newLineWidth;
@@ -1188,10 +1347,10 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
kdDebug() << "RenderFlow::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
#endif
}
- if( !w && w + tmpW > width+1 && (o != start.obj || (unsigned) pos != start.pos) ) {
- // getting below floats wasn't enough...
- //kdDebug() << "still too wide w=" << w << " tmpW = " << tmpW << " width = " << width << endl;
- lBreak.obj = o;
+ if( !w && w + tmpW > width+1 && (o != start.obj || (unsigned) pos != start.pos) ) {
+ // getting below floats wasn't enough...
+ //kdDebug() << "still too wide w=" << w << " tmpW = " << tmpW << " width = " << width << endl;
+ lBreak.obj = o;
if(last != o) {
//kdDebug() << " using last " << last << endl;
//lBreak.obj = last;
@@ -1233,35 +1392,53 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
lBreak.pos = last->length();
}
} else if( lBreak.obj ) {
- if( last != o ) {
- // better break between object boundaries than in the middle of a word
- lBreak.obj = o;
- lBreak.pos = 0;
- } else {
- int w = 0;
- if( lBreak.obj->isText() )
- w += static_cast<RenderText *>(lBreak.obj)->width(lBreak.pos, 1);
- else
- w += lBreak.obj->width();
- while( lBreak.obj && w < width ) {
- ++lBreak;
- if( !lBreak.obj ) break;
- if( lBreak.obj->isText() )
- w += static_cast<RenderText *>(lBreak.obj)->width(lBreak.pos, 1);
- else
- w += lBreak.obj->width();
- }
- }
+ if( last != o ) {
+ // better break between object boundaries than in the middle of a word
+ lBreak.obj = o;
+ lBreak.pos = 0;
+ } else {
+ int w = 0;
+ if( lBreak.obj->isText() )
+ w += static_cast<RenderText *>(lBreak.obj)->width(lBreak.pos, 1);
+ else
+ w += lBreak.obj->width();
+ while( lBreak.obj && w < width ) {
+ ++lBreak;
+ if( !lBreak.obj ) break;
+ if( lBreak.obj->isText() )
+ w += static_cast<RenderText *>(lBreak.obj)->width(lBreak.pos, 1);
+ else
+ w += lBreak.obj->width();
+ }
+ }
}
}
// make sure we consume at least one char/object.
if( lBreak == start )
++lBreak;
-
+
#ifdef DEBUG_LINEBREAKS
kdDebug(6041) << "regular break sol: " << start.obj << " " << start.pos << " end: " << lBreak.obj << " " << lBreak.pos << " width=" << w << endl;
#endif
+
+ if (trailingSpaceObject) {
+ // This object is either going to be part of the last midpoint, or it is going
+ // to be the actual endpoint. In both cases we just decrease our pos by 1 level to
+ // exclude the space, allowing it to - in effect - collapse into the newline.
+ int count = midpoints.count();
+ if (count%2==1) {
+ BidiIterator* lastEndPoint = midpoints.at(count-1);
+ lastEndPoint->pos--;
+ }
+ //else if (lBreak.pos > 0)
+ // lBreak.pos--;
+ else if (lBreak.obj == 0 && trailingSpaceObject->isText()) {
+ lBreak.obj = trailingSpaceObject;
+ lBreak.pos = static_cast<RenderText *>(trailingSpaceObject)->length() - 1;
+ }
+ }
+
return lBreak;
}
diff --git a/WebCore/khtml/rendering/bidi.h b/WebCore/khtml/rendering/bidi.h
index 954e519..67a2da4 100644
--- a/WebCore/khtml/rendering/bidi.h
+++ b/WebCore/khtml/rendering/bidi.h
@@ -24,6 +24,8 @@
#include <qstring.h>
+class RenderArena;
+
namespace khtml {
class RenderFlow;
class RenderObject;
@@ -100,6 +102,20 @@ namespace khtml {
const QChar ¤t() const;
QChar::Direction direction() const;
+ void detach(RenderArena* renderArena);
+
+ // Overloaded new operator. Derived classes must override operator new
+ // in order to allocate out of the RenderArena.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+private:
+ // The normal operator new is disallowed.
+ void* operator new(size_t sz) throw() { assert(false); return 0; };
+
+public:
RenderFlow *par;
RenderObject *obj;
unsigned int pos;
diff --git a/WebCore/khtml/rendering/render_arena.cpp b/WebCore/khtml/rendering/render_arena.cpp
new file mode 100644
index 0000000..aa38ce8
--- /dev/null
+++ b/WebCore/khtml/rendering/render_arena.cpp
@@ -0,0 +1,87 @@
+/*
+ * This file contains the implementation of an arena allocation system for use by
+ * render objects and temporaries allocated during layout and style resolution
+ * of render objects. It is a direct port of Gecko's
+ * FrameArena code (frame = render_object in Gecko).
+ *
+ * Copyright (C) 2002 (hyatt at apple.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include "render_arena.h"
+
+RenderArena::RenderArena(unsigned int arenaSize)
+{
+ // Initialize the arena pool
+ INIT_ARENA_POOL(&m_pool, "RenderArena", arenaSize);
+
+ // Zero out the recyclers array
+ memset(m_recyclers, 0, sizeof(m_recyclers));
+}
+
+RenderArena::~RenderArena()
+{
+ // Free the arena in the pool and finish using it
+ FreeArenaPool(&m_pool);
+}
+
+void* RenderArena::allocate(size_t size)
+{
+ void* result = 0;
+
+ // Ensure we have correct alignment for pointers. Important for Tru64
+ size = ROUNDUP(size, sizeof(void*));
+
+ // Check recyclers first
+ if (size < gMaxRecycledSize) {
+ const int index = size >> 2;
+
+ result = m_recyclers[index];
+ if (result) {
+ // Need to move to the next object
+ void* next = *((void**)result);
+ m_recyclers[index] = next;
+ }
+ }
+
+ if (!result) {
+ // Allocate a new chunk from the arena
+ ARENA_ALLOCATE(result, &m_pool, size);
+ }
+
+ return result;
+}
+
+void RenderArena::free(size_t size, void* ptr)
+{
+#ifdef DEBUG
+ // Mark the memory with 0xdd in DEBUG builds so that there will be
+ // problems if someone tries to access memory that they've freed.
+ memset(ptr, 0xdd, size);
+#endif
+
+ // Ensure we have correct alignment for pointers. Important for Tru64
+ size = ROUNDUP(size, sizeof(void*));
+
+ // See if it's a size that we recycle
+ if (size < gMaxRecycledSize) {
+ const int index = size >> 2;
+ void* currentTop = m_recyclers[index];
+ m_recyclers[index] = ptr;
+ *((void**)ptr) = currentTop;
+ }
+}
diff --git a/WebCore/khtml/rendering/render_arena.h b/WebCore/khtml/rendering/render_arena.h
new file mode 100644
index 0000000..7fb72b5
--- /dev/null
+++ b/WebCore/khtml/rendering/render_arena.h
@@ -0,0 +1,52 @@
+#ifndef RENDERARENA_H
+#define RENDERARENA_H
+
+/*
+ * This file contains the implementation of an arena allocation system for use by
+ * render objects and temporaries allocated during layout and style resolution
+ * of render objects. It is a direct port of Gecko's
+ * FrameArena code (frame = render_object in Gecko).
+ *
+ * Copyright (C) 2002 (hyatt at apple.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include "arena.h"
+
+static const size_t gMaxRecycledSize = 400;
+#define ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
+
+class RenderArena {
+public:
+ RenderArena(unsigned int arenaSize = 4096);
+ ~RenderArena();
+
+ // Memory management functions
+ void* allocate(size_t size);
+ void free(size_t size, void* ptr);
+
+private:
+ // Underlying arena pool
+ ArenaPool m_pool;
+
+ // The recycler array is sparse with the indices being multiples of 4,
+ // i.e., 0, 4, 8, 12, 16, 20, ...
+ void* m_recyclers[gMaxRecycledSize >> 2];
+};
+
+#endif
+
diff --git a/WebCore/khtml/rendering/render_box.cpp b/WebCore/khtml/rendering/render_box.cpp
index 70732d0..e85a5c0 100644
--- a/WebCore/khtml/rendering/render_box.cpp
+++ b/WebCore/khtml/rendering/render_box.cpp
@@ -30,9 +30,11 @@
#include "rendering/render_replaced.h"
#include "rendering/render_root.h"
#include "rendering/render_table.h"
+#include "render_arena.h"
#include "misc/htmlhashes.h"
#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
#include <khtmlview.h>
#include <kdebug.h>
@@ -83,13 +85,22 @@ void RenderBox::setStyle(RenderStyle *_style)
}
if ((isPositioned() || isRelPositioned() || (isFloating() && !isListMarker())) && !m_layer)
- m_layer = new RenderLayer(this);
+ m_layer = new (element()->getDocument()->renderArena()) RenderLayer(this);
}
RenderBox::~RenderBox()
{
//kdDebug( 6040 ) << "Element destructor: this=" << nodeName().string() << endl;
- delete m_layer;
+}
+
+void RenderBox::detach(RenderArena* renderArena)
+{
+ RenderLayer* layer = m_layer;
+
+ RenderContainer::detach(renderArena);
+
+ if (layer)
+ layer->detach(renderArena);
}
short RenderBox::contentWidth() const
diff --git a/WebCore/khtml/rendering/render_box.h b/WebCore/khtml/rendering/render_box.h
index 213c3a3..472bb93 100644
--- a/WebCore/khtml/rendering/render_box.h
+++ b/WebCore/khtml/rendering/render_box.h
@@ -49,6 +49,8 @@ public:
virtual void close();
+ virtual void detach(RenderArena* renderArena);
+
virtual short minWidth() const { return m_minWidth; }
virtual short maxWidth() const { return m_maxWidth; }
diff --git a/WebCore/khtml/rendering/render_br.cpp b/WebCore/khtml/rendering/render_br.cpp
index 67e570a..4cccfbe 100644
--- a/WebCore/khtml/rendering/render_br.cpp
+++ b/WebCore/khtml/rendering/render_br.cpp
@@ -27,7 +27,6 @@ using namespace khtml;
RenderBR::RenderBR(DOM::NodeImpl* node)
: RenderText(node, new DOM::DOMStringImpl(QChar('\n')))
{
- m_hasReturn = true;
}
RenderBR::~RenderBR()
diff --git a/WebCore/khtml/rendering/render_container.cpp b/WebCore/khtml/rendering/render_container.cpp
index dd5ae87..fcbdfed 100644
--- a/WebCore/khtml/rendering/render_container.cpp
+++ b/WebCore/khtml/rendering/render_container.cpp
@@ -45,15 +45,21 @@ RenderContainer::RenderContainer(DOM::NodeImpl* node)
RenderContainer::~RenderContainer()
{
+}
+
+void RenderContainer::detach(RenderArena* renderArena)
+{
RenderObject* next;
for(RenderObject* n = m_first; n; n = next ) {
n->removeFromSpecialObjects();
n->setParent(0);
next = n->nextSibling();
- n->detach();
+ n->detach(renderArena);
}
m_first = 0;
m_last = 0;
+
+ RenderObject::detach(renderArena);
}
void RenderContainer::addChild(RenderObject *newChild, RenderObject *beforeChild)
diff --git a/WebCore/khtml/rendering/render_container.h b/WebCore/khtml/rendering/render_container.h
index 14d1d43..68eb913 100644
--- a/WebCore/khtml/rendering/render_container.h
+++ b/WebCore/khtml/rendering/render_container.h
@@ -43,6 +43,8 @@ public:
virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = 0);
virtual void removeChild(RenderObject *oldChild);
+ virtual void detach(RenderArena* renderArena);
+
virtual RenderObject* removeChildNode(RenderObject* child);
virtual void appendChildNode(RenderObject* child);
virtual void insertChildNode(RenderObject* child, RenderObject* before);
diff --git a/WebCore/khtml/rendering/render_flow.cpp b/WebCore/khtml/rendering/render_flow.cpp
index 6c85d68..d7eea84 100644
--- a/WebCore/khtml/rendering/render_flow.cpp
+++ b/WebCore/khtml/rendering/render_flow.cpp
@@ -36,6 +36,8 @@
#include "rendering/render_root.h"
#include "xml/dom_nodeimpl.h"
#include "xml/dom_docimpl.h"
+#include "html/html_formimpl.h"
+
#include "khtmlview.h"
#include "htmltags.h"
@@ -68,7 +70,7 @@ void RenderFlow::setStyle(RenderStyle *_style)
setInline(false);
if ((isPositioned() || isRelPositioned() || style()->overflow()==OHIDDEN) && !m_layer)
- m_layer = new RenderLayer(this);
+ m_layer = new (renderArena()) RenderLayer(this);
if(isFloating() || !style()->display() == INLINE)
setInline(false);
@@ -245,6 +247,11 @@ void RenderFlow::layout()
m_topMarginQuirk = style()->marginTop().quirk;
m_bottomMarginQuirk = style()->marginBottom().quirk;
+
+ if (element() && element()->id() == ID_FORM && element()->isMalformed())
+ // See if this form is malformed (i.e., unclosed). If so, don't give the form
+ // a bottom margin.
+ m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
}
// A quirk that has become an unfortunate standard. Positioned elements, floating elements
@@ -1223,181 +1230,285 @@ static inline RenderObject *next(RenderObject *par, RenderObject *current)
return next;
}
-
-void RenderFlow::calcMinMaxWidth()
+void RenderFlow::calcInlineMinMaxWidth()
{
- KHTMLAssert( !minMaxKnown() );
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(RenderBox)::calcMinMaxWidth() this=" << this << endl;
-#endif
-
- m_minWidth = 0;
- m_maxWidth = 0;
-
- if (isInline()) {
- setMinMaxKnown();
- return;
- }
-
+ int inlineMax=0;
+ int inlineMin=0;
+
int cw = containingBlock()->contentWidth();
- // non breaking space
- const QChar nbsp = 0xa0;
-
RenderObject *child = firstChild();
RenderObject *prevchild = 0;
- if(childrenInline())
+
+ // If we are at the start of a line, we want to ignore all white-space.
+ // Also strip spaces if we previously had text that ended in a trailing space.
+ bool stripFrontSpaces = true;
+ RenderObject* trailingSpaceChild = 0;
+
+ while(child != 0)
{
- int inlineMax=0;
- int currentMin=0;
- int inlineMin=0;
- bool noBreak=false;
- bool prevWasText = false;
-
- while(child != 0)
+ // positioned children don't affect the minmaxwidth
+ if (child->isPositioned())
{
- // positioned children don't affect the minmaxwidth
- if (child->isPositioned())
- {
- child = next(this, child);
- continue;
- }
+ child = next(this, child);
+ continue;
+ }
- if( !child->isBR() )
- {
- RenderStyle* cstyle = child->style();
+ if( !child->isBR() )
+ {
+ // Step One: determine whether or not we need to go ahead and
+ // terminate our current line. Each discrete chunk can become
+ // the new min-width, if it is the widest chunk seen so far, and
+ // it can also become the max-width.
+
+ // Children fall into three categories:
+ // (1) An inline flow object. These objects always have a min/max of 0,
+ // and are included in the iteration solely so that their margins can
+ // be added in. XXXdwh Just adding in the margins is totally bogus, since
+ // a <span> could wrap to multiple lines. Technically the left margin should
+ // be considered part of the first descendant's start, and the right margin
+ // should be considered part of the last descendant's end. Leave this alone
+ // for now, but fix later.
+ //
+ // (2) An inline non-text non-flow object, e.g., an inline replaced element.
+ // These objects can always be on a line by themselves, so in this situation
+ // we need to go ahead and break the current line, and then add in our own
+ // margins and min/max width on its own line, and then terminate the line.
+ //
+ // (3) A text object. Text runs can have breakable characters at the start,
+ // the middle or the end. They may also lose whitespace off the front if
+ // we're already ignoring whitespace. In order to compute accurate min-width
+ // information, we need three pieces of information.
+ // (a) the min-width of the first non-breakable run. Should be 0 if the text string
+ // starts with whitespace.
+ // (b) the min-width of the last non-breakable run. Should be 0 if the text string
+ // ends with whitespace.
+ // (c) the min/max width of the string (trimmed for whitespace).
+ //
+ // If the text string starts with whitespace, then we need to go ahead and
+ // terminate our current line (unless we're already in a whitespace stripping
+ // mode.
+ //
+ // If the text string has a breakable character in the middle, but didn't start
+ // with whitespace, then we add the width of the first non-breakable run and
+ // then end the current line. We then need to use the intermediate min/max width
+ // values (if any of them are larger than our current min/max). We then look at
+ // the width of the last non-breakable run and use that to start a new line
+ // (unless we end in whitespace).
+ RenderStyle* cstyle = child->style();
+ short childMin = 0;
+ short childMax = 0;
+
+ if (!child->isText()) {
+ // Case (1) and (2). Inline replaced and inline flow elements. Both
+ // add in their margins to their min/max values.
int margins = 0;
- LengthType type = cstyle->marginLeft().type;
+ LengthType type = cstyle->marginLeft().type;
if ( type != Variable )
margins += (type == Fixed ? cstyle->marginLeft().value : child->marginLeft());
- type = cstyle->marginRight().type;
+ type = cstyle->marginRight().type;
if ( type != Variable )
margins += (type == Fixed ? cstyle->marginRight().value : child->marginRight());
- int childMin = child->minWidth() + margins;
- int childMax = child->maxWidth() + margins;
- if (child->isText() && static_cast<RenderText *>(child)->length() > 0)
- {
-
- int ti = cstyle->textIndent().minWidth(cw);
- childMin+=ti;
- childMax+=ti;
-
- bool hasNbsp=false;
- RenderText* t = static_cast<RenderText *>(child);
- if (t->data()[0] == nbsp) //inline starts with nbsp
- {
- currentMin += childMin;
- inlineMax += childMax;
- hasNbsp = true;
+ childMin += margins;
+ childMax += margins;
+ }
+
+ if (!(child->isInline() && child->isFlow()) && !child->isText()) {
+ // Case (2). Inline replaced elements.
+ // Go ahead and terminate the current line as far as
+ // minwidth is concerned.
+ childMin += child->minWidth();
+ childMax += child->maxWidth();
+
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ inlineMin = 0;
+
+ // Add our width to the max.
+ inlineMax += childMax;
+
+ // Now check our line.
+ inlineMin = childMin;
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+
+ // Now start a new line.
+ inlineMin = 0;
+
+ // We are no longer stripping whitespace at the start of
+ // a line.
+ if (!child->isFloating())
+ stripFrontSpaces = false;
+ trailingSpaceChild = 0;
+ }
+ else if (child->isText())
+ {
+ // Case (3). Text.
+ RenderText* t = static_cast<RenderText *>(child);
+
+ // Determine if we have a breakable character. Pass in
+ // whether or not we should ignore any spaces at the front
+ // of the string. If those are going to be stripped out,
+ // then they shouldn't be considered in the breakable char
+ // check.
+ bool hasBreakableChar, hasBreak;
+ short beginMin, endMin;
+ bool beginWS, endWS;
+ short beginMax, endMax;
+ t->trimmedMinMaxWidth(beginMin, beginWS, endMin, endWS, hasBreakableChar,
+ hasBreak, beginMax, endMax,
+ childMin, childMax, stripFrontSpaces);
+ if (stripFrontSpaces)
+ trailingSpaceChild = child;
+ else
+ trailingSpaceChild = 0;
+
+ // Add in text-indent.
+ int ti = cstyle->textIndent().minWidth(cw);
+ childMin+=ti; beginMin += ti;
+ childMax+=ti; beginMax += ti;
+
+ // If we have no breakable characters at all,
+ // then this is the easy case. We add ourselves to the current
+ // min and max and continue.
+ if (!hasBreakableChar) {
+ inlineMin += childMin;
+ inlineMax += childMax;
+ }
+ else {
+ // We have a breakable character. Now we need to know if
+ // we start and end with whitespace.
+ if (beginWS) {
+ // Go ahead and end the current line.
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
}
- if (hasNbsp && t->data()[t->length()-1]==nbsp )
- { //inline starts and ends with nbsp
- noBreak=true;
+ else {
+ inlineMin += beginMin;
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ childMin -= ti;
}
- else if (t->data()[t->length()-1] == nbsp && t->data()[0] != ' ')
- { //inline only ends with nbsp
- if(currentMin < childMin) currentMin = childMin;
- inlineMax += childMax;
- noBreak = true;
- hasNbsp = true;
+
+ inlineMin = childMin;
+
+ if (endWS) {
+ // We end in whitespace, which means we can go ahead
+ // and end our current line.
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ inlineMin = 0;
}
- if ( t->hasBreakableChar() )
- noBreak = false;
- prevWasText = true;
- if (hasNbsp)
- {
- if(inlineMin < currentMin) inlineMin = currentMin;
- prevchild = child;
- child = next(this, child);
- hasNbsp = false;
- continue;
+ else {
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ inlineMin = endMin;
}
- }
- prevWasText = false;
- if (noBreak ||
- (prevchild && prevchild->isFloating() && child->isFloating()))
- {
- currentMin += childMin;
- if(inlineMin < currentMin) inlineMin = currentMin;
+
inlineMax += childMax;
- noBreak = false;
}
- else
- {
- currentMin = childMin;
- if(inlineMin < currentMin) inlineMin = currentMin;
- inlineMax += childMax;
- }
-
}
- else
- {
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
- if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
- inlineMin = currentMin = inlineMax = 0;
- }
- prevWasText = false;
- prevchild = child;
- child = next(this, child);
}
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
- if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
+ else
+ {
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
+ inlineMin = inlineMax = 0;
+ stripFrontSpaces = true;
+ trailingSpaceChild = 0;
+ }
+
+ prevchild = child;
+ child = next(this, child);
+ }
+
+ if (trailingSpaceChild && trailingSpaceChild->isText() && !m_pre) {
+ // Collapse away the trailing space at the end of a block.
+ RenderText* t = static_cast<RenderText *>(trailingSpaceChild);
+ const Font *f = t->htmlFont( false );
+ QChar space[1]; space[0] = ' ';
+ int spaceWidth = f->width(space, 1, 0);
+ inlineMax -= spaceWidth;
+ if (inlineMin > inlineMax)
+ inlineMin = inlineMax;
+ }
+
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
// kdDebug( 6040 ) << "m_minWidth=" << m_minWidth
// << " m_maxWidth=" << m_maxWidth << endl;
- }
- else
+}
+
+void RenderFlow::calcBlockMinMaxWidth()
+{
+ RenderObject *child = firstChild();
+ while(child != 0)
{
- while(child != 0)
+ // positioned children don't affect the minmaxwidth
+ if (child->isPositioned())
{
- // positioned children don't affect the minmaxwidth
- if (child->isPositioned())
- {
- child = child->nextSibling();
- continue;
- }
+ child = child->nextSibling();
+ continue;
+ }
- int margin=0;
- // auto margins don't affect minwidth
+ int margin=0;
+ // auto margins don't affect minwidth
- Length ml = child->style()->marginLeft();
- Length mr = child->style()->marginRight();
+ Length ml = child->style()->marginLeft();
+ Length mr = child->style()->marginRight();
- if (style()->textAlign() == KONQ_CENTER)
- {
- if (ml.type==Fixed) margin+=ml.value;
- if (mr.type==Fixed) margin+=mr.value;
- }
- else
+ if (style()->textAlign() == KONQ_CENTER)
+ {
+ if (ml.type==Fixed) margin+=ml.value;
+ if (mr.type==Fixed) margin+=mr.value;
+ }
+ else
+ {
+ if (!(ml.type==Variable) && !(mr.type==Variable))
{
- if (!(ml.type==Variable) && !(mr.type==Variable))
+ if (!(child->style()->width().type==Variable))
{
- if (!(child->style()->width().type==Variable))
- {
- if (child->style()->direction()==LTR)
- margin = child->marginLeft();
- else
- margin = child->marginRight();
- }
+ if (child->style()->direction()==LTR)
+ margin = child->marginLeft();
else
- margin = child->marginLeft()+child->marginRight();
-
+ margin = child->marginRight();
}
- else if (!(ml.type == Variable))
- margin = child->marginLeft();
- else if (!(mr.type == Variable))
- margin = child->marginRight();
+ else
+ margin = child->marginLeft()+child->marginRight();
+
}
+ else if (!(ml.type == Variable))
+ margin = child->marginLeft();
+ else if (!(mr.type == Variable))
+ margin = child->marginRight();
+ }
- if (margin<0) margin=0;
+ if (margin<0) margin=0;
- int w = child->minWidth() + margin;
- if(m_minWidth < w) m_minWidth = w;
- w = child->maxWidth() + margin;
- if(m_maxWidth < w) m_maxWidth = w;
- child = child->nextSibling();
- }
+ int w = child->minWidth() + margin;
+ if(m_minWidth < w) m_minWidth = w;
+ w = child->maxWidth() + margin;
+ if(m_maxWidth < w) m_maxWidth = w;
+ child = child->nextSibling();
}
+}
+
+void RenderFlow::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(RenderBox)::calcMinMaxWidth() this=" << this << endl;
+#endif
+
+ m_minWidth = 0;
+ m_maxWidth = 0;
+
+ if (isInline()) {
+ // Irrelevant, since some enclosing block will actually flow our children.
+ setMinMaxKnown();
+ return;
+ }
+
+ if (childrenInline())
+ calcInlineMinMaxWidth();
+ else
+ calcBlockMinMaxWidth();
+
if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
if (style()->width().isFixed())
@@ -1494,15 +1605,13 @@ void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
newChild->setBlockBidi();
RenderStyle* pseudoStyle=0;
- if ( !isInline() && ( !firstChild() || firstChild() == beforeChild )
- && ( pseudoStyle=style()->getPseudoStyle(RenderStyle::FIRST_LETTER) ) )
+ if (!isInline() && (!firstChild() || firstChild() == beforeChild) && newChild->isText())
{
- if (newChild->isText()) {
- RenderText* newTextChild = static_cast<RenderText*>(newChild);
+ RenderText* newTextChild = static_cast<RenderText*>(newChild);
+ //kdDebug( 6040 ) << "first letter" << endl;
- //kdDebug( 6040 ) << "first letter" << endl;
-
- RenderFlow* firstLetter = new RenderFlow(0 /* anonymous box */);
+ if ( (pseudoStyle=style()->getPseudoStyle(RenderStyle::FIRST_LETTER)) ) {
+ RenderFlow* firstLetter = new (renderArena()) RenderFlow(0 /* anonymous box */);
pseudoStyle->setDisplay( INLINE );
firstLetter->setStyle(pseudoStyle);
@@ -1519,7 +1628,7 @@ void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
//kdDebug( 6040 ) << "letter= '" << DOMString(oldText->substring(0,length)).string() << "'" << endl;
newTextChild->setText(oldText->substring(length,oldText->l-length));
- RenderText* letter = new RenderText(0 /* anonymous object */, oldText->substring(0,length));
+ RenderText* letter = new (renderArena()) RenderText(0 /* anonymous object */, oldText->substring(0,length));
RenderStyle* newStyle = new RenderStyle();
newStyle->inheritFrom(pseudoStyle);
letter->setStyle(newStyle);
@@ -1568,7 +1677,7 @@ void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
}
removeChildNode(anonBox);
- anonBox->detach(); // does necessary cleanup & deletes anonBox
+ anonBox->detach(renderArena()); // does necessary cleanup & deletes anonBox
KHTMLAssert(beforeChild->parent() == this);
}
@@ -1631,7 +1740,7 @@ void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
newStyle->inheritFrom(style());
newStyle->setDisplay(BLOCK);
- RenderFlow *newBox = new RenderFlow(0 /* anonymous box */);
+ RenderFlow *newBox = new (element()->getDocument()->renderArena()) RenderFlow(0 /* anonymous box */);
newBox->setStyle(newStyle);
newBox->setIsAnonymousBox(true);
@@ -1710,7 +1819,7 @@ void RenderFlow::makeChildrenNonInline(RenderObject *box2Start)
newStyle->inheritFrom(style());
newStyle->setDisplay(BLOCK);
- RenderFlow *box = new RenderFlow(0 /* anonymous box */);
+ RenderFlow *box = new (renderArena()) RenderFlow(0 /* anonymous box */);
box->setStyle(newStyle);
box->setIsAnonymousBox(true);
// ### the children have a wrong style!!!
diff --git a/WebCore/khtml/rendering/render_flow.h b/WebCore/khtml/rendering/render_flow.h
index aa94341..e52a619 100644
--- a/WebCore/khtml/rendering/render_flow.h
+++ b/WebCore/khtml/rendering/render_flow.h
@@ -122,7 +122,9 @@ public:
void positionNewFloats();
void clearFloats();
virtual void calcMinMaxWidth();
-
+ void calcInlineMinMaxWidth();
+ void calcBlockMinMaxWidth();
+
virtual bool containsSpecial() { return specialObjects!=0; }
virtual bool hasOverhangingFloats() { return floatBottom() > m_height; }
@@ -130,7 +132,7 @@ public:
// implementation of the following functions is in bidi.cpp
void bidiReorderLine(const BidiIterator &start, const BidiIterator &end);
- BidiIterator findNextLineBreak(BidiIterator &start);
+ BidiIterator findNextLineBreak(BidiIterator &start, QPtrList<BidiIterator>& midpoints);
virtual bool isSelfCollapsingBlock() const { return m_height == 0; }
virtual bool isTopMarginQuirk() const { return m_topMarginQuirk; }
diff --git a/WebCore/khtml/rendering/render_html.cpp b/WebCore/khtml/rendering/render_html.cpp
index 31db5e3..882814f 100644
--- a/WebCore/khtml/rendering/render_html.cpp
+++ b/WebCore/khtml/rendering/render_html.cpp
@@ -22,6 +22,7 @@
#include "rendering/render_html.h"
#include "rendering/render_root.h"
#include "html/html_elementimpl.h"
+#include "xml/dom_docimpl.h"
#include "khtmlview.h"
@@ -32,7 +33,7 @@ using namespace khtml;
RenderHtml::RenderHtml(DOM::HTMLElementImpl* node)
: RenderFlow(node)
{
- m_layer = new RenderLayer(this);
+ m_layer = new (node->getDocument()->renderArena()) RenderLayer(this);
}
RenderHtml::~RenderHtml()
diff --git a/WebCore/khtml/rendering/render_layer.cpp b/WebCore/khtml/rendering/render_layer.cpp
index ce626de..4adc9b8 100644
--- a/WebCore/khtml/rendering/render_layer.cpp
+++ b/WebCore/khtml/rendering/render_layer.cpp
@@ -25,6 +25,8 @@
#include <assert.h>
#include "khtmlview.h"
#include "render_box.h"
+#include "render_arena.h"
+#include "xml/dom_docimpl.h"
using namespace DOM;
using namespace khtml;
@@ -47,6 +49,7 @@ RenderLayer::~RenderLayer()
{
// Child layers will be deleted by their corresponding render objects, so
// our destructor doesn't have to do anything.
+ m_parent = m_previous = m_next = m_first = m_last = 0;
}
void RenderLayer::updateLayerPosition()
@@ -82,6 +85,26 @@ RenderLayer::enclosingPositionedAncestor()
return curr;
}
+void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ return renderArena->allocate(sz);
+}
+
+void RenderLayer::operator delete(void* ptr, size_t sz) {
+ size_t* szPtr = (size_t*)ptr;
+ *szPtr = sz;
+}
+
+void RenderLayer::detach(RenderArena* renderArena)
+{
+ delete this;
+
+
+ // Now perform the destroy.
+ size_t* sz = (size_t*)this;
+ renderArena->free(*sz, (void*)this);
+}
+
void RenderLayer::addChild(RenderLayer *child)
{
if (!firstChild()) {
@@ -202,7 +225,7 @@ RenderLayer::paint(QPainter *p, int x, int y, int w, int h)
if (currRect != paintRect)
p->restore(); // Pop the clip.
- delete node;
+ node->detach(renderer()->element()->getDocument()->renderArena());
}
bool
@@ -234,7 +257,7 @@ RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
if (inside)
break;
}
- delete node;
+ node->detach(renderer()->element()->getDocument()->renderArena());
return inside;
}
@@ -244,6 +267,9 @@ RenderLayer::constructZTree(QRect damageRect,
RenderLayer* rootLayer,
bool eventProcessing)
{
+ // The arena we use for allocating our temporary ztree elements.
+ RenderArena* renderArena = renderer()->element()->getDocument()->renderArena();
+
// This variable stores the result we will hand back.
RenderLayer::RenderZTreeNode* returnNode = 0;
@@ -266,7 +292,7 @@ RenderLayer::constructZTree(QRect damageRect,
convertToLayerCoords(rootLayer, x, y);
QRect layerBounds(x, y, width(), height());
- returnNode = new RenderLayer::RenderZTreeNode(this);
+ returnNode = new (renderArena) RenderZTreeNode(this);
// If we establish a clip rect, then we want to intersect that rect
// with the damage rect to form a new damage rect.
@@ -309,10 +335,10 @@ RenderLayer::constructZTree(QRect damageRect,
(eventProcessing && layerBounds.contains(damageRect.x(),
damageRect.y())) ||
(!eventProcessing && layerBounds.intersects(damageRect))) {
- RenderLayerElement* layerElt = new RenderLayerElement(this, layerBounds,
+ RenderLayerElement* layerElt = new (renderArena) RenderLayerElement(this, layerBounds,
damageRect, x, y);
if (returnNode->child) {
- RenderZTreeNode* leaf = new RenderZTreeNode(layerElt);
+ RenderZTreeNode* leaf = new (renderArena) RenderZTreeNode(layerElt);
leaf->next = returnNode->child;
returnNode->child = leaf;
@@ -338,7 +364,7 @@ RenderLayer::constructZTree(QRect damageRect,
// children.
if (returnNode->layerElement) {
RenderZTreeNode* leaf = returnNode;
- returnNode = new RenderLayer::RenderZTreeNode(this);
+ returnNode = new (renderArena) RenderZTreeNode(this);
returnNode->child = leaf;
}
@@ -470,3 +496,55 @@ void RenderLayer::RenderZTreeNode::constructLayerList(QPtrVector<RenderLayerElem
elt->zindex = explicitZIndex;
}
}
+
+void* RenderLayer::RenderLayerElement::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ void* result = renderArena->allocate(sz);
+ if (result)
+ memset(result, 0, sz);
+ return result;
+}
+
+void RenderLayer::RenderLayerElement::operator delete(void* ptr, size_t sz) {
+ size_t* szPtr = (size_t*)ptr;
+ *szPtr = sz;
+}
+
+void RenderLayer::RenderLayerElement::detach(RenderArena* renderArena)
+{
+ delete this;
+
+ // Now perform the destroy.
+ size_t* sz = (size_t*)this;
+ renderArena->free(*sz, (void*)this);
+}
+
+void* RenderLayer::RenderZTreeNode::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ void* result = renderArena->allocate(sz);
+ if (result)
+ memset(result, 0, sz);
+ return result;
+}
+
+void RenderLayer::RenderZTreeNode::operator delete(void* ptr, size_t sz) {
+ size_t* szPtr = (size_t*)ptr;
+ *szPtr = sz;
+}
+
+void RenderLayer::RenderZTreeNode::detach(RenderArena* renderArena)
+{
+ if (next)
+ next->detach(renderArena);
+ if (child)
+ child->detach(renderArena);
+ if (layerElement)
+ layerElement->detach(renderArena);
+
+ delete this;
+
+ // Now perform the destroy.
+ size_t* sz = (size_t*)this;
+ renderArena->free(*sz, (void*)this);
+}
+
diff --git a/WebCore/khtml/rendering/render_layer.h b/WebCore/khtml/rendering/render_layer.h
index 111e352..626ef3c 100644
--- a/WebCore/khtml/rendering/render_layer.h
+++ b/WebCore/khtml/rendering/render_layer.h
@@ -98,6 +98,19 @@ public:
void paint(QPainter *p, int x, int y, int w, int h);
bool nodeAtPoint(RenderObject::NodeInfo& info, int x, int y);
+ void detach(RenderArena* renderArena);
+
+ // Overloaded new operator. Derived classes must override operator new
+ // in order to allocate out of the RenderArena.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+private:
+ // The normal operator new is disallowed on all render objects.
+ void* operator new(size_t sz) throw() { assert(false); return 0; };
+
public:
// Z-Index Implementation Notes
//
@@ -133,6 +146,18 @@ public:
RenderLayerElement(RenderLayer* l, const QRect& rect, const QRect& clip, int xpos, int ypos)
:layer(l), absBounds(rect), clipRect(clip), zindex(l->zIndex()), zauto(l->hasAutoZIndex()),
x(xpos), y(ypos) {}
+
+ void detach(RenderArena* renderArena);
+
+ // Overloaded new operator. Derived classes must override operator new
+ // in order to allocate out of the RenderArena.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+ // The normal operator new is disallowed.
+ void* operator new(size_t sz) throw() { assert(false); return 0; };
};
// The list of layer elements is built through a recursive examination
@@ -165,11 +190,22 @@ public:
RenderZTreeNode(RenderLayerElement* layerElt)
:layer(layerElt->layer), next(0), child(0), layerElement(layerElt) {}
- ~RenderZTreeNode() { delete next; delete child; delete layerElement; }
+ ~RenderZTreeNode() {}
void constructLayerList(QPtrVector<RenderLayerElement>* mergeTmpBuffer,
QPtrVector<RenderLayerElement>* finalBuffer);
+ void detach(RenderArena* renderArena);
+
+ // Overloaded new operator. Derived classes must override operator new
+ // in order to allocate out of the RenderArena.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+ // The normal operator new is disallowed.
+ void* operator new(size_t sz) throw() { assert(false); return 0; };
};
private:
diff --git a/WebCore/khtml/rendering/render_list.cpp b/WebCore/khtml/rendering/render_list.cpp
index 330aa46..a90b2ef 100644
--- a/WebCore/khtml/rendering/render_list.cpp
+++ b/WebCore/khtml/rendering/render_list.cpp
@@ -24,6 +24,8 @@
#include "render_list.h"
#include "rendering/render_root.h"
+#include "xml/dom_docimpl.h"
+
#include <qpainter.h>
#include "misc/helper.h"
@@ -143,11 +145,11 @@ void RenderListItem::setStyle(RenderStyle *_style)
if(!m_marker && style()->listStyleType() != LNONE) {
- m_marker = new RenderListMarker();
+ m_marker = new (element()->getDocument()->renderArena()) RenderListMarker();
m_marker->setStyle(newStyle);
insertChildNode( m_marker, firstChild() );
} else if ( m_marker && style()->listStyleType() == LNONE) {
- m_marker->detach();
+ m_marker->detach(element()->getDocument()->renderArena());
m_marker = 0;
}
else if ( m_marker ) {
diff --git a/WebCore/khtml/rendering/render_object.cpp b/WebCore/khtml/rendering/render_object.cpp
index 19e9b54..7837d7b 100644
--- a/WebCore/khtml/rendering/render_object.cpp
+++ b/WebCore/khtml/rendering/render_object.cpp
@@ -32,14 +32,26 @@
#include <kdebug.h>
#include <qpainter.h>
#include "khtmlview.h"
+#include "render_arena.h"
#include <assert.h>
using namespace DOM;
using namespace khtml;
+void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ return renderArena->allocate(sz);
+}
+
+void RenderObject::operator delete(void* ptr, size_t sz) {
+ size_t* szPtr = (size_t*)ptr;
+ *szPtr = sz;
+}
+
RenderObject *RenderObject::createObject(DOM::NodeImpl* node, RenderStyle* style)
{
RenderObject *o = 0;
+ RenderArena* arena = node->getDocument()->renderArena();
switch(style->display())
{
case NONE:
@@ -52,12 +64,12 @@ RenderObject *RenderObject::createObject(DOM::NodeImpl* node, RenderStyle* styl
// to suffice. -dwh
if (style->display() == BLOCK && node->id() == ID_TD &&
node->getDocument()->parseMode() != DocumentImpl::Strict)
- o = new RenderTableCell(node);
+ o = new (arena) RenderTableCell(node);
else
- o = new RenderFlow(node);
+ o = new (arena) RenderFlow(node);
break;
case LIST_ITEM:
- o = new RenderListItem(node);
+ o = new (arena) RenderListItem(node);
break;
case RUN_IN:
case COMPACT:
@@ -67,32 +79,31 @@ RenderObject *RenderObject::createObject(DOM::NodeImpl* node, RenderStyle* styl
case INLINE_TABLE:
// ### set inline/block right
//kdDebug( 6040 ) << "creating RenderTable" << endl;
- o = new RenderTable(node);
+ o = new (arena) RenderTable(node);
break;
case TABLE_ROW_GROUP:
case TABLE_HEADER_GROUP:
case TABLE_FOOTER_GROUP:
- o = new RenderTableSection(node);
+ o = new (arena) RenderTableSection(node);
break;
case TABLE_ROW:
- o = new RenderTableRow(node);
+ o = new (arena) RenderTableRow(node);
break;
case TABLE_COLUMN_GROUP:
case TABLE_COLUMN:
- o = new RenderTableCol(node);
+ o = new (arena) RenderTableCol(node);
break;
case TABLE_CELL:
- o = new RenderTableCell(node);
+ o = new (arena) RenderTableCell(node);
break;
case TABLE_CAPTION:
- o = new RenderTableCaption(node);
+ o = new (arena) RenderTableCaption(node);
break;
}
if(o) o->setStyle(style);
return o;
}
-
RenderObject::RenderObject(DOM::NodeImpl* node)
: CachedObjectClient(),
m_style( 0 ),
@@ -864,11 +875,31 @@ void RenderObject::removeFromSpecialObjects()
}
}
-void RenderObject::detach()
+RenderArena* RenderObject::renderArena() {
+ DOM::NodeImpl* elt = element();
+ RenderObject* current = parent();
+ while (!elt && current) {
+ elt = current->element();
+ current = current->parent();
+ }
+ if (!elt)
+ return 0;
+ return elt->getDocument()->renderArena();
+}
+
+
+void RenderObject::detach(RenderArena* renderArena)
{
remove();
+
+ m_next = m_previous = 0;
+
// by default no refcounting
delete this;
+
+ // Now perform the destroy.
+ size_t* sz = (size_t*)this;
+ renderArena->free(*sz, (void*)this);
}
FindSelectionResult RenderObject::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset )
diff --git a/WebCore/khtml/rendering/render_object.h b/WebCore/khtml/rendering/render_object.h
index 39b722a..fd61bee 100644
--- a/WebCore/khtml/rendering/render_object.h
+++ b/WebCore/khtml/rendering/render_object.h
@@ -37,6 +37,7 @@ class QPainter;
class QTextStream;
class CSSStyle;
class KHTMLView;
+class RenderArena;
#ifndef NDEBUG
#define KHTMLAssert( x ) if( !(x) ) { \
@@ -121,6 +122,20 @@ public:
static RenderObject *createObject(DOM::NodeImpl* node, RenderStyle* style);
+ // Overloaded new operator. Derived classes must override operator new
+ // in order to allocate out of the RenderArena.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+private:
+ // The normal operator new is disallowed on all render objects.
+ void* operator new(size_t sz) throw() { assert(false); return 0; };
+
+public:
+ RenderArena* renderArena();
+
// some helper functions...
virtual bool childrenInline() const { return false; }
virtual bool isRendered() const { return false; }
@@ -404,7 +419,7 @@ public:
virtual short minWidth() const { return 0; }
virtual short maxWidth() const { return 0; }
-
+
RenderStyle* style() const { return m_style; }
RenderStyle* style( bool firstLine ) const {
RenderStyle *s = m_style;
@@ -464,7 +479,7 @@ public:
virtual void calcVerticalMargins() {}
void removeFromSpecialObjects();
- virtual void detach();
+ virtual void detach(RenderArena* renderArena);
const QFont &font(bool firstLine) const {
return style( firstLine )->font();
diff --git a/WebCore/khtml/rendering/render_replaced.cpp b/WebCore/khtml/rendering/render_replaced.cpp
index 29ca898..e1e4f27 100644
--- a/WebCore/khtml/rendering/render_replaced.cpp
+++ b/WebCore/khtml/rendering/render_replaced.cpp
@@ -23,6 +23,8 @@
#include "render_replaced.h"
#include "render_root.h"
+#include "render_arena.h"
+
#include <assert.h>
#include <qwidget.h>
#include <qpainter.h>
@@ -120,7 +122,7 @@ RenderWidget::RenderWidget(DOM::NodeImpl* node)
ref();
}
-void RenderWidget::detach()
+void RenderWidget::detach(RenderArena* renderArena)
{
remove();
@@ -131,6 +133,7 @@ void RenderWidget::detach()
m_widget->removeEventFilter( this );
m_widget->setMouseTracking( false );
}
+
deref();
}
diff --git a/WebCore/khtml/rendering/render_replaced.h b/WebCore/khtml/rendering/render_replaced.h
index 356adc8..ee6ee02 100644
--- a/WebCore/khtml/rendering/render_replaced.h
+++ b/WebCore/khtml/rendering/render_replaced.h
@@ -74,7 +74,7 @@ public:
virtual bool isWidget() const { return true; };
- virtual void detach();
+ virtual void detach(RenderArena* renderArena);
virtual void layout( );
QWidget *widget() const { return m_widget; }
diff --git a/WebCore/khtml/rendering/render_root.cpp b/WebCore/khtml/rendering/render_root.cpp
index cdb7645..52fa062 100644
--- a/WebCore/khtml/rendering/render_root.cpp
+++ b/WebCore/khtml/rendering/render_root.cpp
@@ -20,6 +20,7 @@
*/
#include "rendering/render_root.h"
#include "render_layer.h"
+#include "xml/dom_docimpl.h"
#include "khtmlview.h"
#include <kdebug.h>
@@ -62,7 +63,7 @@ RenderRoot::RenderRoot(DOM::NodeImpl* node, KHTMLView *view)
m_selectionEndPos = -1;
// Create a new root layer for our layer hierarchy.
- m_layer = new RenderLayer(this);
+ m_layer = new (node->getDocument()->renderArena()) RenderLayer(this);
}
RenderRoot::~RenderRoot()
diff --git a/WebCore/khtml/rendering/render_table.cpp b/WebCore/khtml/rendering/render_table.cpp
index e131172..63c9815 100644
--- a/WebCore/khtml/rendering/render_table.cpp
+++ b/WebCore/khtml/rendering/render_table.cpp
@@ -31,6 +31,7 @@
#include "rendering/render_table.h"
#include "html/html_tableimpl.h"
#include "misc/htmltags.h"
+#include "xml/dom_docimpl.h"
#include <kglobal.h>
@@ -211,7 +212,7 @@ void RenderTable::addChild(RenderObject *child, RenderObject *beforeChild)
return;
} else {
// kdDebug( 6040 ) << "creating anonymous table section" << endl;
- o = new RenderTableSection(0 /* anonymous */);
+ o = new (renderArena()) RenderTableSection(0 /* anonymous */);
RenderStyle *newStyle = new RenderStyle();
newStyle->inheritFrom(style());
newStyle->setDisplay(TABLE_ROW_GROUP);
@@ -1010,17 +1011,15 @@ void RenderTable::calcWidth()
calcAbsoluteHorizontal();
}
- int borderWidth = borderLeft() + borderRight();
RenderObject *cb = containingBlock();
- int availableWidth = cb->contentWidth() - borderWidth;
-
+ int availableWidth = cb->contentWidth();
LengthType widthType = style()->width().type;
if(widthType > Relative) {
- // Percent or fixed table
+ // Percent or fixed table
m_width = style()->width().minWidth( availableWidth );
if(m_minWidth > m_width) m_width = m_minWidth;
- //kdDebug( 6040 ) << "1 width=" << m_width << " minWidth=" << m_minWidth << " availableWidth=" << availableWidth << " " << endl;
+ //kdDebug( 6040 ) << "1 width=" << m_width << " minWidth=" << m_minWidth << " availableWidth=" << availableWidth << " " << endl;
} else if (hasPercent) {
m_width = KMIN(short( availableWidth ),m_maxWidth);
// kdDebug( 6040 ) << "width=" << m_width << " maxPercent=" << maxPercent << " maxVar=" << maxVar << " " << endl;
@@ -1030,7 +1029,7 @@ void RenderTable::calcWidth()
// restrict width to what we really have in case we flow around floats
if ( style()->flowAroundFloats() && cb->isFlow() )
- m_width = QMIN( static_cast<RenderFlow *>(cb)->lineWidth( m_y ) - borderWidth, m_width );
+ m_width = QMIN( static_cast<RenderFlow *>(cb)->lineWidth( m_y ), m_width );
m_width = KMAX (m_width, m_minWidth);
@@ -1056,8 +1055,6 @@ void RenderTable::calcWidth()
calcFinalColMax(c, col);
}
}
-
- m_width += borderWidth;
}
void RenderTable::calcColWidth(void)
@@ -1601,7 +1598,7 @@ void RenderTable::setCellWidths()
{
if ( ( indx = c-cell->colSpan()+1) < 0 )
indx = 0;
- int w = columnPos[c+1] - columnPos[ indx ] - spacing ; //- padding*2;
+ int w = columnPos[c+1] - columnPos[ indx ] - spacing; //- padding*2;
#ifdef TABLE_DEBUG
kdDebug( 6040 ) << "0x" << this << ": setting width " << r << "/" << indx << "-" << c << " (0x" << cell << "): " << w << " " << endl;
@@ -1895,7 +1892,7 @@ void RenderTableSection::addChild(RenderObject *child, RenderObject *beforeChild
return;
} else {
kdDebug( 6040 ) << "creating anonymous table row" << endl;
- row = new RenderTableRow(0 /* anonymous table */);
+ row = new (renderArena()) RenderTableRow(0 /* anonymous table */);
RenderStyle *newStyle = new RenderStyle();
newStyle->inheritFrom(style());
newStyle->setDisplay(TABLE_ROW);
@@ -1986,7 +1983,7 @@ void RenderTableRow::addChild(RenderObject *child, RenderObject *beforeChild)
return;
} else {
// kdDebug( 6040 ) << "creating anonymous table cell" << endl;
- cell = new RenderTableCell(0 /* anonymous object */);
+ cell = new (renderArena()) RenderTableCell(0 /* anonymous object */);
RenderStyle *newStyle = new RenderStyle();
newStyle->inheritFrom(style());
newStyle->setDisplay(TABLE_CELL);
diff --git a/WebCore/khtml/rendering/render_text.cpp b/WebCore/khtml/rendering/render_text.cpp
index 6885b6f..da74115 100644
--- a/WebCore/khtml/rendering/render_text.cpp
+++ b/WebCore/khtml/rendering/render_text.cpp
@@ -28,6 +28,8 @@
#include "rendering/render_root.h"
#include "rendering/break_lines.h"
#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "render_arena.h"
#include "misc/loader.h"
@@ -38,6 +40,25 @@
using namespace khtml;
using namespace DOM;
+void TextSlave::detach(RenderArena* renderArena)
+{
+ delete this;
+
+ // Now perform the destroy.
+ size_t* sz = (size_t*)this;
+ renderArena->free(*sz, (void*)this);
+}
+
+void* TextSlave::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ return renderArena->allocate(sz);
+}
+
+void TextSlave::operator delete(void* ptr, size_t sz) {
+ size_t* szPtr = (size_t*)ptr;
+ *szPtr = sz;
+}
+
void TextSlave::printSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos)
{
if(startPos > m_len) return;
@@ -226,7 +247,7 @@ FindSelectionResult TextSlave::checkSelectionPoint(int _x, int _y, int _tx, int
TextSlaveArray::TextSlaveArray()
{
- setAutoDelete(true);
+ setAutoDelete(false);
}
int TextSlaveArray::compareItems( Item d1, Item d2 )
@@ -289,7 +310,6 @@ RenderText::RenderText(DOM::NodeImpl* node, DOMStringImpl *_str)
KHTMLAssert(!str || !str->l || str->s);
m_selectionState = SelectionNone;
- m_hasReturn = true;
#ifdef DEBUG_LAYOUT
QConstString cstr(str->s, str->l);
@@ -315,20 +335,30 @@ void RenderText::setStyle(RenderStyle *_style)
RenderText::~RenderText()
{
- deleteSlaves();
if(str) str->deref();
}
+void RenderText::detach(RenderArena* renderArena)
+{
+ deleteSlaves();
+ RenderObject::detach(renderArena);
+}
+
void RenderText::deleteSlaves()
{
// this is a slight variant of QArray::clear().
// We don't delete the array itself here because its
// likely to be used in the same size later again, saves
// us resize() calls
+ RenderArena* arena = element()->getDocument()->renderArena();
unsigned int len = m_lines.size();
- for(unsigned int i=0; i < len; i++)
+ for(unsigned int i=0; i < len; i++) {
+ TextSlave* s = m_lines.at(i);
+ if (s)
+ s->detach(arena);
m_lines.remove(i);
-
+ }
+
KHTMLAssert(m_lines.count() == 0);
}
@@ -704,62 +734,145 @@ void RenderText::print( QPainter *p, int x, int y, int w, int h,
printObject(p, x, y, w, h, tx, ty);
}
+void RenderText::trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
+ short& endMinW, bool& endWS,
+ bool& hasBreakableChar, bool& hasBreak,
+ short& beginMaxW, short& endMaxW,
+ short& minW, short& maxW, bool& stripFrontSpaces)
+{
+ int len = str->l;
+ bool isPre = style()->whiteSpace() == PRE;
+ if (isPre)
+ stripFrontSpaces = false;
+
+ minW = m_minWidth;
+ maxW = m_maxWidth;
+ beginWS = stripFrontSpaces ? false : m_hasBeginWS;
+ // Handle the case where all space got stripped.
+ endWS = stripFrontSpaces && len > 0 && str->containsOnlyWhitespace() ? false : m_hasEndWS;
+
+ beginMinW = m_beginMinWidth;
+ endMinW = m_endMinWidth;
+
+ hasBreakableChar = m_hasBreakableChar;
+ hasBreak = false; // XXXdwh will need to make this work eventually.
+ // m_hasBreak;
+
+ if (len == 0)
+ return;
+
+ if (stripFrontSpaces && str->s[0].direction() == QChar::DirWS) {
+ const Font *f = htmlFont( false );
+ QChar space[1]; space[0] = ' ';
+ int spaceWidth = f->width(space, 1, 0);
+ maxW -= spaceWidth;
+ }
+
+ stripFrontSpaces = !isPre && endWS;
+
+ if (style()->whiteSpace() == NOWRAP)
+ minW = maxW;
+ else if (minW > maxW)
+ minW = maxW;
+
+ // Compute our max widths by scanning the string for newlines.
+ if (hasBreak) {
+ // XXXdwh this will only be an issue for white-space: pre inlines and
+ // not for the <pre> element itself.
+ }
+}
+
void RenderText::calcMinMaxWidth()
{
KHTMLAssert( !minMaxKnown() );
// ### calc Min and Max width...
- m_minWidth = 0;
+ m_minWidth = m_beginMinWidth = m_endMinWidth = 0;
m_maxWidth = 0;
+ if (isBR())
+ return;
+
int currMinWidth = 0;
int currMaxWidth = 0;
- m_hasReturn = false;
- m_hasBreakableChar = false;
-
+ m_hasBreakableChar = m_hasBreak = m_hasBeginWS = m_hasEndWS = false;
+
// ### not 100% correct for first-line
const Font *f = htmlFont( false );
int len = str->l;
- if ( len == 1 && str->s->latin1() == '\n' )
- m_hasReturn = true;
+ bool ignoringSpaces = false;
+ bool isSpace = false;
+ bool isPre = style()->whiteSpace() == PRE;
+ bool firstWord = true;
for(int i = 0; i < len; i++)
{
+ // XXXdwh Wrong in the first stage. Will stop mutating newlines
+ // in a second stage.
+ if (str->s[i] == '\n') {
+ if (isPre)
+ m_hasBreak = true;
+ else
+ str->s[i] = ' ';
+ }
+
+ bool oldSpace = isSpace;
+ isSpace = str->s[i].direction() == QChar::DirWS;
+
+ if (isSpace && i == 0)
+ m_hasBeginWS = true;
+ if (isSpace && i == len-1)
+ m_hasEndWS = true;
+
+ if (!ignoringSpaces && !isPre && oldSpace && isSpace)
+ ignoringSpaces = true;
+
+ if (ignoringSpaces && !isSpace)
+ ignoringSpaces = false;
+
+ if (ignoringSpaces)
+ continue;
+
int wordlen = 0;
while( i+wordlen < len && !(isBreakable( str->s, i+wordlen, str->l )) )
wordlen++;
+
if (wordlen)
{
int w = f->width(str->s, str->l, i, wordlen);
currMinWidth += w;
currMaxWidth += w;
+ if (firstWord) {
+ firstWord = false;
+ m_beginMinWidth = w;
+ }
+ m_endMinWidth = w;
+
+ if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
+ currMinWidth = 0;
+
+ i += wordlen-1;
}
- if(i+wordlen < len)
- {
- m_hasBreakableChar = true;
- if ( (*(str->s+i+wordlen)).latin1() == '\n' )
+ else {
+ // Nowrap can never be broken, so don't bother setting the
+ // breakable character boolean.
+ if (style()->whiteSpace() != NOWRAP)
+ m_hasBreakableChar = true;
+
+ if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
+ currMinWidth = 0;
+
+ if (str->s[i] == '\n')
{
- m_hasReturn = true;
- if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
- currMinWidth = 0;
if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth;
currMaxWidth = 0;
}
else
{
- if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
- currMinWidth = 0;
currMaxWidth += f->width( str->s, str->l, i + wordlen );
}
- /* else if( c == '-')
- {
- currMinWidth += minus_width;
- if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
- currMinWidth = 0;
- currMaxWidth += minus_width;
- }*/
}
- i += wordlen;
}
+
if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth;
@@ -870,7 +983,8 @@ short RenderText::baselinePosition( bool firstLine ) const
void RenderText::position(int x, int y, int from, int len, int width, bool reverse, bool firstLine, int spaceAdd)
{
// ### should not be needed!!!
- assert(!(len == 0 || (str->l && len == 1 && *(str->s+from) == '\n') ));
+ if (len == 0 || (str->l && len == 1 && *(str->s+from) == '\n'))
+ return;
reverse = reverse && !style()->visuallyOrdered();
@@ -890,7 +1004,7 @@ void RenderText::position(int x, int y, int from, int len, int width, bool rever
qDebug("setting slave text to *%s*, len=%d, w)=%d" , cstr.string().latin1(), len, width );//" << y << ")" << " height=" << lineHeight(false) << " fontHeight=" << metrics(false).height() << " ascent =" << metrics(false).ascent() << endl;
#endif
- TextSlave *s = new TextSlave(x, y, from, len,
+ TextSlave *s = new (element()->getDocument()->renderArena()) TextSlave(x, y, from, len,
baselinePosition( firstLine ),
width+spaceAdd, reverse, spaceAdd, firstLine);
diff --git a/WebCore/khtml/rendering/render_text.h b/WebCore/khtml/rendering/render_text.h
index cc9f0b9..8c68873 100644
--- a/WebCore/khtml/rendering/render_text.h
+++ b/WebCore/khtml/rendering/render_text.h
@@ -56,6 +56,22 @@ public:
m_firstLine = firstLine;
m_toAdd = toAdd;
}
+
+ void detach(RenderArena* renderArena);
+
+ // Overloaded new operator. Derived classes must override operator new
+ // in order to allocate out of the RenderArena.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+private:
+ // The normal operator new is disallowed.
+ void* operator new(size_t sz) throw() { assert(false); return 0; };
+
+public:
+
void printDecoration( QPainter *pt, RenderText* p, int _tx, int _ty, int decoration, bool begin, bool end);
void printBoxDecorations(QPainter *p, RenderStyle* style, RenderText *parent, int _tx, int _ty, bool begin, bool end);
void printSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos);
@@ -123,7 +139,8 @@ public:
int tx, int ty);
void deleteSlaves();
-
+ virtual void detach(RenderArena* renderArena);
+
DOM::DOMString data() const { return str; }
DOM::DOMStringImpl *string() const { return str; }
@@ -153,7 +170,12 @@ public:
virtual void calcMinMaxWidth();
virtual short minWidth() const { return m_minWidth; }
virtual short maxWidth() const { return m_maxWidth; }
-
+ virtual void trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
+ short& endMinW, bool& endWS,
+ bool& hasBreakableChar, bool& hasBreak,
+ short& beginMaxW, short& endMaxW,
+ short& minW, short& maxW, bool& stripFrontSpaces);
+
// returns the minimum x position of all slaves relative to the parent.
// defaults to 0.
int minXPos() const;
@@ -161,8 +183,6 @@ public:
virtual int xPos() const;
virtual int yPos() const;
- bool hasReturn() const { return m_hasReturn; }
-
virtual const QFont &font();
virtual short verticalPositionHint( bool firstLine ) const;
@@ -183,7 +203,6 @@ public:
virtual void repaint();
- bool hasBreakableChar() const { return m_hasBreakableChar; }
const QFontMetrics &metrics(bool firstLine) const;
const Font *htmlFont(bool firstLine) const;
@@ -210,11 +229,15 @@ protected: // members
short m_lineHeight;
short m_minWidth;
short m_maxWidth;
-
+ short m_beginMinWidth;
+ short m_endMinWidth;
+
SelectionState m_selectionState : 3 ;
- bool m_hasReturn : 1;
- bool m_hasBreakableChar : 1;
-
+ bool m_hasBreakableChar : 1; // Whether or not we can be broken into multiple lines.
+ bool m_hasBreak : 1; // Whether or not we have a hard break (e.g., <pre> with '\n').
+ bool m_hasBeginWS : 1; // Whether or not we begin with WS (only true if we aren't pre)
+ bool m_hasEndWS : 1; // Whether or not we end with WS (only true if we aren't pre)
+
// 19 bits left
};
diff --git a/WebCore/khtml/xml/dom_docimpl.cpp b/WebCore/khtml/xml/dom_docimpl.cpp
index 39a0c9e..6542952 100644
--- a/WebCore/khtml/xml/dom_docimpl.cpp
+++ b/WebCore/khtml/xml/dom_docimpl.cpp
@@ -43,6 +43,7 @@
#include "rendering/render_root.h"
#include "rendering/render_replaced.h"
+#include "render_arena.h"
#include "khtmlview.h"
#include "khtml_part.h"
@@ -233,7 +234,8 @@ DocumentImpl::DocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v)
m_paintDeviceMetrics = 0;
m_view = v;
-
+ m_renderArena = 0;
+
if ( v ) {
m_docLoader = new DocLoader(v->part(), this );
setPaintDevice( m_view );
@@ -322,6 +324,8 @@ DocumentImpl::~DocumentImpl()
m_styleSheets->deref();
if (m_focusNode)
m_focusNode->deref();
+
+ delete m_renderArena;
}
@@ -981,8 +985,11 @@ void DocumentImpl::attach()
if ( m_view )
setPaintDevice( m_view );
+ if (!m_renderArena)
+ m_renderArena = new RenderArena();
+
// Create the rendering tree
- m_render = new RenderRoot(this, m_view);
+ m_render = new (m_renderArena) RenderRoot(this, m_view);
m_styleSelector->computeFontSizes(paintDeviceMetrics(), m_view ? m_view->part()->zoomFactor() : 100);
recalcStyle( Force );
@@ -1003,9 +1010,12 @@ void DocumentImpl::detach()
NodeBaseImpl::detach();
if ( render )
- render->detach();
+ render->detach(m_renderArena);
m_view = 0;
+
+ delete m_renderArena;
+ m_renderArena = 0;
}
void DocumentImpl::setVisuallyOrdered()
diff --git a/WebCore/khtml/xml/dom_docimpl.h b/WebCore/khtml/xml/dom_docimpl.h
index 2753123..b9eaced 100644
--- a/WebCore/khtml/xml/dom_docimpl.h
+++ b/WebCore/khtml/xml/dom_docimpl.h
@@ -44,6 +44,7 @@ class QPaintDevice;
class QPaintDeviceMetrics;
class KHTMLView;
class Tokenizer;
+class RenderArena;
namespace khtml {
class CSSStyleSelector;
@@ -226,6 +227,8 @@ public:
virtual void attach();
virtual void detach();
+ RenderArena* renderArena() { return m_renderArena; }
+
// to get visually ordered hebrew and arabic pages right
void setVisuallyOrdered();
@@ -479,6 +482,8 @@ protected:
bool m_inStyleRecalc;
DOMString m_title;
+
+ RenderArena* m_renderArena;
};
class DocumentFragmentImpl : public NodeBaseImpl
diff --git a/WebCore/khtml/xml/dom_nodeimpl.cpp b/WebCore/khtml/xml/dom_nodeimpl.cpp
index 4729e68..8034e9b 100644
--- a/WebCore/khtml/xml/dom_nodeimpl.cpp
+++ b/WebCore/khtml/xml/dom_nodeimpl.cpp
@@ -949,7 +949,7 @@ void NodeImpl::detach()
// assert(m_attached);
if ( m_render )
- m_render->detach();
+ m_render->detach(getDocument()->renderArena());
m_render = 0;
m_attached = false;
@@ -996,6 +996,15 @@ bool NodeImpl::isReadOnly()
return false;
}
+RenderObject * NodeImpl::previousRenderer()
+{
+ for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
+ if (n->renderer())
+ return n->renderer();
+ }
+ return 0;
+}
+
RenderObject * NodeImpl::nextRenderer()
{
for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
diff --git a/WebCore/khtml/xml/dom_nodeimpl.h b/WebCore/khtml/xml/dom_nodeimpl.h
index 841ac78..f031142 100644
--- a/WebCore/khtml/xml/dom_nodeimpl.h
+++ b/WebCore/khtml/xml/dom_nodeimpl.h
@@ -104,7 +104,10 @@ public:
virtual bool isTextNode() const { return false; }
virtual bool isDocumentNode() const { return false; }
virtual bool isXMLElementNode() const { return false; }
-
+
+ virtual bool isMalformed() { return false; }
+ virtual bool containsOnlyWhitespace() const { return false; }
+
// helper functions not being part of the DOM
// Attention: they assume that the caller did the consistency checking!
void setPreviousSibling(NodeImpl *previous) { m_previous = previous; }
@@ -262,6 +265,7 @@ public:
khtml::RenderObject *renderer() const { return m_render; }
khtml::RenderObject *nextRenderer();
+ khtml::RenderObject *previousRenderer();
void checkSetPrefix(const DOMString &_prefix, int &exceptioncode);
void checkAddChild(NodeImpl *newChild, int &exceptioncode);
diff --git a/WebCore/khtml/xml/dom_stringimpl.cpp b/WebCore/khtml/xml/dom_stringimpl.cpp
index b003883..881228d 100644
--- a/WebCore/khtml/xml/dom_stringimpl.cpp
+++ b/WebCore/khtml/xml/dom_stringimpl.cpp
@@ -128,6 +128,21 @@ DOMStringImpl *DOMStringImpl::split(uint pos)
return str;
}
+bool DOMStringImpl::containsOnlyWhitespace() const
+{
+ if (!s)
+ return true;
+
+ unsigned int i;
+ QChar tab('\t');
+ QChar ret('\r');
+ QChar lf('\n');
+ for (i = 0; i < l; i++)
+ if (s[i].direction() != QChar::DirWS && s[i] != tab && s[i] != ret && s[i] != lf)
+ return false;
+ return true;
+}
+
DOMStringImpl *DOMStringImpl::substring(uint pos, uint len)
{
if( pos >=l ) return new DOMStringImpl();
diff --git a/WebCore/khtml/xml/dom_stringimpl.h b/WebCore/khtml/xml/dom_stringimpl.h
index 903208e..b949025 100644
--- a/WebCore/khtml/xml/dom_stringimpl.h
+++ b/WebCore/khtml/xml/dom_stringimpl.h
@@ -76,7 +76,9 @@ public:
{ return *(s+pos); }
khtml::Length toLength() const;
-
+
+ bool containsOnlyWhitespace() const;
+
// ignores trailing garbage, unlike QString
int toInt(bool* ok=0) const {
int len = l;
diff --git a/WebCore/khtml/xml/dom_textimpl.cpp b/WebCore/khtml/xml/dom_textimpl.cpp
index 9843840..0423d4a 100644
--- a/WebCore/khtml/xml/dom_textimpl.cpp
+++ b/WebCore/khtml/xml/dom_textimpl.cpp
@@ -184,6 +184,13 @@ DOMString CharacterDataImpl::nodeValue() const
return str;
}
+bool CharacterDataImpl::containsOnlyWhitespace() const
+{
+ if (str)
+ return str->containsOnlyWhitespace();
+ return true;
+}
+
void CharacterDataImpl::setNodeValue( const DOMString &_nodeValue, int &exceptioncode )
{
// NO_MODIFICATION_ALLOWED_ERR: taken care of by setData()
@@ -357,8 +364,29 @@ void TextImpl::attach()
ElementImpl* element = static_cast<ElementImpl*>(parentNode());
if (!m_render && element->renderer()) {
- khtml::RenderStyle* _style = element->renderer()->style();
- m_render = new RenderText(this, str);
+ RenderObject* par = element->renderer();
+ khtml::RenderStyle* _style = par->style();
+ bool onlyWS = containsOnlyWhitespace();
+ if (onlyWS) {
+ if (par->isTable() || par->isTableRow() || par->isTableSection())
+ return CharacterDataImpl::attach();
+
+ if (!par->isInline() && _style->whiteSpace() != PRE) {
+ RenderObject* prevRender = previousRenderer();
+ if (par->isFlow() && !par->childrenInline() &&
+ (!prevRender || !prevRender->isInline()))
+ return CharacterDataImpl::attach();
+
+ RenderObject* nextRender = nextRenderer();
+ if ((!par->firstChild() ||
+ nextRender == par->firstChild()))
+ // Whitespace at the start of a block just goes away. Don't even
+ // make a render object for this text.
+ return CharacterDataImpl::attach();
+ }
+ }
+
+ m_render = new (getDocument()->renderArena()) RenderText(this, str);
m_render->setStyle(_style);
parentNode()->renderer()->addChild(m_render, nextRenderer());
}
diff --git a/WebCore/khtml/xml/dom_textimpl.h b/WebCore/khtml/xml/dom_textimpl.h
index 9255477..35da605 100644
--- a/WebCore/khtml/xml/dom_textimpl.h
+++ b/WebCore/khtml/xml/dom_textimpl.h
@@ -52,6 +52,8 @@ public:
virtual void deleteData ( const unsigned long offset, const unsigned long count, int &exceptioncode );
virtual void replaceData ( const unsigned long offset, const unsigned long count, const DOMString &arg, int &exceptioncode );
+ virtual bool containsOnlyWhitespace() const;
+
// DOM methods overridden from parent classes
virtual DOMString nodeValue() const;
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list