diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | 9364f22aed35e1a1e9d07c121510f80be3ab0502 (patch) | |
tree | d49911209b132da58d838efa852daf28d516df21 /WebCore/rendering | |
parent | 87eb0cb35bad8784770ebc807e6c982432e47107 (diff) | |
download | external_webkit-9364f22aed35e1a1e9d07c121510f80be3ab0502.zip external_webkit-9364f22aed35e1a1e9d07c121510f80be3ab0502.tar.gz external_webkit-9364f22aed35e1a1e9d07c121510f80be3ab0502.tar.bz2 |
Initial Contribution
Diffstat (limited to 'WebCore/rendering')
62 files changed, 1874 insertions, 1040 deletions
diff --git a/WebCore/rendering/AutoTableLayout.cpp b/WebCore/rendering/AutoTableLayout.cpp index 8f9feec..43c66cd 100644 --- a/WebCore/rendering/AutoTableLayout.cpp +++ b/WebCore/rendering/AutoTableLayout.cpp @@ -493,6 +493,10 @@ void AutoTableLayout::insertSpanCell(RenderTableCell *cell) void AutoTableLayout::layout() { +#ifdef ANDROID_LAYOUT + if (m_table->isSingleColumn()) + return; +#endif // table layout based on the values collected in the layout structure. int tableWidth = m_table->width() - m_table->bordersPaddingAndSpacing(); int available = tableWidth; diff --git a/WebCore/rendering/CounterNode.cpp b/WebCore/rendering/CounterNode.cpp index c30ca9a..e200383 100644 --- a/WebCore/rendering/CounterNode.cpp +++ b/WebCore/rendering/CounterNode.cpp @@ -25,7 +25,6 @@ #include "CounterNode.h" #include "RenderObject.h" -#include <stdio.h> // FIXME: There's currently no strategy for getting the counter tree updated when new // elements with counter-reset and counter-increment styles are added to the render tree. diff --git a/WebCore/rendering/DataRef.h b/WebCore/rendering/DataRef.h index c8d8072..1e063e6 100644 --- a/WebCore/rendering/DataRef.h +++ b/WebCore/rendering/DataRef.h @@ -1,8 +1,10 @@ /* + * This file is part of the DOM implementation for KDE. + * * Copyright (C) 2000 Lars Knoll (knoll@kde.org) * (C) 2000 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2005, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2005 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,28 +26,58 @@ #ifndef DataRef_h #define DataRef_h -#include <wtf/RefPtr.h> - namespace WebCore { template <typename T> class DataRef { public: - const T* get() const { return m_data.get(); } + DataRef() + : m_data(0) + { + } + + DataRef(const DataRef<T>& d) + { + ASSERT(d.m_data); + m_data = d.m_data; + m_data->ref(); + } - const T& operator*() const { return *get(); } - const T* operator->() const { return get(); } + ~DataRef() + { + if (m_data) + m_data->deref(); + } + + const T* get() const { return m_data; } + + T& operator*() const { return *m_data; } + const T* operator->() const { return m_data; } T* access() { - if (!m_data->hasOneRef()) - m_data = m_data->copy(); - return m_data.get(); + if (!m_data->hasOneRef()) { + m_data->deref(); + m_data = new T(*m_data); + m_data->ref(); + } + return m_data; } void init() { ASSERT(!m_data); - m_data = T::create(); + m_data = new T; + m_data->ref(); + } + + DataRef<T>& operator=(const DataRef<T>& d) + { + ASSERT(d.m_data); + d.m_data->ref(); + if (m_data) + m_data->deref(); + m_data = d.m_data; + return *this; } bool operator==(const DataRef<T>& o) const @@ -63,7 +95,7 @@ public: } private: - RefPtr<T> m_data; + T* m_data; }; } // namespace WebCore diff --git a/WebCore/rendering/HitTestResult.cpp b/WebCore/rendering/HitTestResult.cpp index 6946489..6418f19 100644 --- a/WebCore/rendering/HitTestResult.cpp +++ b/WebCore/rendering/HitTestResult.cpp @@ -1,5 +1,7 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * This file is part of the HTML rendering engine for KDE. + * + * Copyright (C) 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,14 +23,19 @@ #include "config.h" #include "HitTestResult.h" +#include "CSSHelper.h" +#include "Document.h" #include "Frame.h" #include "FrameTree.h" #include "HTMLAnchorElement.h" +#include "HTMLElement.h" #include "HTMLImageElement.h" #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "KURL.h" #include "PlatformScrollBar.h" #include "RenderImage.h" +#include "RenderObject.h" #include "SelectionController.h" #if ENABLE(SVG) @@ -234,7 +241,7 @@ KURL HitTestResult::absoluteImageURL() const else return KURL(); - return m_innerNonSharedNode->document()->completeURL(parseURL(urlString)); + return KURL(m_innerNonSharedNode->document()->completeURL(parseURL(urlString).deprecatedString())); } KURL HitTestResult::absoluteLinkURL() const @@ -252,7 +259,7 @@ KURL HitTestResult::absoluteLinkURL() const else return KURL(); - return m_innerURLElement->document()->completeURL(parseURL(urlString)); + return KURL(m_innerURLElement->document()->completeURL(parseURL(urlString).deprecatedString())); } bool HitTestResult::isLiveLink() const diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index 5deb002..ce7ccb9 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -456,7 +456,7 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi if (maxPositionBottom < curr->height()) maxPositionBottom = curr->height(); } - else if (curr->hasTextChildren() || curr->object()->hasHorizontalBordersOrPadding() || strictMode) { + else if (curr->hasTextChildren() || strictMode) { int ascent = curr->baseline() - curr->yPos(); int descent = curr->height() - ascent; if (maxAscent < ascent) @@ -491,7 +491,7 @@ void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bo else if (curr->yPos() == PositionBottom) curr->setYPos(y + maxHeight - curr->height()); else { - if (!curr->hasTextChildren() && !curr->object()->hasHorizontalBordersOrPadding() && !strictMode) + if (!curr->hasTextChildren() && !strictMode) childAffectsTopBottomPos = false; curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline()); } @@ -565,7 +565,7 @@ void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int bottomPos) } // See if we have text children. If not, then we need to shrink ourselves to fit on the line. - if (!hasTextChildren() && !object()->hasHorizontalBordersOrPadding()) { + if (!hasTextChildren()) { if (yPos() < topPos) setYPos(topPos); if (yPos() + height() > bottomPos) diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 14605fe..0eb2a50 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -486,6 +486,17 @@ void InlineTextBox::paintSelection(GraphicsContext* p, int tx, int ty, RenderSty selectionStartEnd(sPos, ePos); if (sPos >= ePos) return; +#ifdef ANDROID_DO_NOT_DRAW_TEXTFIELD_SELECTION + Node* element = m_object->element(); + if (element) { + Node* ancestor = element->shadowAncestorNode(); + if (ancestor && ancestor->renderer()) { + RenderObject* renderer = ancestor->renderer(); + if (renderer->isTextField() || renderer->isTextArea()) + return; + } + } +#endif Color textColor = style->color(); Color c = object()->selectionBackgroundColor(); diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 0fa0b6f..50794c7 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -37,6 +37,11 @@ #include "RenderTheme.h" #include "RenderView.h" #include "SelectionController.h" +#include "TextStream.h" + +#ifdef ANDROID_LAYOUT +#include "Settings.h" +#endif using namespace std; using namespace WTF; @@ -527,6 +532,10 @@ void RenderBlock::layoutBlock(bool relayoutChildren) int oldWidth = m_width; int oldColumnWidth = desiredColumnWidth(); +#ifdef ANDROID_LAYOUT + int oldVisibleWidth = m_visibleWidth; +#endif + calcWidth(); calcColumnWidth(); @@ -536,6 +545,14 @@ void RenderBlock::layoutBlock(bool relayoutChildren) if (oldWidth != m_width || oldColumnWidth != desiredColumnWidth()) relayoutChildren = true; +#ifdef ANDROID_LAYOUT + const Settings* settings = document()->settings(); + ASSERT(settings); + if (oldVisibleWidth != m_visibleWidth + && settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) + relayoutChildren = true; +#endif + clearFloats(); int previousHeight = m_height; @@ -1813,6 +1830,17 @@ GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int // FIXME: overflow: auto/scroll regions need more math here, since painting in the border box is different from painting in the padding box (one is scrolled, the other is // fixed). GapRects result; +#ifdef ANDROID_DO_NOT_DRAW_TEXTFIELD_SELECTION + Node* node = element(); + if (node) { + Node* ancestor = node->shadowAncestorNode(); + if (ancestor && ancestor->renderer()) { + RenderObject* renderer = ancestor->renderer(); + if (renderer->isTextField() || renderer->isTextArea()) + return result; + } + } +#endif if (!isBlockFlow()) // FIXME: Make multi-column selection gap filling work someday. return result; @@ -2363,20 +2391,17 @@ RenderBlock::lineWidth(int y) const return (result < 0) ? 0 : result; } -int RenderBlock::nextFloatBottomBelow(int height) const +int +RenderBlock::nearestFloatBottom(int height) const { - if (!m_floatingObjects) - return 0; - - int bottom = INT_MAX; + if (!m_floatingObjects) return 0; + int bottom = 0; FloatingObject* r; DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); - for ( ; (r = it.current()); ++it) { - if (r->endY > height) - bottom = min(r->endY, bottom); - } - - return bottom == INT_MAX ? 0 : bottom; + for ( ; (r = it.current()); ++it ) + if (r->endY>height && (r->endY<bottom || bottom==0)) + bottom=r->endY; + return max(bottom, height); } int @@ -2819,7 +2844,7 @@ int RenderBlock::getClearDelta(RenderObject *child) // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default). // FIXME: Note that the remaining space checks aren't quite accurate, since you should be able to clear only some floats (the minimum # needed - // to fit) and not all (we should be using nextFloatBottomBelow and looping). + // to fit) and not all (we should be using nearestFloatBottom and looping). // Do not allow tables to wrap in quirks or even in almost strict mode // (ebay on the PLT, finance.yahoo.com in the real world, versiontracker.com forces even almost strict mode not to work) int result = clearSet ? max(0, bottom - child->yPos()) : 0; @@ -3654,7 +3679,14 @@ void RenderBlock::calcInlinePrefWidths() inlineMax += childMax; child->setPrefWidthsDirty(false); - } else { + + if (static_cast<RenderFlow*>(child)->isWordBreak()) { + // End a line and start a new line. + m_minPrefWidth = max(inlineMin, m_minPrefWidth); + inlineMin = 0; + } + } + else { // Inline replaced elts add in their margins to their min/max values. int margins = 0; Length leftMargin = cstyle->marginLeft(); @@ -3683,7 +3715,7 @@ void RenderBlock::calcInlinePrefWidths() prevFloat = child; } else clearPreviousFloat = false; - + bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak; if (canBreakReplacedElement && (autoWrap || oldAutoWrap) || clearPreviousFloat) { m_minPrefWidth = max(inlineMin, m_minPrefWidth); @@ -3695,7 +3727,7 @@ void RenderBlock::calcInlinePrefWidths() m_maxPrefWidth = max(inlineMax, m_maxPrefWidth); inlineMax = 0; } - + // Add in text-indent. This is added in only once. int ti = 0; if (!addedTextIndent) { @@ -3704,7 +3736,7 @@ void RenderBlock::calcInlinePrefWidths() childMin+=ti; childMax+=ti; } - + // Add our width to the max. inlineMax += childMax; @@ -3727,16 +3759,12 @@ void RenderBlock::calcInlinePrefWidths() stripFrontSpaces = false; trailingSpaceChild = 0; } - } else if (child->isText()) { + } + else if (child->isText()) + { // Case (3). Text. RenderText* t = static_cast<RenderText *>(child); - if (t->isWordBreak()) { - m_minPrefWidth = max(inlineMin, m_minPrefWidth); - inlineMin = 0; - continue; - } - // 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, @@ -3744,7 +3772,7 @@ void RenderBlock::calcInlinePrefWidths() // check. bool hasBreakableChar, hasBreak; int beginMin, endMin; - bool beginWS, endWS; + bool beginWS = false, endWS = false; int beginMax, endMax; t->trimmedPrefWidths(inlineMax, beginMin, beginWS, endMin, endWS, hasBreakableChar, hasBreak, beginMax, endMax, @@ -3778,7 +3806,8 @@ void RenderBlock::calcInlinePrefWidths() // min and max and continue. if (!hasBreakableChar) { inlineMin += childMin; - } else { + } + else { // We have a breakable character. Now we need to know if // we start and end with whitespace. if (beginWS) @@ -3808,7 +3837,8 @@ void RenderBlock::calcInlinePrefWidths() m_maxPrefWidth = max(inlineMax, m_maxPrefWidth); m_maxPrefWidth = max(childMax, m_maxPrefWidth); inlineMax = endMax; - } else + } + else inlineMax += childMax; } } else { @@ -3826,7 +3856,7 @@ void RenderBlock::calcInlinePrefWidths() if (style()->collapseWhiteSpace()) stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild); - + m_minPrefWidth = max(inlineMin, m_minPrefWidth); m_maxPrefWidth = max(inlineMax, m_maxPrefWidth); } @@ -4066,10 +4096,7 @@ void RenderBlock::updateFirstLetter() RenderObject* firstLetterBlock = this; bool hasPseudoStyle = false; while (true) { - // We only honor first-letter if the firstLetterBlock can have children in the DOM. This correctly - // prevents form controls from honoring first-letter. - hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LETTER) - && firstLetterBlock->canHaveChildren(); + hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LETTER); if (hasPseudoStyle) break; RenderObject* parentBlock = firstLetterBlock->parent(); @@ -4396,4 +4423,34 @@ const char* RenderBlock::renderName() const return "RenderBlock"; } +#ifndef NDEBUG + +void RenderBlock::dump(TextStream *stream, DeprecatedString ind) const +{ + if (m_childrenInline) { *stream << " childrenInline"; } + if (m_firstLine) { *stream << " firstLine"; } + + if (m_floatingObjects && !m_floatingObjects->isEmpty()) + { + *stream << " special("; + DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); + FloatingObject *r; + bool first = true; + for ( ; (r = it.current()); ++it ) + { + if (!first) + *stream << ","; + *stream << r->node->renderName(); + first = false; + } + *stream << ")"; + } + + // ### EClear m_clearStatus + + RenderFlow::dump(stream,ind); +} + +#endif + } // namespace WebCore diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index 1b086e9..1f4def5 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -4,7 +4,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2007 David Smith (catfish.man@gmail.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Computer, Inc. + * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -136,12 +136,11 @@ public: RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop); bool generatesLineBoxesForInlineChild(RenderObject*); int skipWhitespace(BidiIterator&, BidiState&); - void fitBelowFloats(int widthToFit, int& availableWidth); BidiIterator findNextLineBreak(BidiIterator& start, BidiState& info); - RootInlineBox* constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool lastLine, RenderObject* endObject); + RootInlineBox* constructLine(const BidiIterator& start, const BidiIterator& end); InlineFlowBox* createLineBoxes(RenderObject*); - void computeHorizontalPositionsForLine(RootInlineBox*, BidiRun* firstRun, BidiRun* logicallyLastRun, bool reachedEnd); - void computeVerticalPositionsForLine(RootInlineBox*, BidiRun*); + void computeHorizontalPositionsForLine(RootInlineBox*, bool reachedEnd); + void computeVerticalPositionsForLine(RootInlineBox*); void checkLinesForOverflow(); void deleteEllipsisLineBoxes(); void checkLinesForTextOverflow(); @@ -156,7 +155,7 @@ public: void paintEllipsisBoxes(PaintInfo&, int tx, int ty); void paintSelection(PaintInfo&, int tx, int ty); void paintCaret(PaintInfo&, CaretType); - + void insertFloatingObject(RenderObject*); void removeFloatingObject(RenderObject*); @@ -179,7 +178,7 @@ public: void addIntrudingFloats(RenderBlock* prev, int xoffset, int yoffset); int addOverhangingFloats(RenderBlock* child, int xoffset, int yoffset, bool makeChildPaintOtherFloats); - int nextFloatBottomBelow(int) const; + int nearestFloatBottom(int height) const; int floatBottom() const; inline int leftBottom(); inline int rightBottom(); @@ -278,6 +277,10 @@ public: int leftSelectionOffset(RenderBlock* rootBlock, int y); int rightSelectionOffset(RenderBlock* rootBlock, int y); +#ifndef NDEBUG + virtual void dump(TextStream*, DeprecatedString ind = "") const; +#endif + // Helper methods for computing line counts and heights for line counts. RootInlineBox* lineAtIndex(int); int lineCount(); @@ -306,8 +309,15 @@ protected: private: Position positionForBox(InlineBox*, bool start = true) const; Position positionForRenderer(RenderObject*, bool start = true) const; - +// columGap() is used by WebKit when hit-testing columns. It's called by +// CacheBuilder when it duplicates the hit-testing logic. +#ifdef ANDROID_EXPOSE_COLUMN_GAP +public: +#endif int columnGap() const; +#ifdef ANDROID_EXPOSE_COLUMN_GAP +private: +#endif void calcColumnWidth(); int layoutColumns(int endOfContent = -1); diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 17bd511..f3be819 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -39,10 +39,18 @@ #include "RenderLayer.h" #include "RenderTableCell.h" #include "RenderTheme.h" +#ifdef ANDROID_LAYOUT +#include "Settings.h" +#include "WebCoreViewBridge.h" +#endif #include "RenderView.h" #include <algorithm> #include <math.h> +#ifdef ANDROID_REDIRECT_IMAGE_INVALIDATES + extern bool gAndroid_treatInvalForScreen; +#endif + using std::min; using std::max; @@ -58,6 +66,9 @@ RenderBox::RenderBox(Node* node) : RenderObject(node) , m_width(0) , m_height(0) +#ifdef ANDROID_LAYOUT + , m_visibleWidth(0) +#endif , m_x(0) , m_y(0) , m_marginLeft(0) @@ -504,7 +515,13 @@ void RenderBox::imageChanged(CachedImage* image) IntPoint phase; IntSize tileSize; backgroundRenderer->calculateBackgroundImageGeometry(bgLayer, absoluteRect.x(), absoluteRect.y(), absoluteRect.width(), absoluteRect.height(), repaintRect, phase, tileSize); +#ifdef ANDROID_REDIRECT_IMAGE_INVALIDATES + gAndroid_treatInvalForScreen = true; // no need to inval the content +#endif view()->repaintViewRectangle(repaintRect); +#ifdef ANDROID_REDIRECT_IMAGE_INVALIDATES + gAndroid_treatInvalForScreen = false; // reset to default +#endif if (repaintRect == absoluteRect) didFullRepaint = true; } @@ -674,8 +691,12 @@ void RenderBox::paintBackgroundExtended(GraphicsContext* context, const Color& c context->setCompositeOperation(CompositeCopy); context->fillRect(rect, baseColor); context->restore(); - } else +#ifdef ANDROID_ALLOW_TRANSPARENT_BACKGROUNDS + } +#else + } else context->clearRect(rect); +#endif } if (bgColor.isValid() && bgColor.alpha() > 0) @@ -1069,6 +1090,16 @@ int RenderBox::relativePositionOffsetY() const void RenderBox::calcWidth() { +#ifdef ANDROID_LAYOUT + if (view()->frameView()) { + const Settings* settings = document()->settings(); + ASSERT(settings); + if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) { + m_visibleWidth = view()->frameView()->getWebCoreViewBridge()->screenWidth(); + } + } +#endif + if (isPositioned()) { calcAbsoluteHorizontal(); return; @@ -1104,6 +1135,15 @@ void RenderBox::calcWidth() m_marginRight = marginRight.calcMinValue(containerWidth); if (treatAsReplaced) m_width = max(width.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight(), minPrefWidth()); +#ifdef ANDROID_LAYOUT + // in SSR mode with replaced box, if the box width is wider than the container width, + // it will be shrinked to fit to the container. + if (containerWidth && (m_width+m_marginLeft+m_marginRight) > containerWidth && + document()->frame()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) { + m_marginLeft = m_marginRight = 0; + m_width = m_minPrefWidth = m_maxPrefWidth = containerWidth; + } +#endif return; } @@ -1146,6 +1186,20 @@ void RenderBox::calcWidth() m_marginRight = 0; calcHorizontalMargins(marginLeft, marginRight, containerWidth); } +#ifdef ANDROID_LAYOUT + // in SSR mode with non-replaced box, we use ANDROID_SSR_MARGIN_PADDING for left/right margin. + // If the box width is wider than the container width, it will be shrinked to fit to the container. + if (containerWidth && !treatAsReplaced && + document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) { + m_width += m_marginLeft + m_marginRight; + m_marginLeft = m_marginLeft > ANDROID_SSR_MARGIN_PADDING ? ANDROID_SSR_MARGIN_PADDING : m_marginLeft; + m_marginRight = m_marginRight > ANDROID_SSR_MARGIN_PADDING ? ANDROID_SSR_MARGIN_PADDING : m_marginRight; + if (m_width > containerWidth) + m_width = m_minPrefWidth = m_maxPrefWidth = containerWidth-(m_marginLeft + m_marginRight); + else + m_width -= (m_marginLeft + m_marginRight); + } +#endif if (containerWidth && containerWidth != (m_width + m_marginLeft + m_marginRight) && !isFloating() && !isInline() && !cb->isFlexibleBox()) { @@ -1285,6 +1339,12 @@ void RenderBox::calcHeight() int height; if (checkMinMaxHeight) { +#ifdef ANDROID_LAYOUT + // in SSR mode, ignore CSS height as layout is so different + if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) + height = m_height; + else +#endif height = calcHeightUsing(style()->height()); if (height == -1) height = m_height; diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index f3743a8..f8786b8 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -199,6 +199,10 @@ protected: int m_width; int m_height; +#ifdef ANDROID_LAYOUT + int m_visibleWidth; +#endif + int m_x; int m_y; diff --git a/WebCore/rendering/RenderContainer.cpp b/WebCore/rendering/RenderContainer.cpp index e538cbe..c152b75 100644 --- a/WebCore/rendering/RenderContainer.cpp +++ b/WebCore/rendering/RenderContainer.cpp @@ -650,6 +650,23 @@ void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, un } } + +#ifdef ANDROID_LAYOUT +bool RenderContainer::hasChildTable() const +{ + if (!firstChild()) + return false; + for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { + if (child->isTable()) { + return true; + } else if (child->hasChildTable() == true) { + return true; + } + } + return false; +} +#endif + #undef DEBUG_LAYOUT } // namespace WebCore diff --git a/WebCore/rendering/RenderContainer.h b/WebCore/rendering/RenderContainer.h index 9838eb7..544af8a 100644 --- a/WebCore/rendering/RenderContainer.h +++ b/WebCore/rendering/RenderContainer.h @@ -60,6 +60,9 @@ public: bool isAfterContent(RenderObject* child) const; virtual VisiblePosition positionForCoordinates(int x, int y); +#ifdef ANDROID_LAYOUT + virtual bool hasChildTable() const; +#endif virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX); diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index fea7565..64088f7 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -124,7 +124,11 @@ void RenderFileUploadControl::updateFromElement() addChild(renderer); } +#ifndef ANDROID_DISABLE_UPLOAD m_button->setDisabled(!theme()->isEnabled(this)); +#else + m_button->setDisabled(true); +#endif // This only supports clearing out the filename, but that's OK because for // security reasons that's the only change the DOM is allowed to make. diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp index 13d6d91..16e44e9 100644 --- a/WebCore/rendering/RenderFlexibleBox.cpp +++ b/WebCore/rendering/RenderFlexibleBox.cpp @@ -29,6 +29,11 @@ #include "RenderLayer.h" #include "RenderView.h" +#ifdef ANDROID_LAYOUT +#include "Document.h" +#include "Settings.h" +#endif + using namespace std; namespace WebCore { @@ -223,6 +228,10 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren) int previousWidth = m_width; int previousHeight = m_height; + +#ifdef ANDROID_LAYOUT + int previousVisibleWidth = m_visibleWidth; +#endif calcWidth(); calcHeight(); @@ -233,6 +242,14 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren) parent()->style()->boxAlign() == BSTRETCH)) relayoutChildren = true; +#ifdef ANDROID_LAYOUT + const Settings* settings = document()->settings(); + ASSERT(settings); + if (previousVisibleWidth != m_visibleWidth + && settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) + relayoutChildren = true; +#endif + m_height = 0; m_overflowHeight = 0; m_flexingChildren = m_stretchingChildren = false; diff --git a/WebCore/rendering/RenderFlow.cpp b/WebCore/rendering/RenderFlow.cpp index 0f4d365..227ba37 100644 --- a/WebCore/rendering/RenderFlow.cpp +++ b/WebCore/rendering/RenderFlow.cpp @@ -550,7 +550,7 @@ IntRect RenderFlow::absoluteClippedOverflowRect() int RenderFlow::lowestPosition(bool includeOverflowInterior, bool includeSelf) const { ASSERT(!isInlineFlow()); - if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) + if (!includeOverflowInterior && hasOverflowClip()) return includeSelf && m_width > 0 ? overflowHeight(false) : 0; int bottom = includeSelf && m_width > 0 ? m_height : 0; @@ -574,7 +574,7 @@ int RenderFlow::lowestPosition(bool includeOverflowInterior, bool includeSelf) c int RenderFlow::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const { ASSERT(!isInlineFlow()); - if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) + if (!includeOverflowInterior && hasOverflowClip()) return includeSelf && m_height > 0 ? overflowWidth(false) : 0; int right = includeSelf && m_height > 0 ? m_width : 0; @@ -598,7 +598,7 @@ int RenderFlow::rightmostPosition(bool includeOverflowInterior, bool includeSelf int RenderFlow::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const { ASSERT(!isInlineFlow()); - if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) + if (!includeOverflowInterior && hasOverflowClip()) return includeSelf && m_height > 0 ? overflowLeft(false) : m_width; int left = includeSelf && m_height > 0 ? 0 : m_width; @@ -861,12 +861,6 @@ void RenderFlow::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, i ow); } -void RenderFlow::calcMargins(int containerWidth) -{ - m_marginLeft = style()->marginLeft().calcMinValue(containerWidth); - m_marginRight = style()->marginRight().calcMinValue(containerWidth); -} - #ifndef NDEBUG void RenderFlow::checkConsistency() const diff --git a/WebCore/rendering/RenderFlow.h b/WebCore/rendering/RenderFlow.h index fd0e097..f933a82 100644 --- a/WebCore/rendering/RenderFlow.h +++ b/WebCore/rendering/RenderFlow.h @@ -102,7 +102,7 @@ public: virtual bool hasColumns() const { return m_hasColumns; } - void calcMargins(int containerWidth); + virtual bool isWordBreak() const { ASSERT(isInlineFlow()); return false; } void checkConsistency() const; diff --git a/WebCore/rendering/RenderFrame.cpp b/WebCore/rendering/RenderFrame.cpp index 15bd24e..c996138 100644 --- a/WebCore/rendering/RenderFrame.cpp +++ b/WebCore/rendering/RenderFrame.cpp @@ -30,6 +30,12 @@ #include "HTMLFrameSetElement.h" #include "HTMLNames.h" +#ifdef FLATTEN_FRAMESET +#include "Frame.h" +#include "Document.h" +#include "RenderView.h" +#endif + namespace WebCore { using namespace HTMLNames; @@ -59,4 +65,32 @@ void RenderFrame::viewCleared() } } +#ifdef FLATTEN_FRAMESET +void RenderFrame::layout() +{ + if (m_widget && m_widget->isFrameView()) { + FrameView* view = static_cast<FrameView*>(m_widget); + RenderView* root = NULL; + if (view->frame() && view->frame()->document() && + view->frame()->document()->renderer() && view->frame()->document()->renderer()->isRenderView()) + root = static_cast<RenderView*>(view->frame()->document()->renderer()); + if (root) { + // Resize the widget so that the RenderView will layout according to those dimensions. + view->resize(m_width, m_height); + view->layout(); + // We can only grow in width and height because if positionFrames gives us a width and we become smaller, + // then the fixup process of forcing the frame to fill extra space will fail. + if (m_width > root->docWidth()) { + view->resize(root->docWidth(), 0); + view->layout(); + } + // Honor the height set by RenderFrameSet::positionFrames unless our document height is larger. + m_height = max(root->docHeight(), m_height); + m_width = max(root->docWidth(), m_width); + } + } + setNeedsLayout(false); +} +#endif + } // namespace WebCore diff --git a/WebCore/rendering/RenderFrame.h b/WebCore/rendering/RenderFrame.h index 49aedd3..d7c8c5a 100644 --- a/WebCore/rendering/RenderFrame.h +++ b/WebCore/rendering/RenderFrame.h @@ -38,6 +38,9 @@ public: virtual const char* renderName() const { return "RenderFrame"; } virtual bool isFrame() const { return true; } +#ifdef FLATTEN_FRAMESET + virtual void layout(); +#endif HTMLFrameElement* element() const { return static_cast<HTMLFrameElement*>(RenderPart::element()); } FrameEdgeInfo edgeInfo() const; diff --git a/WebCore/rendering/RenderFrameSet.cpp b/WebCore/rendering/RenderFrameSet.cpp index a546121..94a7ae9 100644 --- a/WebCore/rendering/RenderFrameSet.cpp +++ b/WebCore/rendering/RenderFrameSet.cpp @@ -38,6 +38,7 @@ #include "MouseEvent.h" #include "RenderFrame.h" #include "RenderView.h" +#include "TextStream.h" namespace WebCore { @@ -47,6 +48,9 @@ RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet) : RenderContainer(frameSet) , m_isResizing(false) , m_isChildResizing(false) +#ifdef FLATTEN_FRAMESET + , m_gridCalculated(false) +#endif { setInline(false); } @@ -328,7 +332,7 @@ void RenderFrameSet::layOutAxis(GridAxis& axis, const Length* grid, int availabl } // If we still have some left over space we probably ended up with a remainder of - // a division. We cannot spread it evenly anymore. If we have any percentage + // a division. We can not spread it evenly anymore. If we have any percentage // columns/rows simply spread the remainder equally over all available percentage columns, // regardless of their size. if (remainingLen && countPercent) { @@ -462,6 +466,10 @@ void RenderFrameSet::layout() FrameView* v = view()->frameView(); m_width = v->visibleWidth(); m_height = v->visibleHeight(); +#ifdef FLATTEN_FRAMESET + // Force a grid recalc. + m_gridCalculated = false; +#endif } size_t cols = frameSet()->totalCols(); @@ -470,11 +478,27 @@ void RenderFrameSet::layout() if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) { m_rows.resize(rows); m_cols.resize(cols); +#ifdef FLATTEN_FRAMESET + m_gridCalculated = false; +#endif } +#ifdef FLATTEN_FRAMESET + if (!m_gridCalculated) { + m_gridCalculated = true; + // Make all the child framesets recalculate their grid. + RenderObject* child = firstChild(); + for (; child; child = child->nextSibling()) { + if (child->isFrameSet()) + static_cast<RenderFrameSet*>(child)->setGridNeedsLayout(); + } +#endif int borderThickness = frameSet()->border(); layOutAxis(m_rows, frameSet()->rowLengths(), m_height - (rows - 1) * borderThickness); layOutAxis(m_cols, frameSet()->colLengths(), m_width - (cols - 1) * borderThickness); +#ifdef FLATTEN_FRAMESET + } +#endif positionFrames(); @@ -500,9 +524,88 @@ void RenderFrameSet::positionFrames() int rows = frameSet()->totalRows(); int cols = frameSet()->totalCols(); - + int yPos = 0; int borderThickness = frameSet()->border(); +#ifdef FLATTEN_FRAMESET + // Keep track of the maximum width of a row which will become the maximum width of the frameset. + int maxWidth = 0; + const Length* rowLengths = frameSet()->rowLengths(); + const Length* colLengths = frameSet()->colLengths(); + + for (int r = 0; r < rows && child; r++) { + int xPos = 0; + int height = m_rows.m_sizes[r]; + int rowHeight = -1; + if (rowLengths) { + Length l = rowLengths[r]; + if (l.isFixed()) + rowHeight = l.value(); + } + for (int c = 0; c < cols && child; c++) { + child->setPos(xPos, yPos); + child->setWidth(m_cols.m_sizes[c]); + child->setHeight(height); + int colWidth = -1; + if (colLengths) { + Length l = colLengths[c]; + if (l.isFixed()) + colWidth = l.value(); + } + if (colWidth && rowHeight) { + child->setNeedsLayout(true); + child->layout(); + } else { + child->layoutIfNeeded(); + } + + ASSERT(child->width() >= m_cols.m_sizes[c]); + m_cols.m_sizes[c] = child->width(); + + height = max(child->height(), height); + xPos += child->width() + borderThickness; + child = child->nextSibling(); + } + ASSERT(height >= m_rows.m_sizes[r]); + m_rows.m_sizes[r] = height; + maxWidth = max(xPos, maxWidth); + yPos += height + borderThickness; + } + + // Compute a new width and height according to the positioning of each expanded child frame. + // Note: we subtract borderThickness because we only count borders between frames. + int newWidth = maxWidth - borderThickness; + int newHeight = yPos - borderThickness; + + // Distribute the extra width and height evenly across the grid. + int dWidth = (m_width - newWidth) / cols; + int dHeight = (m_height - newHeight) / rows; + if (dWidth > 0) { + int availableWidth = m_width - (cols - 1) * borderThickness; + for (int c = 0; c < cols; c++) + availableWidth -= m_cols.m_sizes[c] += dWidth; + // If the extra width did not distribute evenly, add the remainder to + // the last column. + if (availableWidth) + m_cols.m_sizes[cols - 1] += availableWidth; + } + if (dHeight > 0) { + int availableHeight = m_height - (rows - 1) * borderThickness; + for (int r = 0; r < rows; r++) + availableHeight -= m_rows.m_sizes[r] += dHeight; + // If the extra height did not distribute evenly, add the remainder to + // the last row. + if (availableHeight) + m_rows.m_sizes[rows - 1] += availableHeight; + } + // Ensure the rows and columns are filled by falling through to the normal + // layout + m_height = max(m_height, newHeight); + m_width = max(m_width, newWidth); + child = firstChild(); + yPos = 0; +#endif // FLATTEN_FRAMESET + for (int r = 0; r < rows; r++) { int xPos = 0; int height = m_rows.m_sizes[r]; @@ -669,4 +772,20 @@ bool RenderFrameSet::isChildAllowed(RenderObject* child, RenderStyle* style) con return child->isFrame() || child->isFrameSet(); } +#ifndef NDEBUG +void RenderFrameSet::dump(TextStream* stream, DeprecatedString ind) const +{ + *stream << " totalrows=" << frameSet()->totalRows(); + *stream << " totalcols=" << frameSet()->totalCols(); + + for (int i = 1; i <= frameSet()->totalRows(); i++) + *stream << " hSplitvar(" << i << ")=" << m_rows.m_preventResize[i]; + + for (int i = 1; i < frameSet()->totalCols(); i++) + *stream << " vSplitvar(" << i << ")=" << m_cols.m_preventResize[i]; + + RenderContainer::dump(stream,ind); +} +#endif + } // namespace WebCore diff --git a/WebCore/rendering/RenderFrameSet.h b/WebCore/rendering/RenderFrameSet.h index 5401c1b..7c25556 100644 --- a/WebCore/rendering/RenderFrameSet.h +++ b/WebCore/rendering/RenderFrameSet.h @@ -76,6 +76,14 @@ public: bool canResizeRow(const IntPoint&) const; bool canResizeColumn(const IntPoint&) const; +#ifdef FLATTEN_FRAMESET + void setGridNeedsLayout() { m_gridCalculated = false; } +#endif + +#ifndef NDEBUG + virtual void dump(TextStream*, DeprecatedString ind = "") const; +#endif + private: static const int noSplit = -1; @@ -115,6 +123,9 @@ private: bool m_isResizing; bool m_isChildResizing; +#ifdef FLATTEN_FRAMESET + bool m_gridCalculated; +#endif }; } // namespace WebCore diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index 5571723..626b9e7 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -1,10 +1,12 @@ -/* +/** + * This file is part of the DOM implementation for KDE. + * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) * (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com) * (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -36,6 +38,17 @@ #include "HitTestResult.h" #include "Page.h" #include "RenderView.h" +#ifdef ANDROID_LAYOUT +#include "Settings.h" +#endif +#ifdef ANDROID_NAVIGATE_AREAMAPS +#include "HTMLAreaElement.h" +#endif + +#ifdef ANDROID_REDIRECT_IMAGE_INVALIDATES +#include "SkBitmapRef.h" + extern bool gAndroid_treatInvalForScreen; +#endif using namespace std; @@ -53,6 +66,11 @@ RenderImage::RenderImage(Node* node) RenderImage::~RenderImage() { +#ifdef ANDROID_NAVIGATE_AREAMAPS + // Set area elements' RenderImage to null, so they do not reference + // the deleted RenderImage. + setAreaElements(NULL); +#endif if (m_cachedImage) m_cachedImage->deref(this); } @@ -160,10 +178,19 @@ void RenderImage::imageChanged(CachedImage* newImage) } } - if (shouldRepaint) + if (shouldRepaint) { // FIXME: We always just do a complete repaint, since we always pass in the full image // rect at the moment anyway. +#ifdef ANDROID_REDIRECT_IMAGE_INVALIDATES + Image* image = newImage->image(); + NativeImagePtr nativeImagePtr = image->nativeImageForCurrentFrame(); + gAndroid_treatInvalForScreen = nativeImagePtr->accessed(); // no need to inval the content after the first time +#endif repaintRectangle(contentBox()); +#ifdef ANDROID_REDIRECT_IMAGE_INVALIDATES + gAndroid_treatInvalForScreen = false; // reset to default +#endif + } } void RenderImage::resetAnimation() @@ -223,7 +250,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) } if (!m_altText.isEmpty()) { - String text = m_altText; + DeprecatedString text = m_altText.deprecatedString(); text.replace('\\', backslashAsCurrencySymbol()); context->setFont(style()->font()); context->setFillColor(style()->color()); @@ -234,7 +261,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) // Only draw the alt text if it'll fit within the content box, // and only if it fits above the error image. - TextRun textRun(text.characters(), text.length()); + TextRun textRun(reinterpret_cast<const UChar*>(text.unicode()), text.length()); int textWidth = font.width(textRun); if (errorPictureDrawn) { if (usableWidth >= textWidth && font.height() <= imageY) @@ -265,7 +292,7 @@ int RenderImage::minimumReplacedHeight() const HTMLMapElement* RenderImage::imageMap() { HTMLImageElement* i = element() && element()->hasTagName(imgTag) ? static_cast<HTMLImageElement*>(element()) : 0; - return i ? i->document()->getImageMap(i->useMap()) : 0; + return i ? i->document()->getImageMap(i->imageMap()) : 0; } bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction) @@ -351,7 +378,18 @@ int RenderImage::calcReplacedWidth() const int minW = calcReplacedWidthUsing(style()->minWidth()); int maxW = style()->maxWidth().isUndefined() ? width : calcReplacedWidthUsing(style()->maxWidth()); - return max(minW, min(width, maxW)); +#ifdef ANDROID_LAYOUT + width = max(minW, min(width, maxW)); + // in SSR mode, we will fit the image to its container width + if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) { + int cw = containingBlockWidth(); + if (cw && width>cw) + width = cw; + } + return width; +#else + return max(minW, min(width, maxW)); +#endif } int RenderImage::calcReplacedHeight() const @@ -369,7 +407,28 @@ int RenderImage::calcReplacedHeight() const int minH = calcReplacedHeightUsing(style()->minHeight()); int maxH = style()->maxHeight().isUndefined() ? height : calcReplacedHeightUsing(style()->maxHeight()); +#ifdef ANDROID_LAYOUT + height = max(minH, min(height, maxH)); + // in SSR mode, we will fit the image to its container width + if (height && document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) { + int width; + if (isWidthSpecified()) + width = calcReplacedWidthUsing(style()->width()); + else + width = calcAspectRatioWidth(); + int minW = calcReplacedWidthUsing(style()->minWidth()); + int maxW = style()->maxWidth().value() == undefinedLength ? width : + calcReplacedWidthUsing(style()->maxWidth()); + width = max(minW, min(width, maxW)); + + int cw = containingBlockWidth(); + if (cw && width && width>cw) + height = cw * height / width; // preserve aspect ratio + } + return height; +#else return max(minH, min(height, maxH)); +#endif } int RenderImage::calcAspectRatioWidth() const @@ -414,4 +473,18 @@ Image* RenderImage::nullImage() return &sharedNullImage; } +#ifdef ANDROID_NAVIGATE_AREAMAPS +void RenderImage::setAreaElements(RenderImage* image) +{ + HTMLMapElement* map = imageMap(); + if (map) { + for (Node* current = map->firstChild(); current; current = current->traverseNextNode(map)) { + if (current->hasTagName(WebCore::HTMLNames::areaTag)) { + HTMLAreaElement* area = static_cast<HTMLAreaElement*>(current); + area->setMap(image); + } + } + } +} +#endif } // namespace WebCore diff --git a/WebCore/rendering/RenderImage.h b/WebCore/rendering/RenderImage.h index 7b63b06..df51bfd 100644 --- a/WebCore/rendering/RenderImage.h +++ b/WebCore/rendering/RenderImage.h @@ -68,6 +68,15 @@ public: void resetAnimation(); +#ifdef ANDROID_NAVIGATE_AREAMAPS + // If this RenderImage has an imagemap, set its area elements to point to it so they + // can know its bounds for focus navigation and drawing the focus ring. + void setImageForAreaElements() { setAreaElements(this); } +private: + // Helper function, also used to set the area elements to have no RenderImage in the + // destructor, so they do not reference the deleted image. + void setAreaElements(RenderImage* image); +#endif protected: Image* image() { return m_cachedImage ? m_cachedImage->image() : nullImage(); } diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index 20160e0..afd3dfe 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -61,8 +61,11 @@ #include "RenderView.h" #include "SelectionController.h" #include "TextResourceDecoder.h" +#include "TextStream.h" #include <algorithm> -#include <stdio.h> +#ifdef ANDROID_LAYOUT +#include "Settings.h" +#endif using namespace std; @@ -710,11 +713,9 @@ void RenderObject::setChildNeedsLayout(bool b, bool markParents) static inline bool objectIsRelayoutBoundary(const RenderObject *obj) { - // FIXME: In future it may be possible to broaden this condition in order to improve performance. - // Table cells are excluded because even when their CSS height is fixed, their height() - // may depend on their contents. + // FIXME: In future it may be possible to broaden this condition in order to improve performance return obj->isTextField() || obj->isTextArea() - || obj->hasOverflowClip() && !obj->style()->width().isIntrinsicOrAuto() && !obj->style()->height().isIntrinsicOrAuto() && !obj->style()->height().isPercent() && !obj->isTableCell() + || obj->hasOverflowClip() && !obj->style()->width().isIntrinsicOrAuto() && !obj->style()->height().isIntrinsicOrAuto() && !obj->style()->height().isPercent() #if ENABLE(SVG) || obj->isSVGRoot() #endif @@ -1670,17 +1671,24 @@ IntRect RenderObject::paintingRootRect(IntRect& topLevelRect) return result; } -void RenderObject::addPDFURLRect(GraphicsContext* context, const IntRect& rect) +void RenderObject::addPDFURLRect(GraphicsContext* graphicsContext, IntRect rect) { - if (rect.isEmpty()) - return; Node* node = element(); - if (!node || !node->isLink() || !node->isElementNode()) - return; - const AtomicString& href = static_cast<Element*>(node)->getAttribute(hrefAttr); - if (href.isNull()) - return; - context->setURLForRect(node->document()->completeURL(href), rect); + if (node) { + if (graphicsContext) { + if (rect.width() > 0 && rect.height() > 0) { + Element* element = static_cast<Element*>(node); + String href; + if (element->isLink()) + href = element->getAttribute(hrefAttr); + + if (!href.isNull()) { + KURL link = element->document()->completeURL(href.deprecatedString()); + graphicsContext->setURLForRect(link, rect); + } + } + } + } } @@ -1946,6 +1954,78 @@ void RenderObject::dirtyLinesFromChangedChild(RenderObject* child) #ifndef NDEBUG +DeprecatedString RenderObject::information() const +{ + DeprecatedString str; + TextStream ts(&str); + ts << renderName() + << "(" << (style() ? style()->refCount() : 0) << ")" + << ": " << (void*)this << " "; + if (isInline()) + ts << "il "; + if (childrenInline()) + ts << "ci "; + if (isFloating()) + ts << "fl "; + if (isAnonymous()) + ts << "an "; + if (isRelPositioned()) + ts << "rp "; + if (isPositioned()) + ts << "ps "; + if (needsLayout()) + ts << "nl "; + if (style() && style()->zIndex()) + ts << "zI: " << style()->zIndex(); + if (element()) { + if (element()->active()) + ts << "act "; + if (element()->isLink()) + ts << "anchor "; + if (element()->focused()) + ts << "focus "; + ts << " <" << element()->localName().deprecatedString() << ">"; + ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")"; + if (isTableCell()) { + const RenderTableCell* cell = static_cast<const RenderTableCell*>(this); + ts << " [r=" << cell->row() << " c=" << cell->col() << " rs=" << cell->rowSpan() << " cs=" << cell->colSpan() << "]"; + } + } + return str; +} + +void RenderObject::dump(TextStream* stream, DeprecatedString ind) const +{ + if (isAnonymous()) + *stream << " anonymous"; + if (isFloating()) + *stream << " floating"; + if (isPositioned()) + *stream << " positioned"; + if (isRelPositioned()) + *stream << " relPositioned"; + if (isText()) + *stream << " text"; + if (isInline()) + *stream << " inline"; + if (isReplaced()) + *stream << " replaced"; + if (hasBoxDecorations()) + *stream << " paintBackground"; + if (needsLayout()) + *stream << " needsLayout"; + if (prefWidthsDirty()) + *stream << " prefWidthsDirty"; + *stream << endl; + + RenderObject* child = firstChild(); + while (child) { + *stream << ind << child->renderName() << ": "; + child->dump(stream, ind + " "); + child = child->nextSibling(); + } +} + void RenderObject::showTreeForThis() const { if (element()) @@ -2076,9 +2156,12 @@ void RenderObject::handleDynamicFloatPositionChange() void RenderObject::setAnimatableStyle(RenderStyle* style) { - if (!isText() && m_style && style) - style = animationController()->updateImplicitAnimations(this, style); - + if (!isText() && m_style && style) { + if (!m_style->transitions()) + animationController()->cancelImplicitAnimations(this); + else + style = animationController()->updateImplicitAnimations(this, style); + } setStyle(style); } @@ -2314,6 +2397,12 @@ int RenderObject::paddingTop() const Length padding = m_style->paddingTop(); if (padding.isPercent()) w = containingBlock()->availableWidth(); +#ifdef ANDROID_LAYOUT + // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding. + if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR && + padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING) + return ANDROID_SSR_MARGIN_PADDING; +#endif return padding.calcMinValue(w); } @@ -2323,6 +2412,12 @@ int RenderObject::paddingBottom() const Length padding = style()->paddingBottom(); if (padding.isPercent()) w = containingBlock()->availableWidth(); +#ifdef ANDROID_LAYOUT + // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding. + if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR && + padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING) + return ANDROID_SSR_MARGIN_PADDING; +#endif return padding.calcMinValue(w); } @@ -2332,6 +2427,12 @@ int RenderObject::paddingLeft() const Length padding = style()->paddingLeft(); if (padding.isPercent()) w = containingBlock()->availableWidth(); +#ifdef ANDROID_LAYOUT + // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding. + if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR && + padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING) + return ANDROID_SSR_MARGIN_PADDING; +#endif return padding.calcMinValue(w); } @@ -2341,6 +2442,12 @@ int RenderObject::paddingRight() const Length padding = style()->paddingRight(); if (padding.isPercent()) w = containingBlock()->availableWidth(); +#ifdef ANDROID_LAYOUT + // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding. + if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR && + padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING) + return ANDROID_SSR_MARGIN_PADDING; +#endif return padding.calcMinValue(w); } diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index 5cbce20..8a85c4f 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -3,7 +3,7 @@ * (C) 2000 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -57,7 +57,7 @@ class RenderTable; class RenderText; class RenderView; class String; - +class TextStream; struct HitTestRequest; /* @@ -227,6 +227,8 @@ private: public: #ifndef NDEBUG + DeprecatedString information() const; + virtual void dump(TextStream*, DeprecatedString ind = "") const; void showTreeForThis() const; #endif @@ -322,9 +324,6 @@ public: bool hasBoxDecorations() const { return m_paintBackground; } bool mustRepaintBackgroundOrBorder() const; - bool hasHorizontalBordersPaddingOrMargin() const { return hasHorizontalBordersOrPadding() || marginLeft() != 0 || marginRight() != 0; } - bool hasHorizontalBordersOrPadding() const { return borderLeft() != 0 || borderRight() != 0 || paddingLeft() != 0 || paddingRight() != 0; } - bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout; } bool selfNeedsLayout() const { return m_needsLayout; } bool posChildNeedsLayout() const { return m_posChildNeedsLayout; } @@ -485,7 +484,7 @@ public: /* This function performs a layout only if one is needed. */ void layoutIfNeeded() { if (needsLayout()) layout(); } - // used for element state updates that cannot be fixed with a + // used for element state updates that can not be fixed with a // repaint and do not need a relayout virtual void updateFromElement() { } @@ -668,7 +667,7 @@ public: // the rect that will be painted if this object is passed as the paintingRoot IntRect paintingRootRect(IntRect& topLevelRect); - void addPDFURLRect(GraphicsContext*, const IntRect&); + void addPDFURLRect(GraphicsContext*, IntRect); virtual void addFocusRingRects(GraphicsContext*, int tx, int ty); @@ -855,6 +854,9 @@ public: { return !paintInfo.paintingRoot || paintInfo.paintingRoot == this; } +#ifdef ANDROID_LAYOUT + virtual bool hasChildTable() const { return false; } +#endif bool hasOverrideSize() const { return m_hasOverrideSize; } void setHasOverrideSize(bool b) { m_hasOverrideSize = b; } diff --git a/WebCore/rendering/RenderPartObject.cpp b/WebCore/rendering/RenderPartObject.cpp index 5571000..89f0cce 100644 --- a/WebCore/rendering/RenderPartObject.cpp +++ b/WebCore/rendering/RenderPartObject.cpp @@ -1,8 +1,10 @@ -/* +/** + * This file is part of the KDE project. + * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2000 Simon Hausmann <hausmann@kde.org> * (C) 2000 Stefan Schimanski (1Stein@gmx.de) - * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -20,10 +22,11 @@ * Boston, MA 02110-1301, USA. * */ - #include "config.h" #include "RenderPartObject.h" +#include "Document.h" +#include "EventHandler.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClient.h" @@ -34,10 +37,19 @@ #include "HTMLNames.h" #include "HTMLObjectElement.h" #include "HTMLParamElement.h" +#include "KURL.h" #include "MIMETypeRegistry.h" #include "Page.h" +#include "RenderView.h" #include "Text.h" +#ifdef FLATTEN_IFRAME +#include "RenderView.h" +#define LOG_TAG "WebCore" +#undef LOG +#include "utils/Log.h" +#endif + namespace WebCore { using namespace HTMLNames; @@ -56,17 +68,21 @@ RenderPartObject::~RenderPartObject() m_view->removeWidgetToUpdate(this); } -static bool isURLAllowed(Document* doc, const String& url) +static bool isURLAllowed(Document *doc, const String &url) { + KURL newURL(doc->completeURL(url.deprecatedString())); + newURL.setRef(DeprecatedString::null); + if (doc->frame()->page()->frameCount() >= 200) return false; // We allow one level of self-reference because some sites depend on that. // But we don't allow more than one. - KURL completeURL = doc->completeURL(url); bool foundSelfReference = false; - for (Frame* frame = doc->frame(); frame; frame = frame->tree()->parent()) { - if (equalIgnoringRef(frame->loader()->url(), completeURL)) { + for (Frame *frame = doc->frame(); frame; frame = frame->tree()->parent()) { + KURL frameURL = frame->loader()->url(); + frameURL.setRef(DeprecatedString::null); + if (frameURL == newURL) { if (foundSelfReference) return false; foundSelfReference = true; @@ -93,10 +109,10 @@ static inline void mapClassIdToServiceType(const String& classId, String& servic serviceType = "application/x-director"; else if (classId.contains("6BF52A52-394A-11d3-B153-00C04F79FAA6")) serviceType = "application/x-mplayer2"; - else if (!classId.isEmpty()) { - // We have a clsid, means this is Active X (Niko) + else if (!classId.isEmpty()) + // We have a clsid, means this is activex (Niko) serviceType = "application/x-activex-handler"; - } + // TODO: add more plugins here } void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) @@ -130,8 +146,8 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) HTMLElement *embedOrObject; if (embed) { embedOrObject = (HTMLElement *)embed; - url = embed->url(); - serviceType = embed->serviceType(); + url = embed->url; + serviceType = embed->m_serviceType; } else embedOrObject = (HTMLElement *)o; @@ -186,8 +202,8 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) Attribute* it = attributes->attributeItem(i); const AtomicString& name = it->name().localName(); if (embed || !uniqueParamNames.contains(name.impl())) { - paramNames.append(name.string()); - paramValues.append(it->value().string()); + paramNames.append(name.domString()); + paramValues.append(it->value().domString()); } } } @@ -222,8 +238,8 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) } else if (element()->hasTagName(embedTag)) { HTMLEmbedElement *o = static_cast<HTMLEmbedElement*>(element()); o->setNeedWidgetUpdate(false); - url = o->url(); - serviceType = o->serviceType(); + url = o->url; + serviceType = o->m_serviceType; if (url.isEmpty() && serviceType.isEmpty()) return; @@ -235,8 +251,8 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) if (a) { for (unsigned i = 0; i < a->length(); ++i) { Attribute* it = a->attributeItem(i); - paramNames.append(it->name().localName().string()); - paramValues.append(it->value().string()); + paramNames.append(it->name().localName().domString()); + paramValues.append(it->value().domString()); } } @@ -260,6 +276,41 @@ void RenderPartObject::layout() calcWidth(); calcHeight(); + +#ifdef FLATTEN_IFRAME + // Some IFrames have a width and/or height of 1 when they are meant to be + // hidden. If that is the case, don't try to expand. + if (m_widget && m_widget->isFrameView() && + m_width > 1 && m_height > 1) { + FrameView* view = static_cast<FrameView*>(m_widget); + RenderView* root = NULL; + if (view->frame() && view->frame()->document() && + view->frame()->document()->renderer() && view->frame()->document()->renderer()->isRenderView()) + root = static_cast<RenderView*>(view->frame()->document()->renderer()); + if (root) { + int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight(); + int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom(); + // Resize the view to recalc the height. + int height = m_height - extraHeight; + int width = m_width - extraWidth; + if (width > view->width()) + height = 0; + if (width != view->width() || height != view->height()) { + view->resize(width, height); + view->setNeedsLayout(); + } + // Layout the view. + if (view->needsLayout()) + view->layout(); + int contentHeight = root->docHeight() + extraHeight; + int contentWidth = root->docWidth() + extraWidth; + // Do not shrink iframes with specified sizes + if (contentHeight > m_height || style()->height().isAuto()) + m_height = contentHeight; + m_width = std::min(contentWidth, 800); + } + } +#endif adjustOverflowForBoxShadow(); RenderPart::layout(); diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index 8e60fc7..65e17c1 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -35,6 +35,10 @@ #include "RenderTheme.h" #include <wtf/MathExtras.h> +#ifdef ANDROID_LAYOUT +#include "Settings.h" +#endif + using std::min; namespace WebCore { @@ -213,6 +217,10 @@ void RenderSlider::layout() if (m_thumb && m_thumb->renderer()) { +#ifdef ANDROID_LAYOUT + int oldVisibleWidth = m_visibleWidth; +#endif + int oldWidth = m_width; calcWidth(); int oldHeight = m_height; @@ -221,6 +229,14 @@ void RenderSlider::layout() if (oldWidth != m_width || oldHeight != m_height) relayoutChildren = true; +#ifdef ANDROID_LAYOUT + const Settings* settings = document()->settings(); + ASSERT(settings); + if (oldVisibleWidth != m_visibleWidth + && settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) + relayoutChildren = true; +#endif + // Allow the theme to set the size of the thumb if (m_thumb->renderer()->style()->hasAppearance()) theme()->adjustSliderThumbSize(m_thumb->renderer()); diff --git a/WebCore/rendering/RenderStyle.cpp b/WebCore/rendering/RenderStyle.cpp index 734c0fd..b35b56d 100644 --- a/WebCore/rendering/RenderStyle.cpp +++ b/WebCore/rendering/RenderStyle.cpp @@ -30,8 +30,7 @@ namespace WebCore { static RenderStyle* defaultStyle; StyleSurroundData::StyleSurroundData() - : margin(Fixed) - , padding(Fixed) + : margin(Fixed), padding(Fixed) { } @@ -50,9 +49,7 @@ bool StyleSurroundData::operator==(const StyleSurroundData& o) const } StyleBoxData::StyleBoxData() - : z_index(0) - , z_auto(true) - , boxSizing(CONTENT_BOX) + : z_index(0), z_auto(true), boxSizing(CONTENT_BOX) { // Initialize our min/max widths/heights. min_width = min_height = RenderStyle::initialMinSize(); @@ -325,9 +322,7 @@ StyleBackgroundData::StyleBackgroundData() } StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData& o) - : RefCounted<StyleBackgroundData>() - , m_background(o.m_background) - , m_outline(o.m_outline) + : RefCounted<StyleBackgroundData>(), m_background(o.m_background), m_outline(o.m_outline) { } @@ -401,8 +396,7 @@ StyleMultiColData::StyleMultiColData() , m_breakBefore(RenderStyle::initialPageBreak()) , m_breakAfter(RenderStyle::initialPageBreak()) , m_breakInside(RenderStyle::initialPageBreak()) -{ -} +{} StyleMultiColData::StyleMultiColData(const StyleMultiColData& o) : RefCounted<StyleMultiColData>() @@ -416,8 +410,7 @@ StyleMultiColData::StyleMultiColData(const StyleMultiColData& o) , m_breakBefore(o.m_breakBefore) , m_breakAfter(o.m_breakAfter) , m_breakInside(o.m_breakInside) -{ -} +{} bool StyleMultiColData::operator==(const StyleMultiColData& o) const { @@ -431,16 +424,14 @@ StyleTransformData::StyleTransformData() : m_operations(RenderStyle::initialTransform()) , m_x(RenderStyle::initialTransformOriginX()) , m_y(RenderStyle::initialTransformOriginY()) -{ -} +{} StyleTransformData::StyleTransformData(const StyleTransformData& o) : RefCounted<StyleTransformData>() , m_operations(o.m_operations) , m_x(o.m_x) , m_y(o.m_y) -{ -} +{} bool StyleTransformData::operator==(const StyleTransformData& o) const { @@ -774,6 +765,9 @@ StyleRareInheritedData::StyleRareInheritedData() , nbspMode(NBNORMAL) , khtmlLineBreak(LBNORMAL) , textSizeAdjust(RenderStyle::initialTextSizeAdjust()) +#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR + , tapHighlightColor(RenderStyle::initialTapHighlightColor()) +#endif , resize(RenderStyle::initialResize()) , userSelect(RenderStyle::initialUserSelect()) { @@ -793,6 +787,9 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) , nbspMode(o.nbspMode) , khtmlLineBreak(o.khtmlLineBreak) , textSizeAdjust(o.textSizeAdjust) +#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR + , tapHighlightColor(o.tapHighlightColor) +#endif , resize(o.resize) , userSelect(o.userSelect) { @@ -817,6 +814,9 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const && nbspMode == o.nbspMode && khtmlLineBreak == o.khtmlLineBreak && textSizeAdjust == o.textSizeAdjust +#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR + && tapHighlightColor == o.tapHighlightColor +#endif && userSelect == o.userSelect; } @@ -830,15 +830,13 @@ bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& } StyleInheritedData::StyleInheritedData() - : indent(RenderStyle::initialTextIndent()) - , line_height(RenderStyle::initialLineHeight()) - , style_image(RenderStyle::initialListStyleImage()) - , color(RenderStyle::initialColor()) - , horizontal_border_spacing(RenderStyle::initialHorizontalBorderSpacing()) - , vertical_border_spacing(RenderStyle::initialVerticalBorderSpacing()) - , widows(RenderStyle::initialWidows()) - , orphans(RenderStyle::initialOrphans()) - , page_break_inside(RenderStyle::initialPageBreak()) + : indent(RenderStyle::initialTextIndent()), line_height(RenderStyle::initialLineHeight()), + style_image(RenderStyle::initialListStyleImage()), + color(RenderStyle::initialColor()), + horizontal_border_spacing(RenderStyle::initialHorizontalBorderSpacing()), + vertical_border_spacing(RenderStyle::initialVerticalBorderSpacing()), + widows(RenderStyle::initialWidows()), orphans(RenderStyle::initialOrphans()), + page_break_inside(RenderStyle::initialPageBreak()) { } @@ -847,18 +845,13 @@ StyleInheritedData::~StyleInheritedData() } StyleInheritedData::StyleInheritedData(const StyleInheritedData& o) - : RefCounted<StyleInheritedData>() - , indent(o.indent) - , line_height(o.line_height) - , style_image(o.style_image) - , cursorData(o.cursorData) - , font(o.font) - , color(o.color) - , horizontal_border_spacing(o.horizontal_border_spacing) - , vertical_border_spacing(o.vertical_border_spacing) - , widows(o.widows) - , orphans(o.orphans) - , page_break_inside(o.page_break_inside) + : RefCounted<StyleInheritedData>(), + indent( o.indent ), line_height( o.line_height ), style_image( o.style_image ), + cursorData(o.cursorData), + font( o.font ), color( o.color ), + horizontal_border_spacing( o.horizontal_border_spacing ), + vertical_border_spacing( o.vertical_border_spacing ), + widows(o.widows), orphans(o.orphans), page_break_inside(o.page_break_inside) { } @@ -950,7 +943,6 @@ RenderStyle::RenderStyle() , m_emptyState(false) , m_childrenAffectedByFirstChildRules(false) , m_childrenAffectedByLastChildRules(false) - , m_childrenAffectedByDirectAdjacentRules(false) , m_childrenAffectedByForwardPositionalRules(false) , m_childrenAffectedByBackwardPositionalRules(false) , m_firstChildState(false) @@ -973,7 +965,6 @@ RenderStyle::RenderStyle(bool) , m_emptyState(false) , m_childrenAffectedByFirstChildRules(false) , m_childrenAffectedByLastChildRules(false) - , m_childrenAffectedByDirectAdjacentRules(false) , m_childrenAffectedByForwardPositionalRules(false) , m_childrenAffectedByBackwardPositionalRules(false) , m_firstChildState(false) @@ -1018,7 +1009,6 @@ RenderStyle::RenderStyle(const RenderStyle& o) , m_emptyState(false) , m_childrenAffectedByFirstChildRules(false) , m_childrenAffectedByLastChildRules(false) - , m_childrenAffectedByDirectAdjacentRules(false) , m_childrenAffectedByForwardPositionalRules(false) , m_childrenAffectedByBackwardPositionalRules(false) , m_firstChildState(false) @@ -1351,6 +1341,15 @@ void RenderStyle::addCursor(CachedImage* image, const IntPoint& hotSpot) inherited.access()->cursorData->append(data); } +void RenderStyle::addSVGCursor(const String& fragmentId) +{ + CursorData data; + data.cursorFragmentId = fragmentId; + if (!inherited.access()->cursorData) + inherited.access()->cursorData = new CursorList; + inherited.access()->cursorData->append(data); +} + void RenderStyle::setCursorList(PassRefPtr<CursorList> other) { inherited.access()->cursorData = other; diff --git a/WebCore/rendering/RenderStyle.h b/WebCore/rendering/RenderStyle.h index 8cc597f..fe7e4a7 100644 --- a/WebCore/rendering/RenderStyle.h +++ b/WebCore/rendering/RenderStyle.h @@ -315,8 +315,8 @@ enum EMarginCollapse { MCOLLAPSE, MSEPARATE, MDISCARD }; class StyleSurroundData : public RefCounted<StyleSurroundData> { public: - static PassRefPtr<StyleSurroundData> create() { return adoptRef(new StyleSurroundData); } - PassRefPtr<StyleSurroundData> copy() const { return adoptRef(new StyleSurroundData(*this)); } + StyleSurroundData(); + StyleSurroundData(const StyleSurroundData& o); bool operator==(const StyleSurroundData& o) const; bool operator!=(const StyleSurroundData& o) const { @@ -327,10 +327,6 @@ public: LengthBox margin; LengthBox padding; BorderData border; - -private: - StyleSurroundData(); - StyleSurroundData(const StyleSurroundData&); }; @@ -341,8 +337,12 @@ enum EBoxSizing { CONTENT_BOX, BORDER_BOX }; class StyleBoxData : public RefCounted<StyleBoxData> { public: - static PassRefPtr<StyleBoxData> create() { return adoptRef(new StyleBoxData); } - PassRefPtr<StyleBoxData> copy() const { return adoptRef(new StyleBoxData(*this)); } + StyleBoxData(); + StyleBoxData(const StyleBoxData& o); + + // copy and assignment +// StyleBoxData(const StyleBoxData &other); +// const StyleBoxData &operator = (const StyleBoxData &other); bool operator==(const StyleBoxData& o) const; bool operator!=(const StyleBoxData& o) const { @@ -363,10 +363,6 @@ public: int z_index; bool z_auto : 1; unsigned boxSizing : 1; // EBoxSizing - -private: - StyleBoxData(); - StyleBoxData(const StyleBoxData&); }; //------------------------------------------------ @@ -420,9 +416,9 @@ enum EUnicodeBidi { class StyleVisualData : public RefCounted<StyleVisualData> { public: - static PassRefPtr<StyleVisualData> create() { return adoptRef(new StyleVisualData); } - PassRefPtr<StyleVisualData> copy() const { return adoptRef(new StyleVisualData(*this)); } + StyleVisualData(); ~StyleVisualData(); + StyleVisualData(const StyleVisualData&); bool operator==(const StyleVisualData& o) const { return ( clip == o.clip && @@ -440,9 +436,6 @@ public: short counterIncrement; // ok, so these are not visual mode specific short counterReset; // can't go to inherited, since these are not inherited -private: - StyleVisualData(); - StyleVisualData(const StyleVisualData&); }; //------------------------------------------------ @@ -561,9 +554,9 @@ public: class StyleBackgroundData : public RefCounted<StyleBackgroundData> { public: - static PassRefPtr<StyleBackgroundData> create() { return adoptRef(new StyleBackgroundData); } - PassRefPtr<StyleBackgroundData> copy() const { return adoptRef(new StyleBackgroundData(*this)); } + StyleBackgroundData(); ~StyleBackgroundData() {} + StyleBackgroundData(const StyleBackgroundData& o ); bool operator==(const StyleBackgroundData& o) const; bool operator!=(const StyleBackgroundData &o) const { @@ -573,10 +566,6 @@ public: BackgroundLayer m_background; Color m_color; OutlineValue m_outline; - -private: - StyleBackgroundData(); - StyleBackgroundData(const StyleBackgroundData& o ); }; //------------------------------------------------ @@ -587,8 +576,8 @@ enum EMarqueeDirection { MAUTO = 0, MLEFT = 1, MRIGHT = -1, MUP = 2, MDOWN = -2, class StyleMarqueeData : public RefCounted<StyleMarqueeData> { public: - static PassRefPtr<StyleMarqueeData> create() { return adoptRef(new StyleMarqueeData); } - PassRefPtr<StyleMarqueeData> copy() const { return adoptRef(new StyleMarqueeData(*this)); } + StyleMarqueeData(); + StyleMarqueeData(const StyleMarqueeData& o); bool operator==(const StyleMarqueeData& o) const; bool operator!=(const StyleMarqueeData& o) const { @@ -602,19 +591,15 @@ public: unsigned behavior : 3; // EMarqueeBehavior EMarqueeDirection direction : 3; // not unsigned because EMarqueeDirection has negative values - -private: - StyleMarqueeData(); - StyleMarqueeData(const StyleMarqueeData&); }; // CSS3 Multi Column Layout class StyleMultiColData : public RefCounted<StyleMultiColData> { public: - static PassRefPtr<StyleMultiColData> create() { return adoptRef(new StyleMultiColData); } - PassRefPtr<StyleMultiColData> copy() const { return adoptRef(new StyleMultiColData(*this)); } - + StyleMultiColData(); + StyleMultiColData(const StyleMultiColData& o); + bool operator==(const StyleMultiColData& o) const; bool operator!=(const StyleMultiColData &o) const { return !(*this == o); @@ -637,17 +622,13 @@ public: unsigned m_breakBefore : 2; // EPageBreak unsigned m_breakAfter : 2; // EPageBreak unsigned m_breakInside : 2; // EPageBreak - -private: - StyleMultiColData(); - StyleMultiColData(const StyleMultiColData&); }; // CSS Transforms (may become part of CSS3) -class TransformOperation : public RefCounted<TransformOperation> { +class TransformOperation : public RefCounted<TransformOperation> +{ public: - TransformOperation() : RefCounted<TransformOperation>(0) { } virtual ~TransformOperation() {} virtual bool operator==(const TransformOperation&) const = 0; @@ -838,8 +819,8 @@ private: class StyleTransformData : public RefCounted<StyleTransformData> { public: - static PassRefPtr<StyleTransformData> create() { return adoptRef(new StyleTransformData); } - PassRefPtr<StyleTransformData> copy() const { return adoptRef(new StyleTransformData(*this)); } + StyleTransformData(); + StyleTransformData(const StyleTransformData&); bool operator==(const StyleTransformData&) const; bool operator!=(const StyleTransformData& o) const { @@ -849,10 +830,6 @@ public: TransformOperations m_operations; Length m_x; Length m_y; - -private: - StyleTransformData(); - StyleTransformData(const StyleTransformData&); }; //------------------------------------------------ @@ -865,9 +842,9 @@ enum EBoxDirection { BNORMAL, BREVERSE }; class StyleFlexibleBoxData : public RefCounted<StyleFlexibleBoxData> { public: - static PassRefPtr<StyleFlexibleBoxData> create() { return adoptRef(new StyleFlexibleBoxData); } - PassRefPtr<StyleFlexibleBoxData> copy() const { return adoptRef(new StyleFlexibleBoxData(*this)); } - + StyleFlexibleBoxData(); + StyleFlexibleBoxData(const StyleFlexibleBoxData& o); + bool operator==(const StyleFlexibleBoxData& o) const; bool operator!=(const StyleFlexibleBoxData &o) const { return !(*this == o); @@ -881,10 +858,6 @@ public: unsigned pack: 3; // EBoxAlignment unsigned orient: 1; // EBoxOrient unsigned lines : 1; // EBoxLines - -private: - StyleFlexibleBoxData(); - StyleFlexibleBoxData(const StyleFlexibleBoxData&); }; // This struct holds information about shadows for the text-shadow and box-shadow properties. @@ -1154,10 +1127,10 @@ public: // actually uses one of these properties. class StyleRareNonInheritedData : public RefCounted<StyleRareNonInheritedData> { public: - static PassRefPtr<StyleRareNonInheritedData> create() { return adoptRef(new StyleRareNonInheritedData); } - PassRefPtr<StyleRareNonInheritedData> copy() const { return adoptRef(new StyleRareNonInheritedData(*this)); } + StyleRareNonInheritedData(); ~StyleRareNonInheritedData(); - + StyleRareNonInheritedData(const StyleRareNonInheritedData&); + #if ENABLE(XBL) bool bindingsEquivalent(const StyleRareNonInheritedData&) const; #endif @@ -1194,10 +1167,6 @@ public: #if ENABLE(XBL) BindingURI* bindingURI; // The XBL binding URI list. #endif - -private: - StyleRareNonInheritedData(); - StyleRareNonInheritedData(const StyleRareNonInheritedData&); }; // This struct is for rarely used inherited CSS3, CSS2, and WebKit-specific properties. @@ -1205,9 +1174,9 @@ private: // actually uses one of these properties. class StyleRareInheritedData : public RefCounted<StyleRareInheritedData> { public: - static PassRefPtr<StyleRareInheritedData> create() { return adoptRef(new StyleRareInheritedData); } - PassRefPtr<StyleRareInheritedData> copy() const { return adoptRef(new StyleRareInheritedData(*this)); } + StyleRareInheritedData(); ~StyleRareInheritedData(); + StyleRareInheritedData(const StyleRareInheritedData& o); bool operator==(const StyleRareInheritedData& o) const; bool operator!=(const StyleRareInheritedData &o) const { @@ -1218,7 +1187,9 @@ public: Color textStrokeColor; float textStrokeWidth; Color textFillColor; - +#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR + Color tapHighlightColor; +#endif ShadowData* textShadow; // Our text shadow information for shadowed text drawing. AtomicString highlight; // Apple-specific extension for custom highlight rendering. unsigned textSecurity : 2; // ETextSecurity @@ -1230,10 +1201,6 @@ public: bool textSizeAdjust : 1; // An Apple extension. unsigned resize : 2; // EResize unsigned userSelect : 1; // EUserSelect - -private: - StyleRareInheritedData(); - StyleRareInheritedData(const StyleRareInheritedData&); }; //------------------------------------------------ @@ -1262,10 +1229,10 @@ enum EPageBreak { class StyleInheritedData : public RefCounted<StyleInheritedData> { public: - static PassRefPtr<StyleInheritedData> create() { return adoptRef(new StyleInheritedData); } - PassRefPtr<StyleInheritedData> copy() const { return adoptRef(new StyleInheritedData(*this)); } + StyleInheritedData(); ~StyleInheritedData(); - + StyleInheritedData(const StyleInheritedData& o ); + bool operator==(const StyleInheritedData& o) const; bool operator != ( const StyleInheritedData &o ) const { return !(*this == o); @@ -1289,10 +1256,6 @@ public: short widows; short orphans; unsigned page_break_inside : 2; // EPageBreak - -private: - StyleInheritedData(); - StyleInheritedData(const StyleInheritedData&); }; @@ -1323,18 +1286,17 @@ struct CursorData { {} bool operator==(const CursorData& o) const { - return hotSpot == o.hotSpot && cursorImage == o.cursorImage; + return hotSpot == o.hotSpot && cursorImage == o.cursorImage && cursorFragmentId == o.cursorFragmentId; } bool operator!=(const CursorData& o) const { return !(*this == o); } IntPoint hotSpot; // for CSS3 support CachedImage* cursorImage; // weak pointer, the CSSValueImage takes care of deleting cursorImage + String cursorFragmentId; // only used for SVGCursorElement, a direct pointer would get stale }; class CursorList : public RefCounted<CursorList> { public: - CursorList() : RefCounted<CursorList>(0) { } - const CursorData& operator[](int i) const { return m_vector[i]; } @@ -1514,12 +1476,11 @@ protected: // *-child-of-type, we will just give up and re-evaluate whenever children change at all. bool m_childrenAffectedByFirstChildRules : 1; bool m_childrenAffectedByLastChildRules : 1; - bool m_childrenAffectedByDirectAdjacentRules : 1; bool m_childrenAffectedByForwardPositionalRules : 1; bool m_childrenAffectedByBackwardPositionalRules : 1; bool m_firstChildState : 1; bool m_lastChildState : 1; - unsigned m_childIndex : 18; // Plenty of bits to cache an index. + unsigned m_childIndex : 19; // Plenty of bits to cache an index. int m_ref; @@ -1868,6 +1829,10 @@ public: bool textSizeAdjust() const { return rareInheritedData->textSizeAdjust; } ETextSecurity textSecurity() const { return static_cast<ETextSecurity>(rareInheritedData->textSecurity); } +#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR + Color tapHighlightColor() const { return rareInheritedData->tapHighlightColor; } +#endif + // attribute setter methods void setDisplay(EDisplay v) { noninherited_flags._effectiveDisplay = v; } @@ -2022,6 +1987,7 @@ public: void setCursor( ECursor c ) { inherited_flags._cursor_style = c; } void addCursor(CachedImage*, const IntPoint& = IntPoint()); + void addSVGCursor(const String&); void setCursorList(PassRefPtr<CursorList>); void clearCursorList(); @@ -2115,6 +2081,10 @@ public: void setTextSizeAdjust(bool b) { SET_VAR(rareInheritedData, textSizeAdjust, b); } void setTextSecurity(ETextSecurity aTextSecurity) { SET_VAR(rareInheritedData, textSecurity, aTextSecurity); } +#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR + void setTapHighlightColor(const Color & v) { SET_VAR(rareInheritedData,tapHighlightColor,v); } +#endif + #if ENABLE(SVG) const SVGRenderStyle* svgStyle() const { return m_svgStyle.get(); } SVGRenderStyle* accessSVGStyle() { return m_svgStyle.access(); } @@ -2166,13 +2136,10 @@ public: bool affectedByEmpty() const { return m_affectedByEmpty; } bool emptyState() const { return m_emptyState; } void setEmptyState(bool b) { m_affectedByEmpty = true; m_unique = true; m_emptyState = b; } - bool childrenAffectedByPositionalRules() const { return childrenAffectedByForwardPositionalRules() || childrenAffectedByBackwardPositionalRules(); } bool childrenAffectedByFirstChildRules() const { return m_childrenAffectedByFirstChildRules; } void setChildrenAffectedByFirstChildRules() { m_childrenAffectedByFirstChildRules = true; } bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; } void setChildrenAffectedByLastChildRules() { m_childrenAffectedByLastChildRules = true; } - bool childrenAffectedByDirectAdjacentRules() const { return m_childrenAffectedByDirectAdjacentRules; } - void setChildrenAffectedByDirectAdjacentRules() { m_childrenAffectedByDirectAdjacentRules = true; } bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; } void setChildrenAffectedByForwardPositionalRules() { m_childrenAffectedByForwardPositionalRules = true; } bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; } @@ -2283,6 +2250,10 @@ public: static ETextSecurity initialTextSecurity() { return TSNONE; } static const Vector<StyleDashboardRegion>& initialDashboardRegions(); static const Vector<StyleDashboardRegion>& noneDashboardRegions(); + +#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR + static Color initialTapHighlightColor() { return Color::tap; } +#endif }; } // namespace WebCore diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index 12da8a4..0d95253 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -36,7 +36,12 @@ #include "RenderTableCell.h" #include "RenderTableCol.h" #include "RenderTableSection.h" +#ifdef ANDROID_LAYOUT +#include "Settings.h" +#include "WebCoreViewBridge.h" +#endif #include "RenderView.h" +#include "TextStream.h" using namespace std; @@ -61,6 +66,9 @@ RenderTable::RenderTable(Node* node) , m_borderLeft(0) , m_borderRight(0) { +#ifdef ANDROID_LAYOUT + m_singleColumn = false; +#endif m_columnPos.fill(0, 2); m_columns.fill(ColumnStruct(), 1); } @@ -209,6 +217,16 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild) void RenderTable::calcWidth() { +#ifdef ANDROID_LAYOUT + if (view()->frameView()) { + const Settings* settings = document()->settings(); + ASSERT(settings); + if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) { + m_visibleWidth = view()->frameView()->getWebCoreViewBridge()->screenWidth(); + } + } +#endif + if (isPositioned()) calcAbsoluteHorizontal(); @@ -244,6 +262,11 @@ void RenderTable::calcWidth() // Finally, with our true width determined, compute our margins for real. m_marginRight = 0; m_marginLeft = 0; +#ifdef ANDROID_LAYOUT + // in SSR mode, we ignore left/right margin for table + if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) + return; +#endif calcHorizontalMargins(style()->marginLeft(), style()->marginRight(), availableWidth); } @@ -271,9 +294,33 @@ void RenderTable::layout() m_overflowTop = 0; initMaxMarginValues(); +#ifdef ANDROID_LAYOUT + bool relayoutChildren = false; + int oldVisibleWidth = m_visibleWidth; +#endif + int oldWidth = m_width; calcWidth(); +#ifdef ANDROID_LAYOUT + if (oldVisibleWidth != m_visibleWidth + && document()->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) + relayoutChildren = true; + else if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) { + // if the width of a table is wider than its container width, or it has a nested table, + // we will render it with single column. + int cw = containingBlockWidth(); + if (m_width > cw || hasChildTable()) { + m_singleColumn = true; + if (m_width > cw) + m_width = cw; + if (m_minPrefWidth > cw) + m_minPrefWidth = cw; + if (m_maxPrefWidth > cw) + m_maxPrefWidth = cw; + } + } +#endif if (m_caption && m_width != oldWidth) m_caption->setNeedsLayout(true, false); @@ -293,8 +340,14 @@ void RenderTable::layout() RenderObject* child = firstChild(); while (child) { // FIXME: What about a form that has a display value that makes it a table section? +#ifdef ANDROID_LAYOUT + if ((relayoutChildren || child->needsLayout()) && + !(child->element() && child->element()->hasTagName(formTag))) + child->layout(); +#else if (child->needsLayout() && !(child->element() && child->element()->hasTagName(formTag))) child->layout(); +#endif if (child->isTableSection()) { static_cast<RenderTableSection*>(child)->calcRowHeight(); calculatedHeight += static_cast<RenderTableSection*>(child)->layoutRows(0); @@ -1102,4 +1155,23 @@ IntRect RenderTable::getOverflowClipRect(int tx, int ty) return rect; } +#ifndef NDEBUG +void RenderTable::dump(TextStream* stream, DeprecatedString ind) const +{ + if (m_caption) + *stream << " tCaption"; + if (m_head) + *stream << " head"; + if (m_foot) + *stream << " foot"; + + *stream << endl << ind << "cspans:"; + for (unsigned i = 0; i < m_columns.size(); i++) + *stream << " " << m_columns[i].span; + *stream << endl << ind; + + RenderBlock::dump(stream, ind); +} +#endif + } diff --git a/WebCore/rendering/RenderTable.h b/WebCore/rendering/RenderTable.h index 32ad83a..7acbd8a 100644 --- a/WebCore/rendering/RenderTable.h +++ b/WebCore/rendering/RenderTable.h @@ -190,6 +190,15 @@ public: recalcSections(); } +#ifndef NDEBUG + virtual void dump(TextStream*, DeprecatedString ind = "") const; +#endif + +#ifdef ANDROID_LAYOUT + void clearSingleColumn() { m_singleColumn = false; } + bool isSingleColumn() const { return m_singleColumn; } +#endif + private: void recalcSections() const; @@ -211,6 +220,9 @@ private: mutable bool m_hasColElements : 1; mutable bool m_needsSectionRecalc : 1; +#ifdef ANDROID_LAYOUT + bool m_singleColumn; // BS(Grace): should I use compact version? +#endif short m_hSpacing; short m_vSpacing; int m_borderLeft; diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index 9a4fd16..f00f8ad 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -30,6 +30,13 @@ #include "HTMLTableCellElement.h" #include "RenderTableCol.h" #include "RenderView.h" +#include "TextStream.h" + +#ifdef ANDROID_LAYOUT +#include "Document.h" +#include "Settings.h" +#include "WebCoreViewBridge.h" +#endif using namespace std; @@ -121,6 +128,15 @@ void RenderTableCell::calcPrefWidths() void RenderTableCell::calcWidth() { +#ifdef ANDROID_LAYOUT + if (view()->frameView()) { + const Settings* settings = document()->settings(); + ASSERT(settings); + if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) { + m_visibleWidth = view()->frameView()->getWebCoreViewBridge()->screenWidth(); + } + } +#endif } void RenderTableCell::setWidth(int width) @@ -729,8 +745,21 @@ static int compareBorderStylesForQSort(const void* pa, const void* pb) if (*a == *b) return 0; CollapsedBorderValue borderWithHigherPrecedence = compareBorders(*a, *b); +#ifdef ANDROID_FIX + if (*a == borderWithHigherPrecedence) { + // klibc uses a combsort for quicksort and requires that two values always give the same answer + // regardless of comparison order. Unfortunately, compareBorders does not honor that requirement. + // Call compareBorders again with reversed parameters. If it returns the first value again then + // we can assume the values are equal. http://bugs.webkit.org/show_bug.cgi?id=13147 + CollapsedBorderValue qSortHack = compareBorders(*b, *a); + if (*b == qSortHack) + return 0; + return 1; + } +#else if (*a == borderWithHigherPrecedence) return 1; +#endif return -1; } @@ -853,4 +882,16 @@ void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty) paintBorder(paintInfo.context, tx, ty, w, h, style()); } +#ifndef NDEBUG +void RenderTableCell::dump(TextStream* stream, DeprecatedString ind) const +{ + *stream << " row=" << row(); + *stream << " col=" << col(); + *stream << " rSpan=" << rowSpan(); + *stream << " cSpan=" << colSpan(); + + RenderBlock::dump(stream,ind); +} +#endif + } // namespace WebCore diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h index 2a58974..b691ff8 100644 --- a/WebCore/rendering/RenderTableCell.h +++ b/WebCore/rendering/RenderTableCell.h @@ -66,6 +66,11 @@ public: virtual void setWidth(int); virtual void setStyle(RenderStyle*); +#ifdef ANDROID_LAYOUT + // RenderTableSection needs to access this in setCellWidths() + int getVisibleWidth() { return m_visibleWidth; } +#endif + virtual bool expandsToEncloseOverhangingFloats() const { return true; } int borderLeft() const; @@ -111,7 +116,11 @@ public: virtual int borderTopExtra() const { return m_topExtra; } virtual int borderBottomExtra() const { return m_bottomExtra; } -private: +#ifndef NDEBUG + virtual void dump(TextStream*, DeprecatedString ind = "") const; +#endif + +protected: int m_row; int m_column; int m_rowSpan; diff --git a/WebCore/rendering/RenderTableCol.cpp b/WebCore/rendering/RenderTableCol.cpp index d7f46c9..a8a398d 100644 --- a/WebCore/rendering/RenderTableCol.cpp +++ b/WebCore/rendering/RenderTableCol.cpp @@ -31,6 +31,7 @@ #include "CachedImage.h" #include "HTMLNames.h" #include "HTMLTableColElement.h" +#include "TextStream.h" namespace WebCore { @@ -92,4 +93,12 @@ void RenderTableCol::imageChanged(CachedImage* image) repaint(); } +#ifndef NDEBUG +void RenderTableCol::dump(TextStream* stream, DeprecatedString ind) const +{ + *stream << " span=" << m_span; + RenderContainer::dump(stream, ind); +} +#endif + } diff --git a/WebCore/rendering/RenderTableCol.h b/WebCore/rendering/RenderTableCol.h index 932d2f5..9f042b0 100644 --- a/WebCore/rendering/RenderTableCol.h +++ b/WebCore/rendering/RenderTableCol.h @@ -49,6 +49,10 @@ public: virtual IntRect absoluteClippedOverflowRect(); virtual void imageChanged(CachedImage*); +#ifndef NDEBUG + virtual void dump(TextStream*, DeprecatedString) const; +#endif + int span() const { return m_span; } void setSpan(int s) { m_span = s; } diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index c4b065a..cadf4c0 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -33,8 +33,14 @@ #include "RenderTableCol.h" #include "RenderTableRow.h" #include "RenderView.h" +#include "TextStream.h" #include <limits> #include <wtf/Vector.h> +#ifdef ANDROID_LAYOUT +#include "Frame.h" +#include "Settings.h" +#include "WebCoreViewBridge.h" +#endif using namespace std; @@ -270,6 +276,17 @@ void RenderTableSection::setCellWidths() Vector<int>& columnPos = table()->columnPositions(); bool pushedLayoutState = false; +#ifdef ANDROID_LAYOUT + int visibleWidth = 0; + if (view()->frameView()) { + const Settings* settings = document()->settings(); + ASSERT(settings); + if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) { + visibleWidth = view()->frameView()->getWebCoreViewBridge()->screenWidth(); + } + } +#endif + for (int i = 0; i < m_gridRows; i++) { Row& row = *m_grid[i].row; int cols = row.size(); @@ -286,8 +303,18 @@ void RenderTableSection::setCellWidths() endCol++; } int w = columnPos[endCol] - columnPos[j] - table()->hBorderSpacing(); +#ifdef ANDROID_LAYOUT + if (table()->isSingleColumn()) + w = table()->width()-(table()->borderLeft()+table()->borderRight()+ + (table()->collapseBorders()?0:(table()->paddingLeft()+table()->paddingRight()+ + 2*table()->hBorderSpacing()))); +#endif int oldWidth = cell->width(); +#ifdef ANDROID_LAYOUT + if (w != oldWidth || (visibleWidth > 0 && visibleWidth != cell->getVisibleWidth())) { +#else if (w != oldWidth) { +#endif cell->setNeedsLayout(true); if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) { if (!pushedLayoutState) { @@ -298,7 +325,12 @@ void RenderTableSection::setCellWidths() } cell->repaint(); } +#ifdef ANDROID_LAYOUT + if (w != oldWidth) + cell->setWidth(w); +#else cell->setWidth(w); +#endif } } } @@ -309,6 +341,10 @@ void RenderTableSection::setCellWidths() void RenderTableSection::calcRowHeight() { +#ifdef ANDROID_LAYOUT + if (table()->isSingleColumn()) + return; +#endif RenderTableCell* cell; int spacing = table()->vBorderSpacing(); @@ -390,6 +426,52 @@ void RenderTableSection::calcRowHeight() int RenderTableSection::layoutRows(int toAdd) { +#ifdef ANDROID_LAYOUT + if (table()->isSingleColumn()) { + int totalRows = m_gridRows; + int hspacing = table()->hBorderSpacing(); + int vspacing = table()->vBorderSpacing(); + int rHeight = vspacing; + + int leftOffset = hspacing; + + int nEffCols = table()->numEffCols(); + for (int r = 0; r < totalRows; r++) { + for (int c = 0; c < nEffCols; c++) { + CellStruct current = cellAt(r, c); + RenderTableCell* cell = current.cell; + + if (!cell || current.inColSpan) + continue; + if (r > 0 && (cellAt(r-1, c).cell == cell)) + continue; + + cell->setCellTopExtra(0); + cell->setCellBottomExtra(0); + + int oldCellX = cell->xPos(); + int oldCellY = cell->yPos(); + + if (style()->direction() == RTL) + cell->setPos(table()->width(), rHeight); + else + cell->setPos(leftOffset, rHeight); + + // If the cell moved, we have to repaint it as well as any floating/positioned + // descendants. An exception is if we need a layout. In this case, we know we're going to + // repaint ourselves (and the cell) anyway. + if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) { + IntRect cellRect(oldCellX, oldCellY - cell->borderTopExtra() , cell->width(), cell->height()); + cell->repaintDuringLayoutIfMoved(cellRect); + } + rHeight += cell->height() + vspacing; + } + } + + m_height = rHeight; + return m_height; + } +#endif int rHeight; int rindx; int totalRows = m_gridRows; @@ -877,6 +959,23 @@ void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty) int w = paintInfo.rect.width(); int h = paintInfo.rect.height(); +#ifdef ANDROID_LAYOUT + unsigned int startrow = 0; + unsigned int endrow = totalRows; + unsigned int startcol = 0; + unsigned int endcol = totalCols; + if (table()->isSingleColumn()) { + // FIXME: should we be smarter too? + } else { + // FIXME: possible to rollback to the common tree. + // rowPos size is set in calcRowHeight(), which is called from table layout(). + // BUT RenderTableSection is init through parsing. On a slow device, paint() as + // the result of layout() can come after the next parse() as everything is triggered + // by timer. So we have to check rowPos before using it. + if (m_rowPos.size() != (totalRows + 1)) + return; +#endif + int os = 2 * maximalOutlineSize(paintPhase); unsigned startrow = 0; unsigned endrow = totalRows; @@ -916,6 +1015,9 @@ void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty) if (!endcol && tx + table()->columnPositions()[0] - table()->outerBorderLeft() <= y + w + os) endcol++; } +#ifdef ANDROID_LAYOUT + } +#endif if (startcol < endcol) { // draw the cells @@ -960,7 +1062,6 @@ void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty) if (!row->hasLayer()) cell->paintBackgroundsBehindCell(paintInfo, tx, ty, row); } - if ((!cell->hasLayer() && !row->hasLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders) cell->paint(paintInfo, tx, ty); } @@ -1075,4 +1176,22 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul return false; } +#ifndef NDEBUG +void RenderTableSection::dump(TextStream* stream, DeprecatedString ind) const +{ + *stream << endl << ind << "grid=(" << m_gridRows << "," << table()->numEffCols() << ")" << endl << ind; + for (int r = 0; r < m_gridRows; r++) { + for (int c = 0; c < table()->numEffCols(); c++) { + if (cellAt(r, c).cell && !cellAt(r, c).inColSpan) + *stream << "(" << cellAt(r, c).cell->row() << "," << cellAt(r, c).cell->col() << "," + << cellAt(r, c).cell->rowSpan() << "," << cellAt(r, c).cell->colSpan() << ") "; + else + *stream << cellAt(r, c).cell << "null cell "; + } + *stream << endl << ind; + } + RenderContainer::dump(stream,ind); +} +#endif + } // namespace WebCore diff --git a/WebCore/rendering/RenderTableSection.h b/WebCore/rendering/RenderTableSection.h index 93f8053..0ebc1db 100644 --- a/WebCore/rendering/RenderTableSection.h +++ b/WebCore/rendering/RenderTableSection.h @@ -125,7 +125,11 @@ public: virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); -private: +#ifndef NDEBUG + virtual void dump(TextStream*, DeprecatedString ind = "") const; +#endif + +protected: bool ensureRows(int); void clearGrid(); diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index 0a807e1..788c6e8 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -42,10 +42,14 @@ using namespace Unicode; namespace WebCore { -// FIXME: Move to StringImpl.h eventually. static inline bool charactersAreAllASCII(StringImpl* text) { - return charactersAreAllASCII(text->characters(), text->length()); + const UChar* chars = text->characters(); + unsigned length = text->length(); + UChar ored = 0; + for (unsigned i = 0; i < length; ++i) + ored |= chars[i]; + return !(ored & 0xFF80); } RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str) @@ -76,21 +80,6 @@ RenderText::~RenderText() #endif -const char* RenderText::renderName() const -{ - return "RenderText"; -} - -bool RenderText::isTextFragment() const -{ - return false; -} - -bool RenderText::isWordBreak() const -{ - return false; -} - void RenderText::setStyle(RenderStyle* newStyle) { RenderStyle* oldStyle = style(); @@ -417,29 +406,24 @@ IntRect RenderText::caretRect(int offset, EAffinity affinity, int* extraWidthToE ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int xPos) const { if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII) { + // FIXME: This code should be simplfied; it's only run when m_text is known to be all 0000-007F, + // but is uses the general purpose Unicode direction function. int monospaceCharacterWidth = f.spaceWidth(); int tabWidth = allowTabs() ? monospaceCharacterWidth * 8 : 0; int w = 0; - bool isSpace; - bool previousCharWasSpace = true; // FIXME: Preserves historical behavior, but seems wrong for start > 0. + char previousChar = ' '; // FIXME: Preserves historical behavior, but seems wrong for start > 0. for (int i = start; i < start + len; i++) { char c = (*m_text)[i]; - if (c <= ' ') { - if (c == ' ' || c == '\n') { + Direction dir = direction(c); + if (dir != NonSpacingMark && dir != BoundaryNeutral) { + if (c == '\t' && tabWidth) + w += tabWidth - ((xPos + w) % tabWidth); + else w += monospaceCharacterWidth; - isSpace = true; - } else if (c == '\t') { - w += tabWidth ? tabWidth - ((xPos + w) % tabWidth) : monospaceCharacterWidth; - isSpace = true; - } else - isSpace = false; - } else { - w += monospaceCharacterWidth; - isSpace = false; + if (isASCIISpace(c) && !isASCIISpace(previousChar)) + w += f.wordSpacing(); } - if (isSpace && !previousCharWasSpace) - w += f.wordSpacing(); - previousCharWasSpace = isSpace; + previousChar = c; } return w; } diff --git a/WebCore/rendering/RenderText.h b/WebCore/rendering/RenderText.h index 2f77c90..fceca48 100644 --- a/WebCore/rendering/RenderText.h +++ b/WebCore/rendering/RenderText.h @@ -37,10 +37,9 @@ public: virtual ~RenderText(); #endif - virtual const char* renderName() const; + virtual const char* renderName() const { return "RenderText"; } - virtual bool isTextFragment() const; - virtual bool isWordBreak() const; + virtual bool isTextFragment() const { return false; } virtual PassRefPtr<StringImpl> originalText() const; diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index 18a9fac..7743c32 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -50,6 +50,10 @@ #include "visible_units.h" #include <math.h> +#ifdef ANDROID_LAYOUT +#include "FrameView.h" +#endif + using namespace std; namespace WebCore { @@ -555,12 +559,21 @@ void RenderTextControl::subtreeHasChanged() String RenderTextControl::finishText(Vector<UChar>& result) const { + // ANDROID: This method was modified with a fix from WebKit r31081. This + // comment can be removed the next time we update. + + // Remove one trailing newline; there's always one that's collapsed out by rendering. + size_t size = result.size(); + if (size && result[size - 1] == '\n') + result.shrink(--size); + + // Convert backslash to currency symbol. UChar symbol = backslashAsCurrencySymbol(); if (symbol != '\\') { - size_t size = result.size(); - for (size_t i = 0; i < size; ++i) + for (size_t i = 0; i < size; ++i) { if (result[i] == '\\') result[i] = symbol; + } } return String::adopt(result); @@ -791,11 +804,54 @@ void RenderTextControl::layout() m_innerBlock->renderer()->style()->setHeight(Length(textBlockHeight, Fixed)); } +#ifdef ANDROID_LAYOUT + int oldVisibleWidth = m_visibleWidth; +#endif + int oldWidth = m_width; calcWidth(); + + // FIXME: This causes cnn.com loading way slow. Comment it out for now +//#ifdef ANDROID_LAYOUT +#if 0 + Frame* frame = document()->frame(); + if (frame && frame->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) { + int maxWidth = frame->view()->visibleWidth() - 2 * ANDROID_FCTS_MARGIN_PADDING; + if (maxWidth > 0 && maxWidth < m_width) { + m_width = maxWidth; + // not only modify the control's width, we also need to modify its + // parent (even grandparent) width if it is not auto + Length styleWidth = style()->width(); + if (styleWidth.isFixed()) { + // now we need to get max style width + maxWidth -= borderLeft() + borderRight() + paddingLeft() + paddingRight(); + style()->setWidth(Length(maxWidth, Fixed)); + } else if (styleWidth.isPercent()) { + RenderObject* o = this; + while (RenderBox* p = (RenderBox*)(o->parent())) { + int maxParentWidth = (int)(maxWidth * 100 / styleWidth.percent()); + if (p->width() <= maxParentWidth) + break; + p->setWidth(maxParentWidth); + styleWidth = p->style()->width(); + if (!styleWidth.isPercent()) + break; + o = p; + maxWidth = maxParentWidth; + } + } + } + } +#endif if (oldWidth != m_width) relayoutChildren = true; +#ifdef ANDROID_LAYOUT + if (oldVisibleWidth != m_visibleWidth + && document()->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) + relayoutChildren = true; +#endif + int searchExtrasWidth = 0; if (m_resultsButton) { m_resultsButton->renderer()->calcWidth(); @@ -892,6 +948,18 @@ void RenderTextControl::calcPrefWidths() m_minPrefWidth += toAdd; m_maxPrefWidth += toAdd; + // FIXME: This causes cnn.com loading way slow. Comment it out for now +//#ifdef ANDROID_LAYOUT +#if 0 + Frame* frame = document()->frame(); + if (frame && frame->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) { + int maxWidth = frame->view()->visibleWidth() - 2 * ANDROID_FCTS_MARGIN_PADDING; + if (maxWidth > 0 && maxWidth < m_minPrefWidth) + m_minPrefWidth = maxWidth; + if (maxWidth > 0 && maxWidth < m_maxPrefWidth) + m_maxPrefWidth = maxWidth; + } +#endif setPrefWidthsDirty(false); } diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp index 41c19d8..417b1c1 100644 --- a/WebCore/rendering/RenderTheme.cpp +++ b/WebCore/rendering/RenderTheme.cpp @@ -22,7 +22,6 @@ #include "config.h" #include "RenderTheme.h" -#include "CSSValueKeywords.h" #include "Document.h" #include "FocusController.h" #include "Frame.h" @@ -518,71 +517,6 @@ void RenderTheme::platformColorsDidChange() m_inactiveSelectionColor = Color(); } -Color RenderTheme::systemColor(int cssValueId) const -{ - switch (cssValueId) { - case CSS_VAL_ACTIVEBORDER: - return 0xFFFFFFFF; - case CSS_VAL_ACTIVECAPTION: - return 0xFFCCCCCC; - case CSS_VAL_APPWORKSPACE: - return 0xFFFFFFFF; - case CSS_VAL_BACKGROUND: - return 0xFF6363CE; - case CSS_VAL_BUTTONFACE: - return 0xFFC0C0C0; - case CSS_VAL_BUTTONHIGHLIGHT: - return 0xFFDDDDDD; - case CSS_VAL_BUTTONSHADOW: - return 0xFF888888; - case CSS_VAL_BUTTONTEXT: - return 0xFF000000; - case CSS_VAL_CAPTIONTEXT: - return 0xFF000000; - case CSS_VAL_GRAYTEXT: - return 0xFF808080; - case CSS_VAL_HIGHLIGHT: - return 0xFFB5D5FF; - case CSS_VAL_HIGHLIGHTTEXT: - return 0xFF000000; - case CSS_VAL_INACTIVEBORDER: - return 0xFFFFFFFF; - case CSS_VAL_INACTIVECAPTION: - return 0xFFFFFFFF; - case CSS_VAL_INACTIVECAPTIONTEXT: - return 0xFF7F7F7F; - case CSS_VAL_INFOBACKGROUND: - return 0xFFFBFCC5; - case CSS_VAL_INFOTEXT: - return 0xFF000000; - case CSS_VAL_MENU: - return 0xFFC0C0C0; - case CSS_VAL_MENUTEXT: - return 0xFF000000; - case CSS_VAL_SCROLLBAR: - return 0xFFFFFFFF; - case CSS_VAL_TEXT: - return 0xFF000000; - case CSS_VAL_THREEDDARKSHADOW: - return 0xFF666666; - case CSS_VAL_THREEDFACE: - return 0xFFC0C0C0; - case CSS_VAL_THREEDHIGHLIGHT: - return 0xFFDDDDDD; - case CSS_VAL_THREEDLIGHTSHADOW: - return 0xFFC0C0C0; - case CSS_VAL_THREEDSHADOW: - return 0xFF888888; - case CSS_VAL_WINDOW: - return 0xFFFFFFFF; - case CSS_VAL_WINDOWFRAME: - return 0xFFCCCCCC; - case CSS_VAL_WINDOWTEXT: - return 0xFF000000; - } - return Color(); -} - Color RenderTheme::platformTextSearchHighlightColor() const { return Color(255, 255, 0); diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h index 2fcf798..308e81e 100644 --- a/WebCore/rendering/RenderTheme.h +++ b/WebCore/rendering/RenderTheme.h @@ -117,13 +117,12 @@ public: virtual Color inactiveListBoxSelectionBackgroundColor() const; virtual Color inactiveListBoxSelectionForegroundColor() const; - virtual void platformColorsDidChange(); + void platformColorsDidChange(); virtual double caretBlinkFrequency() const { return 0.5; } - // System fonts and colors for CSS. + // System fonts. virtual void systemFont(int cssValueId, FontDescription&) const = 0; - virtual Color systemColor(int cssValueId) const; virtual int minimumMenuListSize(RenderStyle*) const { return 0; } diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h index f2356e5..6d20bd9 100644 --- a/WebCore/rendering/RenderThemeMac.h +++ b/WebCore/rendering/RenderThemeMac.h @@ -24,7 +24,6 @@ #define RenderThemeMac_h #import "RenderTheme.h" -#import <wtf/HashMap.h> #import <wtf/RetainPtr.h> #ifdef __OBJC__ @@ -58,11 +57,11 @@ public: virtual bool isControlStyled(const RenderStyle*, const BorderData&, const BackgroundLayer&, const Color& backgroundColor) const; + virtual void paintResizeControl(GraphicsContext*, const IntRect&); + virtual Color platformActiveSelectionBackgroundColor() const; virtual Color platformInactiveSelectionBackgroundColor() const; virtual Color activeListBoxSelectionBackgroundColor() const; - - virtual void platformColorsDidChange(); // System fonts. virtual void systemFont(int cssValueId, FontDescription&) const; @@ -78,8 +77,6 @@ public: virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual Color systemColor(int cssValueId) const; - protected: // Methods for each appearance value. virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); @@ -185,6 +182,7 @@ private: NSMenu* searchMenuTemplate() const; NSSliderCell* sliderThumbHorizontal() const; NSSliderCell* sliderThumbVertical() const; + Image* resizeCornerImage() const; private: mutable RetainPtr<NSButtonCell> m_checkbox; @@ -195,12 +193,11 @@ private: mutable RetainPtr<NSMenu> m_searchMenuTemplate; mutable RetainPtr<NSSliderCell> m_sliderThumbHorizontal; mutable RetainPtr<NSSliderCell> m_sliderThumbVertical; + mutable Image* m_resizeCornerImage; bool m_isSliderThumbHorizontalPressed; bool m_isSliderThumbVerticalPressed; - mutable HashMap<int, RGBA32> m_systemColorCache; - RetainPtr<WebCoreRenderThemeNotificationObserver> m_notificationObserver; }; diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index 34487d7..887ef0a 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -105,7 +105,8 @@ RenderTheme* theme() } RenderThemeMac::RenderThemeMac() - : m_isSliderThumbHorizontalPressed(false) + : m_resizeCornerImage(0) + , m_isSliderThumbHorizontalPressed(false) , m_isSliderThumbVerticalPressed(false) , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this]) { @@ -118,6 +119,7 @@ RenderThemeMac::RenderThemeMac() RenderThemeMac::~RenderThemeMac() { [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()]; + delete m_resizeCornerImage; } Color RenderThemeMac::platformActiveSelectionBackgroundColor() const @@ -199,190 +201,6 @@ void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription fontDescription = *cachedDesc; } -static RGBA32 convertNSColorToColor(NSColor *color) -{ - NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; - if (colorInColorSpace) { - static const double scaleFactor = nextafter(256.0, 0.0); - return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]), - static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]), - static_cast<int>(scaleFactor * [colorInColorSpace blueComponent])); - } - - // This conversion above can fail if the NSColor in question is an NSPatternColor - // (as many system colors are). These colors are actually a repeating pattern - // not just a solid color. To work around this we simply draw a 1x1 image of - // the color and use that pixel's color. It might be better to use an average of - // the colors in the pattern instead. - NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil - pixelsWide:1 - pixelsHigh:1 - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bytesPerRow:4 - bitsPerPixel:32]; - - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]]; - NSEraseRect(NSMakeRect(0, 0, 1, 1)); - [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)]; - [NSGraphicsContext restoreGraphicsState]; - - NSUInteger pixel[4]; - [offscreenRep getPixel:pixel atX:0 y:0]; - - [offscreenRep release]; - - return makeRGB(pixel[0], pixel[1], pixel[2]); -} - -static RGBA32 menuBackgroundColor() -{ - NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil - pixelsWide:1 - pixelsHigh:1 - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bytesPerRow:4 - bitsPerPixel:32]; - - CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]); - CGRect rect = CGRectMake(0, 0, 1, 1); - HIThemeMenuDrawInfo drawInfo; - drawInfo.version = 0; - drawInfo.menuType = kThemeMenuTypePopUp; - HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted); - - NSUInteger pixel[4]; - [offscreenRep getPixel:pixel atX:0 y:0]; - - [offscreenRep release]; - - return makeRGB(pixel[0], pixel[1], pixel[2]); -} - -void RenderThemeMac::platformColorsDidChange() -{ - m_systemColorCache.clear(); - RenderTheme::platformColorsDidChange(); -} - -Color RenderThemeMac::systemColor(int cssValueId) const -{ - if (m_systemColorCache.contains(cssValueId)) - return m_systemColorCache.get(cssValueId); - - Color color; - switch (cssValueId) { - case CSS_VAL_ACTIVEBORDER: - color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); - break; - case CSS_VAL_ACTIVECAPTION: - color = convertNSColorToColor([NSColor windowFrameTextColor]); - break; - case CSS_VAL_APPWORKSPACE: - color = convertNSColorToColor([NSColor headerColor]); - break; - case CSS_VAL_BACKGROUND: - // Use theme independent default - break; - case CSS_VAL_BUTTONFACE: - // We use this value instead of NSColor's controlColor to avoid website incompatibilities. - // We may want to change this to use the NSColor in future. - color = 0xFFC0C0C0; - break; - case CSS_VAL_BUTTONHIGHLIGHT: - color = convertNSColorToColor([NSColor controlHighlightColor]); - break; - case CSS_VAL_BUTTONSHADOW: - color = convertNSColorToColor([NSColor controlShadowColor]); - break; - case CSS_VAL_BUTTONTEXT: - color = convertNSColorToColor([NSColor controlTextColor]); - break; - case CSS_VAL_CAPTIONTEXT: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSS_VAL_GRAYTEXT: - color = convertNSColorToColor([NSColor disabledControlTextColor]); - break; - case CSS_VAL_HIGHLIGHT: - color = convertNSColorToColor([NSColor selectedTextBackgroundColor]); - break; - case CSS_VAL_HIGHLIGHTTEXT: - color = convertNSColorToColor([NSColor selectedTextColor]); - break; - case CSS_VAL_INACTIVEBORDER: - color = convertNSColorToColor([NSColor controlBackgroundColor]); - break; - case CSS_VAL_INACTIVECAPTION: - color = convertNSColorToColor([NSColor controlBackgroundColor]); - break; - case CSS_VAL_INACTIVECAPTIONTEXT: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSS_VAL_INFOBACKGROUND: - // There is no corresponding NSColor for this so we use a hard coded value. - color = 0xFFFBFCC5; - break; - case CSS_VAL_INFOTEXT: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSS_VAL_MENU: - color = menuBackgroundColor(); - break; - case CSS_VAL_MENUTEXT: - color = convertNSColorToColor([NSColor selectedMenuItemTextColor]); - break; - case CSS_VAL_SCROLLBAR: - color = convertNSColorToColor([NSColor scrollBarColor]); - break; - case CSS_VAL_TEXT: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSS_VAL_THREEDDARKSHADOW: - color = convertNSColorToColor([NSColor controlDarkShadowColor]); - break; - case CSS_VAL_THREEDSHADOW: - color = convertNSColorToColor([NSColor shadowColor]); - break; - case CSS_VAL_THREEDFACE: - // We use this value instead of NSColor's controlColor to avoid website incompatibilities. - // We may want to change this to use the NSColor in future. - color = 0xFFC0C0C0; - break; - case CSS_VAL_THREEDHIGHLIGHT: - color = convertNSColorToColor([NSColor highlightColor]); - break; - case CSS_VAL_THREEDLIGHTSHADOW: - color = convertNSColorToColor([NSColor controlLightHighlightColor]); - break; - case CSS_VAL_WINDOW: - color = convertNSColorToColor([NSColor windowBackgroundColor]); - break; - case CSS_VAL_WINDOWFRAME: - color = convertNSColorToColor([NSColor windowFrameColor]); - break; - case CSS_VAL_WINDOWTEXT: - color = convertNSColorToColor([NSColor windowFrameTextColor]); - break; - } - - if (!color.isValid()) - color = RenderTheme::systemColor(cssValueId); - - if (color.isValid()) - m_systemColorCache.set(cssValueId, color.rgb()); - - return color; -} - bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border, const BackgroundLayer& background, const Color& backgroundColor) const { @@ -391,6 +209,13 @@ bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& return RenderTheme::isControlStyled(style, border, background, backgroundColor); } +void RenderThemeMac::paintResizeControl(GraphicsContext* c, const IntRect& r) +{ + Image* resizeCornerImage = this->resizeCornerImage(); + IntPoint imagePoint(r.right() - resizeCornerImage->width(), r.bottom() - resizeCornerImage->height()); + c->drawImage(resizeCornerImage, imagePoint); +} + void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r) { switch (o->style()->appearance()) { @@ -1704,4 +1529,11 @@ NSSliderCell* RenderThemeMac::sliderThumbVertical() const return m_sliderThumbVertical.get(); } +Image* RenderThemeMac::resizeCornerImage() const +{ + if (!m_resizeCornerImage) + m_resizeCornerImage = Image::loadPlatformResource("textAreaResizeCorner"); + return m_resizeCornerImage; +} + } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeWin.cpp b/WebCore/rendering/RenderThemeWin.cpp index 4317ff9..122c30e 100644 --- a/WebCore/rendering/RenderThemeWin.cpp +++ b/WebCore/rendering/RenderThemeWin.cpp @@ -23,18 +23,14 @@ #include "config.h" #include "RenderThemeWin.h" -#include "CSSValueKeywords.h" +#include <cairo-win32.h> #include "Document.h" #include "GraphicsContext.h" -#include "PlatformString.h" -#include "SoftLinking.h" - -#include <cairo-win32.h> /* * The following constants are used to determine how a widget is drawn using * Windows' Theme API. For more information on theme parts and states see - * http://msdn2.microsoft.com/en-us/library/bb773210(VS.85).aspx + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp */ #define THEME_COLOR 204 #define THEME_FONT 210 @@ -58,15 +54,33 @@ // Combobox constants #define CP_DROPDOWNBUTTON 1 -SOFT_LINK_LIBRARY(uxtheme) -SOFT_LINK(uxtheme, OpenThemeData, HANDLE, WINAPI, (HWND hwnd, LPCWSTR pszClassList), (hwnd, pszClassList)) -SOFT_LINK(uxtheme, CloseThemeData, HRESULT, WINAPI, (HANDLE hTheme), (hTheme)) -SOFT_LINK(uxtheme, DrawThemeBackground, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT* pRect, const RECT* pClipRect), (hTheme, hdc, iPartId, iStateId, pRect, pClipRect)) -SOFT_LINK(uxtheme, DrawThemeEdge, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT* pRect, unsigned uEdge, unsigned uFlags, const RECT* pClipRect), (hTheme, hdc, iPartId, iStateId, pRect, uEdge, uFlags, pClipRect)) -SOFT_LINK(uxtheme, GetThemeContentRect, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT* pRect, const RECT* pContentRect), (hTheme, hdc, iPartId, iStateId, pRect, pContentRect)) -SOFT_LINK(uxtheme, GetThemePartSize, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, RECT* pRect, int ts, SIZE* psz), (hTheme, hdc, iPartId, iStateId, pRect, ts, psz)) -SOFT_LINK(uxtheme, GetThemeSysFont, HRESULT, WINAPI, (HANDLE hTheme, int iFontId, OUT LOGFONT* pFont), (hTheme, iFontId, pFont)) -SOFT_LINK(uxtheme, GetThemeColor, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, int iPropId, OUT COLORREF* pColor), (hTheme, hdc, iPartId, iStateId, iPropId, pColor)) +typedef HANDLE (WINAPI*openThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList); +typedef HRESULT (WINAPI*closeThemeDataPtr)(HANDLE hTheme); +typedef HRESULT (WINAPI*drawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId, + int iStateId, const RECT *pRect, + const RECT* pClipRect); +typedef HRESULT (WINAPI*drawThemeEdgePtr)(HANDLE hTheme, HDC hdc, int iPartId, + int iStateId, const RECT *pRect, + unsigned uEdge, unsigned uFlags, + const RECT* pClipRect); +typedef HRESULT (WINAPI*getThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId, + int iStateId, const RECT* pRect, + RECT* pContentRect); +typedef HRESULT (WINAPI*getThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId, + int iStateId, RECT* prc, int ts, + SIZE* psz); +typedef HRESULT (WINAPI*getThemeSysFontPtr)(HANDLE hTheme, int iFontId, OUT LOGFONT* pFont); +typedef HRESULT (WINAPI*getThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId, + int iStateId, int iPropId, OUT COLORREF* pFont); + +static openThemeDataPtr openTheme = 0; +static closeThemeDataPtr closeTheme = 0; +static drawThemeBackgroundPtr drawThemeBG = 0; +static drawThemeEdgePtr drawThemeEdge = 0; +static getThemeContentRectPtr getThemeContentRect = 0; +static getThemePartSizePtr getThemePartSize = 0; +static getThemeSysFontPtr getThemeSysFont = 0; +static getThemeColorPtr getThemeColor = 0; namespace WebCore { @@ -77,29 +91,40 @@ RenderTheme* theme() } RenderThemeWin::RenderThemeWin() - : m_buttonTheme(0) - , m_textFieldTheme(0) - , m_menuListTheme(0) +:m_themeDLL(0), m_buttonTheme(0), m_textFieldTheme(0), m_menuListTheme(0) { + m_themeDLL = ::LoadLibrary(L"uxtheme.dll"); + if (m_themeDLL) { + openTheme = (openThemeDataPtr)GetProcAddress(m_themeDLL, "OpenThemeData"); + closeTheme = (closeThemeDataPtr)GetProcAddress(m_themeDLL, "CloseThemeData"); + drawThemeBG = (drawThemeBackgroundPtr)GetProcAddress(m_themeDLL, "DrawThemeBackground"); + drawThemeEdge = (drawThemeEdgePtr)GetProcAddress(m_themeDLL, "DrawThemeEdge"); + getThemeContentRect = (getThemeContentRectPtr)GetProcAddress(m_themeDLL, "GetThemeBackgroundContentRect"); + getThemePartSize = (getThemePartSizePtr)GetProcAddress(m_themeDLL, "GetThemePartSize"); + getThemeSysFont = (getThemeSysFontPtr)GetProcAddress(m_themeDLL, "GetThemeSysFont"); + getThemeColor = (getThemeColorPtr)GetProcAddress(m_themeDLL, "GetThemeColor"); + } } RenderThemeWin::~RenderThemeWin() { - if (!uxthemeLibrary()) + if (!m_themeDLL) return; close(); + + ::FreeLibrary(m_themeDLL); } void RenderThemeWin::close() { // This method will need to be called when the OS theme changes to flush our cached themes. if (m_buttonTheme) - CloseThemeData(m_buttonTheme); + closeTheme(m_buttonTheme); if (m_textFieldTheme) - CloseThemeData(m_textFieldTheme); + closeTheme(m_textFieldTheme); if (m_menuListTheme) - CloseThemeData(m_menuListTheme); + closeTheme(m_menuListTheme); m_buttonTheme = m_textFieldTheme = m_menuListTheme = 0; } @@ -137,6 +162,8 @@ bool RenderThemeWin::supportsFocus(EAppearance appearance) default: return false; } + + return false; } unsigned RenderThemeWin::determineState(RenderObject* o) @@ -203,14 +230,14 @@ ThemeData RenderThemeWin::getThemeData(RenderObject* o) } // May need to add stuff to these later, so keep the graphics context retrieval/release in some helpers. -static HDC prepareForDrawing(GraphicsContext* g, const IntRect& r) +static HDC prepareForDrawing(GraphicsContext* g) { - return g->getWindowsContext(r); + return g->getWindowsContext(); } -static void doneDrawing(GraphicsContext* g, HDC hdc, const IntRect& r) +static void doneDrawing(GraphicsContext* g, HDC hdc) { - g->releaseWindowsContext(hdc, r); + g->releaseWindowsContext(hdc); } bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) @@ -219,13 +246,13 @@ bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& ThemeData themeData = getThemeData(o); // Now paint the button. - HDC hdc = prepareForDrawing(i.context, r); + HDC hdc = prepareForDrawing(i.context); RECT widgetRect = r; - if (uxthemeLibrary() && !m_buttonTheme) - m_buttonTheme = OpenThemeData(0, L"Button"); - if (m_buttonTheme) - DrawThemeBackground(m_buttonTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL); - else { + if (m_themeDLL && !m_buttonTheme) + m_buttonTheme = openTheme(0, L"Button"); + if (m_buttonTheme && drawThemeBG) { + drawThemeBG(m_buttonTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL); + } else { if ((themeData.m_part == BP_BUTTON) && isFocused(o)) { // Draw black focus rect around button outer edge HBRUSH brush = GetSysColorBrush(COLOR_3DDKSHADOW); @@ -235,10 +262,11 @@ bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& } } DrawFrameControl(hdc, &widgetRect, DFC_BUTTON, themeData.m_classicState); - if ((themeData.m_part != BP_BUTTON) && isFocused(o)) + if ((themeData.m_part != BP_BUTTON) && isFocused(o)) { DrawFocusRect(hdc, &widgetRect); + } } - doneDrawing(i.context, hdc, r); + doneDrawing(i.context, hdc); return false; } @@ -265,17 +293,17 @@ bool RenderThemeWin::paintTextField(RenderObject* o, const RenderObject::PaintIn ThemeData themeData = getThemeData(o); // Now paint the text field. - HDC hdc = prepareForDrawing(i.context, r); + HDC hdc = prepareForDrawing(i.context); RECT widgetRect = r; - if (uxthemeLibrary() && !m_textFieldTheme) - m_textFieldTheme = OpenThemeData(0, L"Edit"); - if (m_textFieldTheme) - DrawThemeBackground(m_textFieldTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL); - else { + if (m_themeDLL && !m_textFieldTheme) + m_textFieldTheme = openTheme(0, L"Edit"); + if (m_textFieldTheme && drawThemeBG) { + drawThemeBG(m_textFieldTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL); + } else { DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); FillRect(hdc, &widgetRect, reinterpret_cast<HBRUSH>(((themeData.m_classicState & DFCS_INACTIVE) ? COLOR_BTNFACE : COLOR_WINDOW) + 1)); } - doneDrawing(i.context, hdc, r); + doneDrawing(i.context, hdc); return false; } @@ -313,67 +341,17 @@ bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInf bool RenderThemeWin::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { - HDC hdc = prepareForDrawing(i.context, r); + HDC hdc = prepareForDrawing(i.context); RECT widgetRect = r; - if (uxthemeLibrary() && !m_menuListTheme) - m_menuListTheme = OpenThemeData(0, L"Combobox"); - if (m_menuListTheme) - DrawThemeBackground(m_menuListTheme, hdc, CP_DROPDOWNBUTTON, determineState(o), &widgetRect, NULL); + if (m_themeDLL && !m_menuListTheme) + m_menuListTheme = openTheme(0, L"Combobox"); + if (m_menuListTheme && drawThemeBG) + drawThemeBG(m_menuListTheme, hdc, CP_DROPDOWNBUTTON, determineState(o), &widgetRect, NULL); else DrawFrameControl(hdc, &widgetRect, DFC_SCROLL, DFCS_SCROLLCOMBOBOX | determineClassicState(o)); - doneDrawing(i.context, hdc, r); + doneDrawing(i.context, hdc); return false; } -void RenderThemeWin::systemFont(int propId, FontDescription& fontDescription) const -{ - static FontDescription systemFont; - static FontDescription smallSystemFont; - static FontDescription menuFont; - static FontDescription labelFont; - static FontDescription miniControlFont; - static FontDescription smallControlFont; - static FontDescription controlFont; - - FontDescription* cachedDesc; - float fontSize = 0; - switch (propId) { - case CSS_VAL_SMALL_CAPTION: - cachedDesc = &smallSystemFont; - break; - case CSS_VAL_MENU: - cachedDesc = &menuFont; - break; - case CSS_VAL_STATUS_BAR: - cachedDesc = &labelFont; - if (!labelFont.isAbsoluteSize()) - fontSize = 10.0f; - break; - case CSS_VAL__WEBKIT_MINI_CONTROL: - cachedDesc = &miniControlFont; - break; - case CSS_VAL__WEBKIT_SMALL_CONTROL: - cachedDesc = &smallControlFont; - break; - case CSS_VAL__WEBKIT_CONTROL: - cachedDesc = &controlFont; - break; - default: - cachedDesc = &systemFont; - if (!systemFont.isAbsoluteSize()) - fontSize = 13.0f; - } - - if (fontSize) { - cachedDesc->setIsAbsoluteSize(true); - cachedDesc->setGenericFamily(FontDescription::NoFamily); - cachedDesc->firstFamily().setFamily("Lucida Grande"); - cachedDesc->setSpecifiedSize(fontSize); - cachedDesc->setBold(false); - cachedDesc->setItalic(false); - } - fontDescription = *cachedDesc; } - -} // namespace diff --git a/WebCore/rendering/RenderThemeWin.h b/WebCore/rendering/RenderThemeWin.h index bd27035..08f10b0 100644 --- a/WebCore/rendering/RenderThemeWin.h +++ b/WebCore/rendering/RenderThemeWin.h @@ -1,7 +1,7 @@ /* * This file is part of the WebKit project. * - * Copyright (C) 2006, 2008 Apple Computer, Inc. + * Copyright (C) 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -88,6 +88,7 @@ private: ThemeData getThemeData(RenderObject*); + HMODULE m_themeDLL; mutable HANDLE m_buttonTheme; mutable HANDLE m_textFieldTheme; mutable HANDLE m_menuListTheme; diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index 15bc6c0..eef4866 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -39,7 +39,6 @@ #include "RenderView.h" #include "RenderWidget.h" #include "SelectionController.h" -#include "TextStream.h" #include <wtf/Vector.h> #if ENABLE(SVG) @@ -490,23 +489,24 @@ static void writeSelection(TextStream& ts, const RenderObject* o) << "selection end: position " << selection.end().offset() << " of " << nodePosition(selection.end().node()) << "\n"; } -String externalRepresentation(RenderObject* o) +DeprecatedString externalRepresentation(RenderObject* o) { - if (!o) - return String(); - - TextStream ts; + DeprecatedString s; + if (o) { + TextStream ts(&s); + ts.precision(2); #if ENABLE(SVG) - writeRenderResources(ts, o->document()); + writeRenderResources(ts, o->document()); #endif - if (o->view()->frameView()) - o->view()->frameView()->layout(); - RenderLayer* l = o->layer(); - if (l) { - writeLayers(ts, l, l, IntRect(l->xPos(), l->yPos(), l->width(), l->height())); - writeSelection(ts, o); + if (o->view()->frameView()) + o->view()->frameView()->layout(); + RenderLayer* l = o->layer(); + if (l) { + writeLayers(ts, l, l, IntRect(l->xPos(), l->yPos(), l->width(), l->height())); + writeSelection(ts, o); + } } - return ts.release(); + return s; } } // namespace WebCore diff --git a/WebCore/rendering/RenderTreeAsText.h b/WebCore/rendering/RenderTreeAsText.h index daca253..c42a5b7 100644 --- a/WebCore/rendering/RenderTreeAsText.h +++ b/WebCore/rendering/RenderTreeAsText.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,13 +26,13 @@ #ifndef RenderTreeAsText_h #define RenderTreeAsText_h +#include "TextStream.h" + namespace WebCore { class RenderObject; - class String; - class TextStream; - String externalRepresentation(RenderObject*); + DeprecatedString externalRepresentation(RenderObject*); void write(TextStream&, const RenderObject&, int indent = 0); // Helper function shared with SVGRenderTreeAsText diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp index bd9c500..09ecacb 100644 --- a/WebCore/rendering/RenderView.cpp +++ b/WebCore/rendering/RenderView.cpp @@ -29,6 +29,11 @@ #include "GraphicsContext.h" #include "RenderLayer.h" +#ifdef ANDROID_LAYOUT +#include "Settings.h" +#include "WebCoreViewBridge.h" +#endif + namespace WebCore { RenderView::RenderView(Node* node, FrameView* view) @@ -79,6 +84,14 @@ void RenderView::calcWidth() { if (!printing() && m_frameView) m_width = m_frameView->visibleWidth(); +#ifdef ANDROID_LAYOUT + const Settings * settings = document()->settings(); + ASSERT(settings); + if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) + m_visibleWidth = m_frameView->getWebCoreViewBridge()->screenWidth(); + if (settings->useWideViewport() && settings->viewportWidth() == -1 && m_width < minPrefWidth()) + m_width = m_minPrefWidth; +#endif m_marginLeft = 0; m_marginRight = 0; } diff --git a/WebCore/rendering/RenderWordBreak.cpp b/WebCore/rendering/RenderWordBreak.cpp index a620560..e7036f9 100644 --- a/WebCore/rendering/RenderWordBreak.cpp +++ b/WebCore/rendering/RenderWordBreak.cpp @@ -32,7 +32,7 @@ namespace WebCore { RenderWordBreak::RenderWordBreak(HTMLElement* element) - : RenderText(element, StringImpl::empty()) + : RenderInline(element) { } @@ -46,4 +46,9 @@ bool RenderWordBreak::isWordBreak() const return true; } +bool RenderWordBreak::canHaveChildren() const +{ + return false; +} + } diff --git a/WebCore/rendering/RenderWordBreak.h b/WebCore/rendering/RenderWordBreak.h index acd8179..51c15a6 100644 --- a/WebCore/rendering/RenderWordBreak.h +++ b/WebCore/rendering/RenderWordBreak.h @@ -27,18 +27,19 @@ #ifndef RenderWordBreak_h #define RenderWordBreak_h -#include "RenderText.h" +#include "RenderInline.h" namespace WebCore { class HTMLElement; -class RenderWordBreak : public RenderText { +class RenderWordBreak : public RenderInline { public: RenderWordBreak(HTMLElement*); virtual const char* renderName() const; virtual bool isWordBreak() const; + virtual bool canHaveChildren() const; }; } diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.h b/WebCore/rendering/SVGCharacterLayoutInfo.h index b9143a2..4124323 100644 --- a/WebCore/rendering/SVGCharacterLayoutInfo.h +++ b/WebCore/rendering/SVGCharacterLayoutInfo.h @@ -177,7 +177,16 @@ private: // Holds extra data, when the character is laid out on a path struct SVGCharOnPath : RefCounted<SVGCharOnPath> { - static PassRefPtr<SVGCharOnPath> create() { return adoptRef(new SVGCharOnPath); } + SVGCharOnPath() + : RefCounted<SVGCharOnPath>() + , xScale(1.0f) + , yScale(1.0f) + , xShift(0.0f) + , yShift(0.0f) + , orientationAngle(0.0f) + , hidden(false) + { + } float xScale; float yScale; @@ -188,17 +197,6 @@ struct SVGCharOnPath : RefCounted<SVGCharOnPath> { float orientationAngle; bool hidden : 1; - -private: - SVGCharOnPath() - : xScale(1.0f) - , yScale(1.0f) - , xShift(0.0f) - , yShift(0.0f) - , orientationAngle(0.0f) - , hidden(false) - { - } }; struct SVGChar { diff --git a/WebCore/rendering/SVGRenderStyle.cpp b/WebCore/rendering/SVGRenderStyle.cpp index 1749978..ddca85d 100644 --- a/WebCore/rendering/SVGRenderStyle.cpp +++ b/WebCore/rendering/SVGRenderStyle.cpp @@ -38,23 +38,26 @@ namespace WebCore { +SVGRenderStyle *SVGRenderStyle::s_defaultStyle = 0; + SVGRenderStyle::SVGRenderStyle() { - static SVGRenderStyle* defaultStyle = new SVGRenderStyle(CreateDefault); - - fill = defaultStyle->fill; - stroke = defaultStyle->stroke; - text = defaultStyle->text; - stops = defaultStyle->stops; - clip = defaultStyle->clip; - mask = defaultStyle->mask; - misc = defaultStyle->misc; - markers = defaultStyle->markers; + if (!s_defaultStyle) + s_defaultStyle = new SVGRenderStyle(true); + + fill = s_defaultStyle->fill; + stroke = s_defaultStyle->stroke; + text = s_defaultStyle->text; + stops = s_defaultStyle->stops; + clip = s_defaultStyle->clip; + mask = s_defaultStyle->mask; + misc = s_defaultStyle->misc; + markers = s_defaultStyle->markers; setBitDefaults(); } -SVGRenderStyle::SVGRenderStyle(CreateDefaultType) +SVGRenderStyle::SVGRenderStyle(bool) { setBitDefaults(); @@ -68,8 +71,7 @@ SVGRenderStyle::SVGRenderStyle(CreateDefaultType) markers.init(); } -SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle& other) - : RefCounted<SVGRenderStyle>() +SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle &other) : RefCounted<SVGRenderStyle>() { fill = other.fill; stroke = other.stroke; diff --git a/WebCore/rendering/SVGRenderStyle.h b/WebCore/rendering/SVGRenderStyle.h index 5724621..5fb395a 100644 --- a/WebCore/rendering/SVGRenderStyle.h +++ b/WebCore/rendering/SVGRenderStyle.h @@ -40,8 +40,9 @@ namespace WebCore { class SVGRenderStyle : public RefCounted<SVGRenderStyle> { public: - static PassRefPtr<SVGRenderStyle> create() { return adoptRef(new SVGRenderStyle); } - PassRefPtr<SVGRenderStyle> copy() const { return adoptRef(new SVGRenderStyle(*this));} + SVGRenderStyle(); + SVGRenderStyle(bool); // Used to create the default style. + SVGRenderStyle(const SVGRenderStyle&); ~SVGRenderStyle(); bool inheritedNotEqual(const SVGRenderStyle*) const; @@ -179,12 +180,11 @@ namespace WebCore { DataRef<StyleMaskData> mask; DataRef<StyleMiscData> misc; + // static default style + static SVGRenderStyle *s_defaultStyle; + private: - enum CreateDefaultType { CreateDefault }; - - SVGRenderStyle(); - SVGRenderStyle(const SVGRenderStyle&); - SVGRenderStyle(CreateDefaultType); // Used to create the default style. + SVGRenderStyle(const SVGRenderStyle*) { } void setBitDefaults() { diff --git a/WebCore/rendering/SVGRenderStyleDefs.cpp b/WebCore/rendering/SVGRenderStyleDefs.cpp index f5faad3..641c04c 100644 --- a/WebCore/rendering/SVGRenderStyleDefs.cpp +++ b/WebCore/rendering/SVGRenderStyleDefs.cpp @@ -35,14 +35,13 @@ using namespace WebCore; -StyleFillData::StyleFillData() +StyleFillData::StyleFillData() : RefCounted<StyleFillData>() { paint = SVGRenderStyle::initialFillPaint(); opacity = SVGRenderStyle::initialFillOpacity(); } -StyleFillData::StyleFillData(const StyleFillData& other) - : RefCounted<StyleFillData>() +StyleFillData::StyleFillData(const StyleFillData &other) : RefCounted<StyleFillData>() { paint = other.paint; opacity = other.opacity; @@ -68,7 +67,7 @@ bool StyleFillData::operator==(const StyleFillData &other) const return paint == other.paint; } -StyleStrokeData::StyleStrokeData() +StyleStrokeData::StyleStrokeData() : RefCounted<StyleStrokeData>() { width = SVGRenderStyle::initialStrokeWidth(); paint = SVGRenderStyle::initialStrokePaint(); @@ -78,8 +77,7 @@ StyleStrokeData::StyleStrokeData() dashArray = SVGRenderStyle::initialStrokeDashArray(); } -StyleStrokeData::StyleStrokeData(const StyleStrokeData& other) - : RefCounted<StyleStrokeData>() +StyleStrokeData::StyleStrokeData(const StyleStrokeData &other) : RefCounted<StyleStrokeData>() { width = other.width; paint = other.paint; @@ -99,14 +97,13 @@ bool StyleStrokeData::operator==(const StyleStrokeData &other) const (dashArray == other.dashArray); } -StyleStopData::StyleStopData() +StyleStopData::StyleStopData() : RefCounted<StyleStopData>() { color = SVGRenderStyle::initialStopColor(); opacity = SVGRenderStyle::initialStopOpacity(); } -StyleStopData::StyleStopData(const StyleStopData& other) - : RefCounted<StyleStopData>() +StyleStopData::StyleStopData(const StyleStopData &other) : RefCounted<StyleStopData>() { color = other.color; opacity = other.opacity; @@ -118,13 +115,12 @@ bool StyleStopData::operator==(const StyleStopData &other) const (opacity == other.opacity); } -StyleTextData::StyleTextData() +StyleTextData::StyleTextData() : RefCounted<StyleTextData>() { kerning = SVGRenderStyle::initialKerning(); } -StyleTextData::StyleTextData(const StyleTextData& other) - : RefCounted<StyleTextData>() +StyleTextData::StyleTextData(const StyleTextData& other) : RefCounted<StyleTextData>() { kerning = other.kerning; } @@ -134,13 +130,12 @@ bool StyleTextData::operator==(const StyleTextData& other) const return kerning == other.kerning; } -StyleClipData::StyleClipData() +StyleClipData::StyleClipData() : RefCounted<StyleClipData>() { clipPath = SVGRenderStyle::initialClipPath(); } -StyleClipData::StyleClipData(const StyleClipData& other) - : RefCounted<StyleClipData>() +StyleClipData::StyleClipData(const StyleClipData &other) : RefCounted<StyleClipData>() { clipPath = other.clipPath; } @@ -150,13 +145,12 @@ bool StyleClipData::operator==(const StyleClipData &other) const return (clipPath == other.clipPath); } -StyleMaskData::StyleMaskData() +StyleMaskData::StyleMaskData() : RefCounted<StyleMaskData>() { maskElement = SVGRenderStyle::initialMaskElement(); } -StyleMaskData::StyleMaskData(const StyleMaskData& other) - : RefCounted<StyleMaskData>() +StyleMaskData::StyleMaskData(const StyleMaskData &other) : RefCounted<StyleMaskData>() { maskElement = other.maskElement; } @@ -166,15 +160,14 @@ bool StyleMaskData::operator==(const StyleMaskData &other) const return (maskElement == other.maskElement); } -StyleMarkerData::StyleMarkerData() +StyleMarkerData::StyleMarkerData() : RefCounted<StyleMarkerData>() { startMarker = SVGRenderStyle::initialStartMarker(); midMarker = SVGRenderStyle::initialMidMarker(); endMarker = SVGRenderStyle::initialEndMarker(); } -StyleMarkerData::StyleMarkerData(const StyleMarkerData& other) - : RefCounted<StyleMarkerData>() +StyleMarkerData::StyleMarkerData(const StyleMarkerData &other) : RefCounted<StyleMarkerData>() { startMarker = other.startMarker; midMarker = other.midMarker; @@ -186,7 +179,7 @@ bool StyleMarkerData::operator==(const StyleMarkerData &other) const return (startMarker == other.startMarker && midMarker == other.midMarker && endMarker == other.endMarker); } -StyleMiscData::StyleMiscData() +StyleMiscData::StyleMiscData() : RefCounted<StyleMiscData>() { floodColor = SVGRenderStyle::initialFloodColor(); floodOpacity = SVGRenderStyle::initialFloodOpacity(); @@ -194,8 +187,7 @@ StyleMiscData::StyleMiscData() baselineShiftValue = SVGRenderStyle::initialBaselineShiftValue(); } -StyleMiscData::StyleMiscData(const StyleMiscData& other) - : RefCounted<StyleMiscData>() +StyleMiscData::StyleMiscData(const StyleMiscData &other) : RefCounted<StyleMiscData>() { filter = other.filter; floodColor = other.floodColor; diff --git a/WebCore/rendering/SVGRenderStyleDefs.h b/WebCore/rendering/SVGRenderStyleDefs.h index 12a70d3..7b2dc1d 100644 --- a/WebCore/rendering/SVGRenderStyleDefs.h +++ b/WebCore/rendering/SVGRenderStyleDefs.h @@ -131,9 +131,9 @@ namespace WebCore { // Inherited/Non-Inherited Style Datastructures class StyleFillData : public RefCounted<StyleFillData> { public: - static PassRefPtr<StyleFillData> create() { return adoptRef(new StyleFillData); } - PassRefPtr<StyleFillData> copy() const { return adoptRef(new StyleFillData(*this)); } - + StyleFillData(); + StyleFillData(const StyleFillData &other); + bool operator==(const StyleFillData &other) const; bool operator!=(const StyleFillData &other) const { @@ -144,14 +144,13 @@ namespace WebCore { RefPtr<SVGPaint> paint; private: - StyleFillData(); - StyleFillData(const StyleFillData&); + StyleFillData &operator=(const StyleFillData &); }; class StyleStrokeData : public RefCounted<StyleStrokeData> { public: - static PassRefPtr<StyleStrokeData> create() { return adoptRef(new StyleStrokeData); } - PassRefPtr<StyleStrokeData> copy() const { return adoptRef(new StyleStrokeData(*this)); } + StyleStrokeData(); + StyleStrokeData(const StyleStrokeData&); bool operator==(const StyleStrokeData&) const; bool operator!=(const StyleStrokeData& other) const @@ -168,15 +167,14 @@ namespace WebCore { RefPtr<SVGPaint> paint; RefPtr<CSSValueList> dashArray; - private: - StyleStrokeData(); - StyleStrokeData(const StyleStrokeData&); + private: + StyleStrokeData &operator=(const StyleStrokeData&); }; class StyleStopData : public RefCounted<StyleStopData> { public: - static PassRefPtr<StyleStopData> create() { return adoptRef(new StyleStopData); } - PassRefPtr<StyleStopData> copy() const { return adoptRef(new StyleStopData(*this)); } + StyleStopData(); + StyleStopData(const StyleStopData &other); bool operator==(const StyleStopData &other) const; bool operator!=(const StyleStopData &other) const @@ -187,16 +185,15 @@ namespace WebCore { float opacity; Color color; - private: - StyleStopData(); - StyleStopData(const StyleStopData&); + private: + StyleStopData &operator=(const StyleStopData &); }; class StyleTextData : public RefCounted<StyleTextData> { public: - static PassRefPtr<StyleTextData> create() { return adoptRef(new StyleTextData); } - PassRefPtr<StyleTextData> copy() const { return adoptRef(new StyleTextData(*this)); } - + StyleTextData(); + StyleTextData(const StyleTextData& other); + bool operator==(const StyleTextData& other) const; bool operator!=(const StyleTextData& other) const { @@ -206,14 +203,13 @@ namespace WebCore { RefPtr<CSSValue> kerning; private: - StyleTextData(); - StyleTextData(const StyleTextData& other); + StyleTextData& operator=(const StyleTextData&); }; class StyleClipData : public RefCounted<StyleClipData> { public: - static PassRefPtr<StyleClipData> create() { return adoptRef(new StyleClipData); } - PassRefPtr<StyleClipData> copy() const { return adoptRef(new StyleClipData(*this)); } + StyleClipData(); + StyleClipData(const StyleClipData &other); bool operator==(const StyleClipData &other) const; bool operator!=(const StyleClipData &other) const @@ -224,29 +220,27 @@ namespace WebCore { String clipPath; private: - StyleClipData(); - StyleClipData(const StyleClipData&); + StyleClipData &operator=(const StyleClipData &); }; class StyleMaskData : public RefCounted<StyleMaskData> { public: - static PassRefPtr<StyleMaskData> create() { return adoptRef(new StyleMaskData); } - PassRefPtr<StyleMaskData> copy() const { return adoptRef(new StyleMaskData(*this)); } + StyleMaskData(); + StyleMaskData(const StyleMaskData &other); bool operator==(const StyleMaskData &other) const; bool operator!=(const StyleMaskData &other) const { return !(*this == other); } String maskElement; - private: - StyleMaskData(); - StyleMaskData(const StyleMaskData&); + private: + StyleMaskData &operator=(const StyleMaskData &); }; class StyleMarkerData : public RefCounted<StyleMarkerData> { public: - static PassRefPtr<StyleMarkerData> create() { return adoptRef(new StyleMarkerData); } - PassRefPtr<StyleMarkerData> copy() const { return adoptRef(new StyleMarkerData(*this)); } + StyleMarkerData(); + StyleMarkerData(const StyleMarkerData &other); bool operator==(const StyleMarkerData &other) const; bool operator!=(const StyleMarkerData &other) const @@ -259,15 +253,14 @@ namespace WebCore { String endMarker; private: - StyleMarkerData(); - StyleMarkerData(const StyleMarkerData&); + StyleMarkerData &operator=(const StyleMarkerData &); }; // Note : the rule for this class is, *no inheritance* of these props class StyleMiscData : public RefCounted<StyleMiscData> { public: - static PassRefPtr<StyleMiscData> create() { return adoptRef(new StyleMiscData); } - PassRefPtr<StyleMiscData> copy() const { return adoptRef(new StyleMiscData(*this)); } + StyleMiscData(); + StyleMiscData(const StyleMiscData &other); bool operator==(const StyleMiscData &other) const; bool operator!=(const StyleMiscData &other) const @@ -285,8 +278,7 @@ namespace WebCore { RefPtr<CSSValue> baselineShiftValue; private: - StyleMiscData(); - StyleMiscData(const StyleMiscData&); + StyleMiscData &operator=(const StyleMiscData &); }; } // namespace WebCore diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index db6e345..ee7806b 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -1,4 +1,6 @@ -/* +/** + * This file is part of the DOM implementation for WebKit. + * * Copyright (C) 2007 Rob Buis <buis@kde.org> * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * (C) 2007 Eric Seidel <eric@webkit.org> @@ -136,7 +138,6 @@ void renderSubtreeToImage(ImageBuffer* image, RenderObject* item) if (svgContainer && !drawsContents) svgContainer->setDrawsContents(true); - item->layoutIfNeeded(); item->paint(info, 0, 0); if (svgContainer && !drawsContents) diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index 4c13dc9..347f4ec 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -430,7 +430,7 @@ static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textB ts << " override"; } - ts << ": " << quoteAndEscapeNonPrintables(String(textBox->textObject()->text()).substring(textBox->start() + range.startOffset, offset)) << "\n"; + ts << ": " << quoteAndEscapeNonPrintables(String(textBox->textObject()->text()).substring(textBox->start() + range.startOffset, offset)) << endl; j++; } @@ -463,7 +463,7 @@ void write(TextStream& ts, const RenderSVGContainer& container, int indent) ts << " {" << tagName << "}"; } - ts << container << "\n"; + ts << container << endl; for (RenderObject* child = container.firstChild(); child; child = child->nextSibling()) write(ts, *child, indent + 1); @@ -480,7 +480,7 @@ void write(TextStream& ts, const RenderSVGRoot& root, int indent) ts << " {" << tagName << "}"; } - ts << root << "\n"; + ts << root << endl; for (RenderObject* child = root.firstChild(); child; child = child->nextSibling()) write(ts, *child, indent + 1); @@ -497,7 +497,7 @@ void write(TextStream& ts, const RenderSVGText& text, int indent) ts << " {" << tagName << "}"; } - ts << text << "\n"; + ts << text << endl; for (RenderObject* child = text.firstChild(); child; child = child->nextSibling()) write(ts, *child, indent + 1); @@ -514,7 +514,7 @@ void write(TextStream& ts, const RenderSVGInlineText& text, int indent) ts << " {" << tagName << "}"; } - ts << " at (" << text.xPos() << "," << text.yPos() << ") size " << text.width() << "x" << text.height() << "\n"; + ts << " at (" << text.xPos() << "," << text.yPos() << ") size " << text.width() << "x" << text.height() << endl; writeSVGInlineText(ts, text, indent); } @@ -529,7 +529,7 @@ void write(TextStream& ts, const RenderPath& path, int indent) ts << " {" << tagName << "}"; } - ts << path << "\n"; + ts << path << endl; } void writeRenderResources(TextStream& ts, Node* parent) @@ -551,9 +551,9 @@ void writeRenderResources(TextStream& ts, Node* parent) String elementId = svgElement->getAttribute(HTMLNames::idAttr); if (resource->isPaintServer()) { RefPtr<SVGPaintServer> paintServer = WTF::static_pointer_cast<SVGPaintServer>(resource); - ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *paintServer << "}" << "\n"; + ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *paintServer << "}" << endl; } else - ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << "\n"; + ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << endl; } while ((node = node->traverseNextNode(parent))); } diff --git a/WebCore/rendering/SVGRenderTreeAsText.h b/WebCore/rendering/SVGRenderTreeAsText.h index 2722613..e4c0efe 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.h +++ b/WebCore/rendering/SVGRenderTreeAsText.h @@ -28,6 +28,7 @@ #if ENABLE(SVG) +#include "DeprecatedString.h" #include "TextStream.h" namespace WebCore { diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp index d609687..b493e43 100644 --- a/WebCore/rendering/SVGRootInlineBox.cpp +++ b/WebCore/rendering/SVGRootInlineBox.cpp @@ -1114,7 +1114,7 @@ void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& SVGChar svgChar; if (info.inPathLayout()) - svgChar.pathData = SVGCharOnPath::create(); + svgChar.pathData = new SVGCharOnPath(); float glyphWidth = 0.0f; float glyphHeight = 0.0f; diff --git a/WebCore/rendering/bidi.cpp b/WebCore/rendering/bidi.cpp index 56fa321..e3e706b 100644 --- a/WebCore/rendering/bidi.cpp +++ b/WebCore/rendering/bidi.cpp @@ -35,6 +35,15 @@ #include "break_lines.h" #include <wtf/AlwaysInline.h> #include <wtf/Vector.h> +#ifdef ANDROID_LAYOUT +#include "Frame.h" +#include "FrameTree.h" +#include "Settings.h" +#include "Text.h" +#include "HTMLNames.h" +#include "WebCoreViewBridge.h" + +#endif // ANDROID using namespace std; using namespace WTF; @@ -72,6 +81,12 @@ public: unsigned int pos; }; +// Used to track a list of chained bidi runs. +static BidiRun* sFirstBidiRun; +static BidiRun* sLastBidiRun; +static BidiRun* sLogicallyLastBidiRun; +static int sBidiRunCount; + // Midpoint globals. The goal is not to do any allocation when dealing with // these midpoints, so we just keep an array around and never clear it. We track // the number of items and position using the two other variables. @@ -82,13 +97,28 @@ static bool betweenMidpoints; static bool isLineEmpty = true; static bool previousLineBrokeCleanly = true; +static int numSpaces; + +static int getBPMWidth(int childValue, Length cssUnit) +{ + if (!cssUnit.isIntrinsicOrAuto()) + return (cssUnit.isFixed() ? cssUnit.value() : childValue); + return 0; +} static int getBorderPaddingMargin(RenderObject* child, bool endOfInline) { - bool leftSide = (child->style()->direction() == LTR) ? !endOfInline : endOfInline; - if (leftSide) - return child->marginLeft() + child->paddingLeft() + child->borderLeft(); - return child->marginRight() + child->paddingRight() + child->borderRight(); + RenderStyle* cstyle = child->style(); + int result = 0; + bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline; + result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()), + (leftSide ? cstyle->marginLeft() : + cstyle->marginRight())); + result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()), + (leftSide ? cstyle->paddingLeft() : + cstyle->paddingRight())); + result += leftSide ? child->borderLeft() : child->borderRight(); + return result; } static int inlineWidth(RenderObject* child, bool start = true, bool end = true) @@ -124,19 +154,18 @@ static BidiRunCounter bidiRunCounter; static bool inBidiRunDestroy; #endif -void BidiRun::destroy() +void BidiRun::destroy(RenderArena* renderArena) { #ifndef NDEBUG inBidiRunDestroy = true; #endif - RenderArena* renderArena = m_object->renderArena(); delete this; #ifndef NDEBUG inBidiRunDestroy = false; #endif // Recover the size left there for us by operator delete and free the memory. - renderArena->free(*reinterpret_cast<size_t*>(this), this); + renderArena->free(*(size_t *)this, this); } void* BidiRun::operator new(size_t sz, RenderArena* renderArena) throw() @@ -158,6 +187,25 @@ void BidiRun::operator delete(void* ptr, size_t sz) *(size_t*)ptr = sz; } +template <> +void BidiState::deleteRuns() +{ + emptyRun = true; + if (!m_firstRun) + return; + + BidiRun* curr = m_firstRun; + while (curr) { + BidiRun* s = curr->next(); + curr->destroy(curr->obj->renderArena()); + curr = s; + } + + m_firstRun = 0; + m_lastRun = 0; + m_runCount = 0; +} + // --------------------------------------------------------------------- inline bool operator==(const BidiIterator& it1, const BidiIterator& it2) @@ -234,7 +282,7 @@ static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current, if (!next) break; - if (next->isText() || next->isFloating() || next->isReplaced() || next->isPositioned() + if (next->isText() || next->isBR() || next->isFloating() || next->isReplaced() || next->isPositioned() || ((!skipInlines || !next->firstChild()) // Always return EMPTY inlines. && next->isInlineFlow())) break; @@ -266,7 +314,7 @@ static RenderObject* bidiFirst(RenderBlock* block, BidiState& bidi, bool skipInl return o; // Never skip empty inlines. } - if (o && !o->isText() && !o->isReplaced() && !o->isFloating() && !o->isPositioned()) + if (o && !o->isText() && !o->isBR() && !o->isReplaced() && !o->isFloating() && !o->isPositioned()) o = bidiNext(block, o, bidi, skipInlines); return o; } @@ -320,12 +368,37 @@ ALWAYS_INLINE Direction BidiIterator::direction() const // ------------------------------------------------------------------------------------------------- +template <> +inline void BidiState::addRun(BidiRun* bidiRun) +{ + if (!m_firstRun) + m_firstRun = bidiRun; + else + m_lastRun->m_next = bidiRun; + m_lastRun = bidiRun; + m_runCount++; + + sLogicallyLastBidiRun = bidiRun; + + // Compute the number of spaces in this run, + if (bidiRun->obj && bidiRun->obj->isText()) { + RenderText* text = static_cast<RenderText*>(bidiRun->obj); + if (text->characters()) { + for (int i = bidiRun->m_start; i < bidiRun->m_stop; i++) { + UChar c = text->characters()[i]; + if (c == ' ' || c == '\n' || c == '\t') + numSpaces++; + } + } + } +} + static void chopMidpointsAt(RenderObject* obj, unsigned pos) { if (!sNumMidpoints) return; BidiIterator* midpoints = smidpoints->data(); - for (int i = sNumMidpoints - 1; i >= 0; i--) { + for (unsigned i = 0; i < sNumMidpoints; i++) { const BidiIterator& point = midpoints[i]; if (point.obj == obj && point.pos == pos) { sNumMidpoints = i; @@ -487,7 +560,7 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj) parentBox->setFirstLineStyleBit(m_firstLine); constructedNewBox = true; } - + if (!result) result = parentBox; @@ -496,12 +569,12 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj) // inline. if (childBox) parentBox->addToLine(childBox); - + if (!constructedNewBox || obj == this) break; - + childBox = parentBox; - + // If we've exceeded our line depth, then jump straight to the root and skip all the remaining // intermediate inline flows. obj = (++lineDepth >= cMaxLineDepth) ? this : obj->parent(); @@ -511,34 +584,34 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj) return result; } -RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool lastLine, RenderObject* endObject) +RootInlineBox* RenderBlock::constructLine(const BidiIterator& start, const BidiIterator& end) { - ASSERT(firstRun); + if (!sFirstBidiRun) + return 0; // We had no runs. Don't make a root inline box at all. The line is empty. InlineFlowBox* parentBox = 0; - for (BidiRun* r = firstRun; r; r = r->next()) { + for (BidiRun* r = sFirstBidiRun; r; r = r->next()) { // Create a box for our object. - bool isOnlyRun = (runCount == 1); - if (runCount == 2 && !r->m_object->isListMarker()) - isOnlyRun = ((style()->direction() == RTL) ? lastRun : firstRun)->m_object->isListMarker(); - r->m_box = r->m_object->createInlineBox(r->m_object->isPositioned(), false, isOnlyRun); - - if (r->m_box) { + bool isOnlyRun = (sBidiRunCount == 1); + if (sBidiRunCount == 2 && !r->obj->isListMarker()) + isOnlyRun = ((style()->direction() == RTL) ? sLastBidiRun : sFirstBidiRun)->obj->isListMarker(); + r->box = r->obj->createInlineBox(r->obj->isPositioned(), false, isOnlyRun); + if (r->box) { // If we have no parent box yet, or if the run is not simply a sibling, // then we need to construct inline boxes as necessary to properly enclose the // run's inline box. - if (!parentBox || parentBox->object() != r->m_object->parent()) + if (!parentBox || parentBox->object() != r->obj->parent()) // Create new inline boxes all the way back to the appropriate insertion point. - parentBox = createLineBoxes(r->m_object->parent()); + parentBox = createLineBoxes(r->obj->parent()); // Append the inline box to this line. - parentBox->addToLine(r->m_box); + parentBox->addToLine(r->box); - if (r->m_box->isInlineTextBox()) { - InlineTextBox* text = static_cast<InlineTextBox*>(r->m_box); + if (r->box->isInlineTextBox()) { + InlineTextBox *text = static_cast<InlineTextBox*>(r->box); text->setStart(r->m_start); text->setLen(r->m_stop - r->m_start); - bool visuallyOrdered = r->m_object->style()->visuallyOrdered(); + bool visuallyOrdered = r->obj->style()->visuallyOrdered(); text->m_reversed = r->reversed(visuallyOrdered); text->m_dirOverride = r->dirOverride(visuallyOrdered); } @@ -553,6 +626,10 @@ RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun, // paint borders/margins/padding. This knowledge will ultimately be used when // we determine the horizontal positions and widths of all the inline boxes on // the line. + RenderObject* endObject = 0; + bool lastLine = !end.obj; + if (end.obj && end.pos == 0) + endObject = end.obj; lastLineBox()->determineSpacingForFlowBoxes(lastLine, endObject); // Now mark the line boxes as being constructed. @@ -562,53 +639,44 @@ RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun, return lastRootBox(); } -void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, BidiRun* logicallyLastRun, bool reachedEnd) +void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool reachedEnd) { // First determine our total width. int availableWidth = lineWidth(m_height); int totWidth = lineBox->getFlowSpacingWidth(); + BidiRun* r = 0; bool needsWordSpacing = false; - unsigned numSpaces = 0; - ETextAlign textAlign = style()->textAlign(); - - for (BidiRun* r = firstRun; r; r = r->next()) { - if (!r->m_box || r->m_object->isPositioned() || r->m_box->isLineBreak()) + for (r = sFirstBidiRun; r; r = r->next()) { + if (!r->box || r->obj->isPositioned() || r->box->isLineBreak()) continue; // Positioned objects are only participating to figure out their // correct static x position. They have no effect on the width. // Similarly, line break boxes have no effect on the width. - if (r->m_object->isText()) { - RenderText* rt = static_cast<RenderText*>(r->m_object); - - if (textAlign == JUSTIFY) { - const UChar* characters = rt->characters(); - for (int i = r->m_start; i < r->m_stop; i++) { - UChar c = characters[i]; - if (c == ' ' || c == '\n' || c == '\t') - numSpaces++; - } - } - - if (int length = rt->textLength()) { - if (!r->m_compact && !r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characters()[r->m_start])) + if (r->obj->isText()) { + RenderText* rt = static_cast<RenderText*>(r->obj); + int textWidth = rt->width(r->m_start, r->m_stop - r->m_start, totWidth, m_firstLine); + int rtLength = rt->textLength(); + if (rtLength != 0) { + if (!r->compact && !r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characters()[r->m_start])) totWidth += rt->style(m_firstLine)->font().wordSpacing(); - needsWordSpacing = !isSpaceOrNewline(rt->characters()[r->m_stop - 1]) && r->m_stop == length; + needsWordSpacing = !isSpaceOrNewline(rt->characters()[r->m_stop - 1]) && r->m_stop == rtLength; } - r->m_box->setWidth(rt->width(r->m_start, r->m_stop - r->m_start, totWidth, m_firstLine)); - } else if (!r->m_object->isInlineFlow()) { - r->m_object->calcWidth(); - r->m_box->setWidth(r->m_object->width()); - if (!r->m_compact) - totWidth += r->m_object->marginLeft() + r->m_object->marginRight(); + r->box->setWidth(textWidth); + } else if (!r->obj->isInlineFlow()) { + r->obj->calcWidth(); + r->box->setWidth(r->obj->width()); + if (!r->compact) + totWidth += r->obj->marginLeft() + r->obj->marginRight(); } // Compacts don't contribute to the width of the line, since they are placed in the margin. - if (!r->m_compact) - totWidth += r->m_box->width(); + if (!r->compact) + totWidth += r->box->width(); } - if (totWidth > availableWidth && logicallyLastRun->m_object->style(m_firstLine)->autoWrap() - && logicallyLastRun->m_object->style(m_firstLine)->breakOnlyAfterWhiteSpace() && !logicallyLastRun->m_compact) { - logicallyLastRun->m_box->setWidth(logicallyLastRun->m_box->width() - totWidth + availableWidth); + if (totWidth > availableWidth && sLogicallyLastBidiRun->obj->style(m_firstLine)->autoWrap() && + sLogicallyLastBidiRun->obj->style(m_firstLine)->breakOnlyAfterWhiteSpace() && + !sLogicallyLastBidiRun->compact) { + sLogicallyLastBidiRun->box->setWidth(sLogicallyLastBidiRun->box->width() - totWidth + availableWidth); totWidth = availableWidth; } @@ -617,16 +685,17 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi // objects horizontally. The total width of the line can be increased if we end up // justifying text. int x = leftOffset(m_height); - switch(textAlign) { + switch(style()->textAlign()) { case LEFT: case WEBKIT_LEFT: // The direction of the block should determine what happens with wide lines. In // particular with RTL blocks, wide lines should still spill out to the left. if (style()->direction() == RTL && totWidth > availableWidth) x -= (totWidth - availableWidth); + numSpaces = 0; break; case JUSTIFY: - if (numSpaces && !reachedEnd && !lineBox->endsWithBreak()) + if (numSpaces != 0 && !reachedEnd && !lineBox->endsWithBreak()) break; // fall through case TAAUTO: @@ -641,27 +710,26 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi // side of the block. if (style()->direction() == RTL || totWidth < availableWidth) x += availableWidth - totWidth; + numSpaces = 0; break; case CENTER: case WEBKIT_CENTER: - if (style()->direction() == LTR) - x += max((availableWidth - totWidth) / 2, 0); - else - x += totWidth > availableWidth ? (availableWidth - totWidth) : (availableWidth - totWidth) / 2; + int xd = (availableWidth - totWidth)/2; + x += xd > 0 ? xd : 0; + numSpaces = 0; break; } - if (numSpaces) { - for (BidiRun* r = firstRun; r; r = r->next()) { - if (!r->m_box) - continue; + if (numSpaces > 0) { + for (r = sFirstBidiRun; r; r = r->next()) { + if (!r->box) continue; int spaceAdd = 0; - if (r->m_object->isText() && !r->m_compact) { - unsigned spaces = 0; - const UChar* characters = static_cast<RenderText*>(r->m_object)->characters(); + if (numSpaces > 0 && r->obj->isText() && !r->compact) { + // get the number of spaces in the run + int spaces = 0; for (int i = r->m_start; i < r->m_stop; i++) { - UChar c = characters[i]; + UChar c = static_cast<RenderText*>(r->obj)->characters()[i]; if (c == ' ' || c == '\n' || c == '\t') spaces++; } @@ -669,18 +737,16 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi ASSERT(spaces <= numSpaces); // Only justify text if whitespace is collapsed. - if (r->m_object->style()->collapseWhiteSpace()) { - spaceAdd = (availableWidth - totWidth) * spaces / numSpaces; - static_cast<InlineTextBox*>(r->m_box)->setSpaceAdd(spaceAdd); + if (r->obj->style()->collapseWhiteSpace()) { + spaceAdd = (availableWidth - totWidth)*spaces/numSpaces; + static_cast<InlineTextBox*>(r->box)->setSpaceAdd(spaceAdd); totWidth += spaceAdd; } numSpaces -= spaces; - if (!numSpaces) - break; } } } - + // The widths of all runs are now known. We can now place every inline box (and // compute accurate widths for the inline flow boxes). int leftPosition = x; @@ -690,7 +756,7 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi lineBox->setHorizontalOverflowPositions(leftPosition, rightPosition); } -void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun) +void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox) { lineBox->verticallyAlignBoxes(m_height); lineBox->setBlockHeight(m_height); @@ -699,20 +765,20 @@ void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRu int bottomOfLine = lineBox->bottomOverflow(); if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight) m_overflowHeight = bottomOfLine; - + // Now make sure we place replaced render objects correctly. - for (BidiRun* r = firstRun; r; r = r->next()) { - if (!r->m_box) + for (BidiRun* r = sFirstBidiRun; r; r = r->next()) { + if (!r->box) continue; // Skip runs with no line boxes. // Align positioned boxes with the top of the line box. This is // a reasonable approximation of an appropriate y position. - if (r->m_object->isPositioned()) - r->m_box->setYPos(m_height); + if (r->obj->isPositioned()) + r->box->setYPos(m_height); // Position is used to properly position both replaced elements and // to update the static normal flow x/y of positioned elements. - r->m_object->position(r->m_box); + r->obj->position(r->box); } } @@ -725,7 +791,13 @@ void RenderBlock::bidiReorderLine(const BidiIterator& start, const BidiIterator& return; } + numSpaces = 0; + bidi.createBidiRunsForLine(start, end, style()->visuallyOrdered(), previousLineBrokeCleanly); + + sFirstBidiRun = bidi.firstRun(); + sLastBidiRun = bidi.lastRun(); + sBidiRunCount = bidi.runCount(); } static void buildCompactRuns(RenderObject* compactObj, BidiState& bidi) @@ -744,14 +816,14 @@ static void buildCompactRuns(RenderObject* compactObj, BidiState& bidi) betweenMidpoints = false; isLineEmpty = true; previousLineBrokeCleanly = true; - + end = compactBlock->findNextLineBreak(start, bidi); if (!isLineEmpty) compactBlock->bidiReorderLine(start, end, bidi); for (BidiRun* run = bidi.firstRun(); run; run = run->next()) - run->m_compact = true; - + run->compact = true; + sNumMidpoints = 0; sCurrMidpoint = 0; betweenMidpoints = false; @@ -769,31 +841,47 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i m_height = borderTop() + paddingTop(); int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight(); - + // Figure out if we should clear out our line boxes. // FIXME: Handle resize eventually! // FIXME: Do something better when floats are present. bool fullLayout = !firstLineBox() || !firstChild() || selfNeedsLayout() || relayoutChildren || containsFloats(); if (fullLayout) deleteLineBoxes(); - + // Text truncation only kicks in if your overflow isn't visible and your text-overflow-mode isn't // clip. // FIXME: CSS3 says that descendants that are clipped must also know how to truncate. This is insanely // difficult to figure out (especially in the middle of doing layout), and is really an esoteric pile of nonsense // anyway, so we won't worry about following the draft here. bool hasTextOverflow = style()->textOverflow() && hasOverflowClip(); - + // Walk all the lines and delete our ellipsis line boxes if they exist. if (hasTextOverflow) deleteEllipsisLineBoxes(); if (firstChild()) { +#ifdef ANDROID_LAYOUT + // if we are in fitColumnToScreen mode and viewport width is not device-width, + // and text align is auto, or justify or left in LTR, or right in RTL, we + // will wrap text around screen width so that it doesn't need to scroll + // horizontally when reading a paragraph. + const Settings* settings = document()->settings(); + bool doTextWrap = settings && settings->viewportWidth() != 0 && + settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen; + if (doTextWrap) { + int ta = style()->textAlign(); + int dir = style()->direction(); + doTextWrap = (ta == TAAUTO) || (ta == JUSTIFY) || + ((ta == LEFT || ta == WEBKIT_LEFT) && (dir == LTR)) || + ((ta == RIGHT || ta == WEBKIT_RIGHT) && (dir == RTL)); + } + bool hasTextToWrap = false; +#endif // layout replaced elements bool endOfInline = false; RenderObject* o = bidiFirst(this, bidi, false); bool hasFloat = false; - int containerWidth = max(0, containingBlockWidth()); while (o) { o->invalidateVerticalPosition(); if (o->isReplaced() || o->isFloating() || o->isPositioned()) { @@ -807,6 +895,11 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i if (o->isPositioned()) o->containingBlock()->insertPositionedObject(o); else { +#ifdef ANDROID_LAYOUT + // ignore text wrap for textField or menuList + if (doTextWrap && (o->isTextField() || o->isMenuList())) + doTextWrap = false; +#endif if (o->isFloating()) hasFloat = true; else if (fullLayout || o->needsLayout()) // Replaced elements @@ -817,18 +910,64 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i else if (o->isText() || (o->isInlineFlow() && !endOfInline)) { if (fullLayout || o->selfNeedsLayout()) o->dirtyLineBoxes(fullLayout); - - // Calculate margins of inline flows so that they can be used later by line layout. - if (o->isInlineFlow()) - static_cast<RenderFlow*>(o)->calcMargins(containerWidth); o->setNeedsLayout(false); +#ifdef ANDROID_LAYOUT + if (doTextWrap && !hasTextToWrap && o->isText()) { + Node* node = o->element(); + // as it is very common for sites to use a serial of <a> as + // tabs, we don't force text to wrap if all the text are + // short and within an <a> tag, or only separated by short + // word like "|" or ";". + if (node && node->isTextNode() && + !static_cast<Text*>(node)->containsOnlyWhitespace()) { + int length = static_cast<Text*>(node)->length(); + if (length > 20 || (length >3 && + !node->parent()->hasTagName(HTMLNames::aTag))) + hasTextToWrap = true; + } + } +#endif } o = bidiNext(this, o, bidi, false, &endOfInline); } +#ifdef ANDROID_LAYOUT + // try to make sure that inline text will not span wider than the + // screen size unless the container has a fixed height, + if (doTextWrap && hasTextToWrap) { + // check all the nested containing blocks, unless it is table or + // table-cell, to make sure there is no fixed height as it implies + // fixed layout. If we constrain the text to fit screen, we may + // cause text overlap with the block after. + bool isConstrained = false; + RenderObject* obj = this; + while (obj) { + if (obj->style()->height().isFixed() && (!obj->isTable() && !obj->isTableCell())) { + isConstrained = true; + break; + } + if (obj->isFloating() || obj->isPositioned()) { + // floating and absolute or fixed positioning are done out + // of normal flow. Don't need to worry about height any more. + break; + } + obj = obj->container(); + } + if (!isConstrained) { + int maxWidth = view()->frameView()->getWebCoreViewBridge()->screenWidth() + - 2 * ANDROID_FCTS_MARGIN_PADDING; + if (maxWidth > 0) { + m_width = min(m_width, maxWidth); + m_minPrefWidth = min(m_minPrefWidth, maxWidth); + m_maxPrefWidth = min(m_maxPrefWidth, maxWidth); + m_overflowWidth = min(m_overflowWidth, maxWidth); + } + } + } +#endif if (hasFloat) fullLayout = true; // FIXME: Will need to find a way to optimize floats some day. - + if (fullLayout && !selfNeedsLayout()) { setNeedsLayout(true, false); // Mark ourselves as needing a full layout. This way we'll repaint like // we're supposed to. @@ -843,7 +982,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i } } - BidiContext* startEmbed; + BidiContext *startEmbed; if (style()->direction() == LTR #if ENABLE(SVG) || (style()->unicodeBidi() == UBNormal && isSVGText()) @@ -858,17 +997,17 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i bidi.setLastDir(startEmbed->dir()); bidi.setEorDir(startEmbed->dir()); bidi.setContext(startEmbed); - + if (!smidpoints) smidpoints = new Vector<BidiIterator>(); - + sNumMidpoints = 0; sCurrMidpoint = 0; - + // We want to skip ahead to the first dirty line BidiIterator start; RootInlineBox* startLine = determineStartPosition(fullLayout, start, bidi); - + // We also find the first clean line and extract these lines. We will add them back // if we determine that we're able to synchronize after handling all our dirty lines. BidiIterator cleanLineStart; @@ -890,8 +1029,9 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i box->deleteLine(arena); box = next; } + startLine = 0; } - + BidiIterator end = start; bool endLineMatched = false; @@ -920,16 +1060,16 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i // inline flow boxes. RootInlineBox* lineBox = 0; - if (bidi.runCount()) { - lineBox = constructLine(bidi.runCount(), bidi.firstRun(), bidi.lastRun(), !end.obj, end.obj && !end.pos ? end.obj : 0); + if (sBidiRunCount) { + lineBox = constructLine(start, end); if (lineBox) { lineBox->setEndsWithBreak(previousLineBrokeCleanly); // Now we position all of our text runs horizontally. - computeHorizontalPositionsForLine(lineBox, bidi.firstRun(), bidi.logicallyLastRun(), end.atEnd()); - + computeHorizontalPositionsForLine(lineBox, end.atEnd()); + // Now position our text runs vertically. - computeVerticalPositionsForLine(lineBox, bidi.firstRun()); + computeVerticalPositionsForLine(lineBox); #if ENABLE(SVG) // Special SVG text layout code @@ -945,7 +1085,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i } bidi.deleteRuns(); - + if (end == start) { bidi.setAdjustEmbedding(true); end.increment(bidi); @@ -959,27 +1099,27 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i repaintBottom = max(repaintBottom, lineBox->bottomOverflow()); } } - + m_firstLine = false; newLine(); } - + sNumMidpoints = 0; sCurrMidpoint = 0; } - + if (endLine) { if (endLineMatched) { // Attach all the remaining lines, and then adjust their y-positions as needed. for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) line->attachLine(); - + // Now apply the offset to each line if needed. int delta = m_height - endLineYPos; if (delta) { for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) { - repaintTop = min(repaintTop, line->topOverflow() + min(delta, 0)); - repaintBottom = max(repaintBottom, line->bottomOverflow() + max(delta, 0)); + repaintTop = min(repaintTop, line->topOverflow() + (delta < 0 ? delta : 0)); + repaintBottom = max(repaintBottom, line->bottomOverflow() + (delta > 0 ? delta : 0)); line->adjustPosition(0, delta); } } @@ -1006,13 +1146,13 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i // This has to be done before adding in the bottom border/padding, or the float will // include the padding incorrectly. -dwh positionNewFloats(); - + // Now add in the bottom border/padding. m_height += toAdd; // Always make sure this is at least our height. m_overflowHeight = max(m_height, m_overflowHeight); - + // See if any lines spill out of the block. If so, we need to update our overflow width. checkLinesForOverflow(); @@ -1031,7 +1171,7 @@ RootInlineBox* RenderBlock::determineStartPosition(bool fullLayout, BidiIterator RootInlineBox* last = 0; RenderObject* startObj = 0; int pos = 0; - + if (fullLayout) { // Nuke all our lines. if (firstRootBox()) { @@ -1061,11 +1201,11 @@ RootInlineBox* RenderBlock::determineStartPosition(bool fullLayout, BidiIterator if (lastRootBox() && !lastRootBox()->endsWithBreak()) curr = lastRootBox(); } - + // If we have no dirty lines, then last is just the last root box. last = curr ? curr->prevRootBox() : lastRootBox(); } - + m_firstLine = !last; previousLineBrokeCleanly = !last || last->endsWithBreak(); if (last) { @@ -1078,9 +1218,9 @@ RootInlineBox* RenderBlock::determineStartPosition(bool fullLayout, BidiIterator startObj = bidiFirst(this, bidi, 0); bidi.setAdjustEmbedding(false); } - + start = BidiIterator(this, startObj, pos); - + return curr; } @@ -1097,19 +1237,19 @@ RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, BidiI last = curr; } } - + if (!last) return 0; - + RootInlineBox* prev = last->prevRootBox(); cleanLineStart = BidiIterator(this, prev->lineBreakObj(), prev->lineBreakPos()); cleanLineBidiStatus = prev->lineBreakBidiStatus(); yPos = prev->blockHeight(); - + for (RootInlineBox* line = last; line; line = line->nextRootBox()) line->extractLine(); // Disconnect all line boxes from their render objects while preserving // their connections to one another. - + return last; } @@ -1119,46 +1259,46 @@ bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiStatus& st { if (start == endLineStart) return status == endLineStatus; + else { + // The first clean line doesn't match, but we can check a handful of following lines to try + // to match back up. + static int numLines = 8; // The # of lines we're willing to match against. + RootInlineBox* line = endLine; + for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) { + if (line->lineBreakObj() == start.obj && line->lineBreakPos() == start.pos) { + // We have a match. + if (line->lineBreakBidiStatus() != status) + return false; // ...but the bidi state doesn't match. + RootInlineBox* result = line->nextRootBox(); + + // Set our yPos to be the block height of endLine. + if (result) + endYPos = line->blockHeight(); + + // Now delete the lines that we failed to sync. + RootInlineBox* boxToDelete = endLine; + RenderArena* arena = renderArena(); + while (boxToDelete && boxToDelete != result) { + repaintTop = min(repaintTop, boxToDelete->topOverflow()); + repaintBottom = max(repaintBottom, boxToDelete->bottomOverflow()); + RootInlineBox* next = boxToDelete->nextRootBox(); + boxToDelete->deleteLine(arena); + boxToDelete = next; + } - // The first clean line doesn't match, but we can check a handful of following lines to try - // to match back up. - static int numLines = 8; // The # of lines we're willing to match against. - RootInlineBox* line = endLine; - for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) { - if (line->lineBreakObj() == start.obj && line->lineBreakPos() == start.pos) { - // We have a match. - if (line->lineBreakBidiStatus() != status) - return false; // ...but the bidi state doesn't match. - RootInlineBox* result = line->nextRootBox(); - - // Set our yPos to be the block height of endLine. - if (result) - endYPos = line->blockHeight(); - - // Now delete the lines that we failed to sync. - RootInlineBox* boxToDelete = endLine; - RenderArena* arena = renderArena(); - while (boxToDelete && boxToDelete != result) { - repaintTop = min(repaintTop, boxToDelete->topOverflow()); - repaintBottom = max(repaintBottom, boxToDelete->bottomOverflow()); - RootInlineBox* next = boxToDelete->nextRootBox(); - boxToDelete->deleteLine(arena); - boxToDelete = next; + endLine = result; + return result; } - - endLine = result; - return result; } } - return false; } -static inline bool skipNonBreakingSpace(BidiIterator& it) +static inline bool skipNonBreakingSpace(BidiIterator &it) { if (it.obj->style()->nbspMode() != SPACE || it.current() != noBreakSpace) return false; - + // FIXME: This is bad. It makes nbsp inconsistent with space and won't work correctly // with m_minWidth/m_maxWidth. // Do not skip a non-breaking space if it is the first character @@ -1166,7 +1306,7 @@ static inline bool skipNonBreakingSpace(BidiIterator& it) // |true|). if (isLineEmpty && previousLineBrokeCleanly) return false; - + return true; } @@ -1188,9 +1328,19 @@ static inline bool shouldPreserveNewline(RenderObject* object) static bool inlineFlowRequiresLineBox(RenderObject* flow) { // FIXME: Right now, we only allow line boxes for inlines that are truly empty. - // We need to fix this, though, because at the very least, inlines containing only - // ignorable whitespace should should also have line boxes. - return flow->isInlineFlow() && !flow->firstChild() && flow->hasHorizontalBordersPaddingOrMargin(); + // We need to fix this, though, because at the very least, inlines with only text + // children that is all whitespace should should also have line boxes. + if (!flow->isInlineFlow() || flow->firstChild()) + return false; + + bool hasPaddingOrMargin = !(flow->paddingLeft() == 0 && flow->paddingRight() == 0 + && flow->paddingTop() == 0 && flow->paddingBottom() == 0 + && flow->marginLeft() == 0 && flow->marginRight() == 0 + && flow->marginTop() == 0 && flow->marginBottom() == 0); + if (flow->hasBoxDecorations() || hasPaddingOrMargin) + return true; + + return false; } static inline bool requiresLineBox(BidiIterator& it) @@ -1220,58 +1370,70 @@ bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj) return !it.atEnd(); } -int RenderBlock::skipWhitespace(BidiIterator& it, BidiState& bidi) +int RenderBlock::skipWhitespace(BidiIterator &it, BidiState &bidi) { // FIXME: The entire concept of the skipWhitespace function is flawed, since we really need to be building // line boxes even for containers that may ultimately collapse away. Otherwise we'll never get positioned // elements quite right. In other words, we need to build this function's work into the normal line // object iteration process. int w = lineWidth(m_height); + bidi.setAdjustEmbedding(true); while (!it.atEnd() && !requiresLineBox(it)) { - RenderObject* o = it.obj; - if (o->isFloating()) { - insertFloatingObject(o); - positionNewFloats(); - w = lineWidth(m_height); - } else if (o->isPositioned()) { - // FIXME: The math here is actually not really right. It's a best-guess approximation that - // will work for the common cases - RenderObject* c = o->container(); - if (c->isInlineFlow()) { - // A relative positioned inline encloses us. In this case, we also have to determine our - // position as though we were an inline. Set |staticX| and |staticY| on the relative positioned - // inline so that we can obtain the value later. - c->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : rightOffset(m_height)); - c->setStaticY(m_height); + if (it.obj->isFloatingOrPositioned()) { + RenderObject *o = it.obj; + // add to special objects... + if (o->isFloating()) { + insertFloatingObject(o); + positionNewFloats(); + w = lineWidth(m_height); } - - if (o->hasStaticX()) { - if (o->style()->isOriginalDisplayInlineType()) - o->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : width() - rightOffset(m_height)); - else - o->setStaticX(style()->direction() == LTR ? borderLeft() + paddingLeft() : borderRight() + paddingRight()); + else if (o->isPositioned()) { + // FIXME: The math here is actually not really right. It's a best-guess approximation that + // will work for the common cases + RenderObject* c = o->container(); + if (c->isInlineFlow()) { + // A relative positioned inline encloses us. In this case, we also have to determine our + // position as though we were an inline. Set |staticX| and |staticY| on the relative positioned + // inline so that we can obtain the value later. + c->setStaticX(style()->direction() == LTR ? + leftOffset(m_height) : rightOffset(m_height)); + c->setStaticY(m_height); + } + + if (o->hasStaticX()) { + bool wasInline = o->style()->isOriginalDisplayInlineType(); + if (wasInline) + o->setStaticX(style()->direction() == LTR ? + leftOffset(m_height) : + width() - rightOffset(m_height)); + else + o->setStaticX(style()->direction() == LTR ? + borderLeft() + paddingLeft() : + borderRight() + paddingRight()); + } + if (o->hasStaticY()) + o->setStaticY(m_height); } - - if (o->hasStaticY()) - o->setStaticY(m_height); } it.increment(bidi); } + bidi.setAdjustEmbedding(false); return w; } // This is currently just used for list markers and inline flows that have line boxes. Neither should // have an effect on whitespace at the start of the line. -static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o, BidiState& bidi) +static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o, BidiState &bidi) { RenderObject* next = bidiNext(block, o, bidi); if (next && !next->isBR() && next->isText() && static_cast<RenderText*>(next)->textLength() > 0) { RenderText* nextText = static_cast<RenderText*>(next); UChar nextChar = nextText->characters()[0]; if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) { - addMidpoint(BidiIterator(0, o, 0)); + BidiIterator endMid(0, o, 0); + addMidpoint(endMid); return true; } } @@ -1279,37 +1441,10 @@ static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObjec return false; } -void RenderBlock::fitBelowFloats(int widthToFit, int& availableWidth) -{ - ASSERT(widthToFit > availableWidth); - - int floatBottom; - int lastFloatBottom = m_height; - int newLineWidth = availableWidth; - while (true) { - floatBottom = nextFloatBottomBelow(lastFloatBottom); - if (!floatBottom) - break; - - newLineWidth = lineWidth(floatBottom); - lastFloatBottom = floatBottom; - if (newLineWidth >= widthToFit) - break; - } - - if (newLineWidth > availableWidth) { - m_height = lastFloatBottom; - availableWidth = newLineWidth; - } -} - BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi) { - bool appliedStartWidth = start.pos > 0; - - bidi.setAdjustEmbedding(true); + // eliminate spaces at beginning of line int width = skipWhitespace(start, bidi); - bidi.setAdjustEmbedding(false); int w = 0; int tmpW = 0; @@ -1340,10 +1475,9 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi previousLineBrokeCleanly = false; bool autoWrapWasEverTrueOnLine = false; - bool floatsFitOnLine = true; // Firefox and Opera will allow a table cell to grow to fit an image inside it under - // very specific circumstances (in order to match common WinIE renderings). + // very specific cirucumstances (in order to match common WinIE renderings). // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.) bool allowImagesToBreak = !style()->htmlHacks() || !isTableCell() || !style()->width().isIntrinsicOrAuto(); @@ -1397,11 +1531,10 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi // 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 (floatsFitOnLine && o->width() + o->marginLeft() + o->marginRight() + w + tmpW <= width) { + if (o->width() + o->marginLeft() + o->marginRight() + w + tmpW <= width) { positionNewFloats(); width = lineWidth(m_height); - } else - floatsFitOnLine = false; + } } else if (o->isPositioned()) { // If our original display wasn't an inline type, then we can // go ahead and determine our static x position now. @@ -1449,7 +1582,6 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi // If this object is at the start of the line, we need to behave like list markers and // start ignoring spaces. if (inlineFlowRequiresLineBox(o)) { - isLineEmpty = false; if (ignoringSpaces) { trailingSpaceObject = 0; addMidpoint(BidiIterator(0, o, 0)); // Stop ignoring spaces. @@ -1464,6 +1596,12 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi } } + if (static_cast<RenderFlow*>(o)->isWordBreak()) { + w += tmpW; + tmpW = 0; + lBreak.obj = o; + lBreak.pos = 0; + } tmpW += o->marginLeft() + o->borderLeft() + o->paddingLeft() + o->marginRight() + o->borderRight() + o->paddingRight(); } else if (o->isReplaced()) { @@ -1475,9 +1613,10 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi lBreak.pos = 0; } - if (ignoringSpaces) - addMidpoint(BidiIterator(0, o, 0)); - + if (ignoringSpaces) { + BidiIterator startMid( 0, o, 0 ); + addMidpoint(startMid); + } isLineEmpty = false; ignoringSpaces = false; currentCharacterIsSpace = false; @@ -1497,11 +1636,7 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi } else tmpW += o->width() + o->marginLeft() + o->marginRight() + inlineWidth(o); } else if (o->isText()) { - if (!pos) - appliedStartWidth = false; - RenderText* t = static_cast<RenderText*>(o); - int strlen = t->textLength(); int len = strlen - pos; const UChar* str = t->characters(); @@ -1512,6 +1647,8 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi int wordSpacing = o->style()->wordSpacing(); int lastSpaceWordSpacing = 0; + bool appliedStartWidth = pos > 0; // If the span originated on a previous line, + // then assume the start width has been applied. int wrapW = tmpW + inlineWidth(o, !appliedStartWidth, true); int charWidth = 0; int nextBreakable = -1; @@ -1522,14 +1659,6 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi bool midWordBreak = false; bool breakAll = o->style()->wordBreak() == BreakAllWordBreak && autoWrap; - if (t->isWordBreak()) { - w += tmpW; - tmpW = 0; - lBreak.obj = o; - lBreak.pos = 0; - ASSERT(!len); - } - while (len) { bool previousCharacterIsSpace = currentCharacterIsSpace; bool previousCharacterIsWS = currentCharacterIsWS; @@ -1562,7 +1691,8 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi if (autoWrap) tmpW += t->width(pos, 1, f, w + tmpW); - addMidpoint(BidiIterator(0, o, pos + 1)); + BidiIterator startMid(0, o, pos + 1); + addMidpoint(startMid); } pos++; @@ -1593,7 +1723,8 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi ignoringSpaces = false; lastSpaceWordSpacing = 0; lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces. - addMidpoint(BidiIterator(0, o, pos)); + BidiIterator startMid(0, o, pos); + addMidpoint(startMid); stoppedIgnoringSpaces = true; } else { // Just keep ignoring these spaces. @@ -1612,9 +1743,24 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi applyWordSpacing = wordSpacing && currentCharacterIsSpace && !previousCharacterIsSpace; - if (!w && autoWrap && tmpW > width) - fitBelowFloats(tmpW, width); - + if (autoWrap && w + tmpW > width && !w) { + int fb = nearestFloatBottom(m_height); + int newLineWidth = lineWidth(fb); + // See if |tmpW| will fit on the new line. As long as it does not, + // keep adjusting our float bottom until we find some room. + int lastFloatBottom = m_height; + while (lastFloatBottom < fb && tmpW > newLineWidth) { + lastFloatBottom = fb; + fb = nearestFloatBottom(fb); + newLineWidth = lineWidth(fb); + } + + if (!w && m_height < fb && width < newLineWidth) { + m_height = fb; + width = newLineWidth; + } + } + if (autoWrap || breakWords) { // If we break only after white-space, consider the current character // as candidate width for this line. @@ -1633,17 +1779,19 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi if (pos > 0) { // Separate the trailing space into its own box, which we will // resize to fit on the line in computeHorizontalPositionsForLine(). - addMidpoint(BidiIterator(0, o, pos - 1)); // Stop + BidiIterator midpoint(0, o, pos); + addMidpoint(BidiIterator(0, o, pos-1)); // Stop addMidpoint(BidiIterator(0, o, pos)); // Start } skipWhitespace(lBreak, bidi); } } if (lineWasTooWide || w + tmpW > width) { - if (lBreak.obj && shouldPreserveNewline(lBreak.obj) && lBreak.obj->isText() && !static_cast<RenderText*>(lBreak.obj)->isWordBreak() && static_cast<RenderText*>(lBreak.obj)->characters()[lBreak.pos] == '\n') { + if (lBreak.obj && shouldPreserveNewline(lBreak.obj) && lBreak.obj->isText() && static_cast<RenderText*>(lBreak.obj)->characters()[lBreak.pos] == '\n') { if (!stoppedIgnoringSpaces && pos > 0) { // We need to stop right before the newline and then start up again. - addMidpoint(BidiIterator(0, o, pos - 1)); // Stop + BidiIterator midpoint(0, o, pos); + addMidpoint(BidiIterator(0, o, pos-1)); // Stop addMidpoint(BidiIterator(0, o, pos)); // Start } lBreak.increment(bidi); @@ -1662,7 +1810,8 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi if (c == '\n' && preserveNewline) { if (!stoppedIgnoringSpaces && pos > 0) { // We need to stop right before the newline and then start up again. - addMidpoint(BidiIterator(0, o, pos - 1)); // Stop + BidiIterator midpoint(0, o, pos); + addMidpoint(BidiIterator(0, o, pos-1)); // Stop addMidpoint(BidiIterator(0, o, pos)); // Start } lBreak.obj = o; @@ -1715,7 +1864,8 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi ignoringSpaces = false; lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0; lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces. - addMidpoint(BidiIterator(0, o, pos)); + BidiIterator startMid(0, o, pos); + addMidpoint(startMid); } if (currentCharacterIsSpace && !previousCharacterIsSpace) { @@ -1739,7 +1889,7 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi len--; atStart = false; } - + // IMPORTANT: pos is > length here! if (!ignoringSpaces) tmpW += t->width(lastSpace, pos - lastSpace, f, w+tmpW) + lastSpaceWordSpacing; @@ -1758,20 +1908,15 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi else { checkForBreak = false; RenderText* nextText = static_cast<RenderText*>(next); - if (nextText->textLength()) { + if (nextText->textLength() != 0) { UChar c = nextText->characters()[0]; if (c == ' ' || c == '\t' || (c == '\n' && !shouldPreserveNewline(next))) // If the next item on the line is text, and if we did not end with // a space, then the next text run continues our word (and so it needs to // keep adding to |tmpW|. Just update and continue. checkForBreak = true; - } else if (nextText->isWordBreak()) - checkForBreak = true; - bool willFitOnLine = w + tmpW <= width; - if (!willFitOnLine && !w) { - fitBelowFloats(tmpW, width); - willFitOnLine = tmpW <= width; } + bool willFitOnLine = (w + tmpW <= width); bool canPlaceOnLine = willFitOnLine || !autoWrapWasEverTrueOnLine; if (canPlaceOnLine && checkForBreak) { w += tmpW; @@ -1787,11 +1932,21 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi // if we have floats, try to get below them. if (currentCharacterIsSpace && !ignoringSpaces && o->style()->collapseWhiteSpace()) trailingSpaceObject = 0; - - if (w) - goto end; - - fitBelowFloats(tmpW, width); + + int fb = nearestFloatBottom(m_height); + int newLineWidth = lineWidth(fb); + // See if |tmpW| will fit on the new line. As long as it does not, + // keep adjusting our float bottom until we find some room. + int lastFloatBottom = m_height; + while (lastFloatBottom < fb && tmpW > newLineWidth) { + lastFloatBottom = fb; + fb = nearestFloatBottom(fb); + newLineWidth = lineWidth(fb); + } + if (!w && m_height < fb && width < newLineWidth) { + m_height = fb; + width = newLineWidth; + } // |width| may have been adjusted because we got shoved down past a float (thus // giving us more room), so we need to retest, and only jump to diff --git a/WebCore/rendering/bidi.h b/WebCore/rendering/bidi.h index 065b3c3..7e213e3 100644 --- a/WebCore/rendering/bidi.h +++ b/WebCore/rendering/bidi.h @@ -35,15 +35,15 @@ class RenderObject; class InlineBox; struct BidiRun : BidiCharacterRun { - BidiRun(int start, int stop, RenderObject* object, BidiContext* context, WTF::Unicode::Direction dir) + BidiRun(int start, int stop, RenderObject* o, BidiContext* context, WTF::Unicode::Direction dir) : BidiCharacterRun(start, stop, context, dir) - , m_object(object) - , m_box(0) - , m_compact(false) + , obj(o) + , box(0) + , compact(false) { } - void destroy(); + void destroy(RenderArena*); // Overloaded new operator. void* operator new(size_t, RenderArena*) throw(); @@ -58,9 +58,9 @@ private: void* operator new(size_t) throw(); public: - RenderObject* m_object; - InlineBox* m_box; - bool m_compact; + RenderObject* obj; + InlineBox* box; + bool compact; }; } // namespace WebCore diff --git a/WebCore/rendering/break_lines.cpp b/WebCore/rendering/break_lines.cpp index 05748ac..583e3ba 100644 --- a/WebCore/rendering/break_lines.cpp +++ b/WebCore/rendering/break_lines.cpp @@ -47,16 +47,14 @@ static inline bool isBreakableSpace(UChar ch, bool treatNoBreakSpaceAsBreak) static inline bool shouldBreakAfter(UChar ch) { // Match WinIE's breaking strategy, which is to always allow breaks after hyphens and question marks. - // FIXME: it appears that IE behavior is more complex, see <http://bugs.webkit.org/show_bug.cgi?id=17475>. switch (ch) { case '-': case '?': +#ifdef ANDROID_LAYOUT + // as '/' is used in uri which is always long, we would like to break it + case '/': +#endif case softHyphen: - // FIXME: cases for ideographicComma and ideographicFullStop are a workaround for an issue in Unicode 5.0 - // which is likely to be resolved in Unicode 5.1 <http://bugs.webkit.org/show_bug.cgi?id=17411>. - // We may want to remove or conditionalize this workaround at some point. - case ideographicComma: - case ideographicFullStop: return true; default: return false; |