diff options
Diffstat (limited to 'WebCore/rendering')
72 files changed, 991 insertions, 618 deletions
diff --git a/WebCore/rendering/InlineBox.cpp b/WebCore/rendering/InlineBox.cpp index b8f0ce1..145096b 100644 --- a/WebCore/rendering/InlineBox.cpp +++ b/WebCore/rendering/InlineBox.cpp @@ -164,22 +164,26 @@ void InlineBox::paint(PaintInfo& paintInfo, int tx, int ty) if (!paintInfo.shouldPaintWithinRoot(renderer()) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)) return; + IntPoint childPoint = IntPoint(tx, ty); + if (parent()->renderer()->style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock(). + childPoint = renderer()->containingBlock()->flipForWritingMode(toRenderBox(renderer()), childPoint, RenderBox::ParentToChildFlippingAdjustment); + // Paint all phases of replaced elements atomically, as though the replaced element established its // own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1 // specification.) bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip; PaintInfo info(paintInfo); info.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground; - renderer()->paint(info, tx, ty); + renderer()->paint(info, childPoint.x(), childPoint.y()); if (!preservePhase) { info.phase = PaintPhaseChildBlockBackgrounds; - renderer()->paint(info, tx, ty); + renderer()->paint(info, childPoint.x(), childPoint.y()); info.phase = PaintPhaseFloat; - renderer()->paint(info, tx, ty); + renderer()->paint(info, childPoint.x(), childPoint.y()); info.phase = PaintPhaseForeground; - renderer()->paint(info, tx, ty); + renderer()->paint(info, childPoint.x(), childPoint.y()); info.phase = PaintPhaseOutline; - renderer()->paint(info, tx, ty); + renderer()->paint(info, childPoint.x(), childPoint.y()); } } diff --git a/WebCore/rendering/InlineBox.h b/WebCore/rendering/InlineBox.h index 72e5534..c5f1997 100644 --- a/WebCore/rendering/InlineBox.h +++ b/WebCore/rendering/InlineBox.h @@ -113,6 +113,13 @@ public: virtual bool isLineBreak() const { return false; } virtual void adjustPosition(int dx, int dy); + void adjustLineDirectionPosition(int delta) + { + if (isHorizontal()) + adjustPosition(delta, 0); + else + adjustPosition(0, delta); + } virtual void paint(PaintInfo&, int tx, int ty); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty); @@ -248,7 +255,7 @@ public: // The logical height is our extent in the block flow direction, i.e., height for horizontal text and width for vertical text. int logicalHeight() const; - virtual int baselinePosition() const { return boxModelObject()->baselinePosition(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); } + virtual int baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); } virtual int lineHeight() const { return boxModelObject()->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); } diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index 8525673..e67c751 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -35,6 +35,7 @@ #include "RenderTableCell.h" #include "RootInlineBox.h" #include "Text.h" +#include "VerticalPositionCache.h" #include <math.h> @@ -359,6 +360,43 @@ int InlineFlowBox::placeBoxesInInlineDirection(int logicalLeft, bool& needsWordS return logicalLeft; } +bool InlineFlowBox::requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap& textBoxDataMap) const +{ + if (isHorizontal()) + return false; + + if (renderer()->style(m_firstLine)->font().primaryFont()->orientation() == Vertical) + return true; + + for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { + if (curr->renderer()->isPositioned()) + continue; // Positioned placeholders don't affect calculations. + + if (curr->isInlineFlowBox()) { + if (static_cast<InlineFlowBox*>(curr)->requiresIdeographicBaseline(textBoxDataMap)) + return true; + } else { + if (curr->renderer()->style(m_firstLine)->font().primaryFont()->orientation() == Vertical) + return true; + + const Vector<const SimpleFontData*>* usedFonts = 0; + if (curr->isInlineTextBox()) { + GlyphOverflowAndFallbackFontsMap::const_iterator it = textBoxDataMap.find(static_cast<InlineTextBox*>(curr)); + usedFonts = it == textBoxDataMap.end() ? 0 : &it->second.first; + } + + if (usedFonts) { + for (size_t i = 0; i < usedFonts->size(); ++i) { + if (usedFonts->at(i)->orientation() == Vertical) + return true; + } + } + } + } + + return false; +} + void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom) { @@ -387,29 +425,102 @@ void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, } } -static int verticalPositionForBox(InlineBox* curr, bool firstLine) +static int verticalPositionForBox(InlineBox* box, FontBaseline baselineType, bool firstLine, VerticalPositionCache& verticalPositionCache) { - if (curr->renderer()->isText()) - return curr->parent()->logicalTop(); - if (curr->renderer()->isBox()) - return toRenderBox(curr->renderer())->verticalPosition(firstLine); - return toRenderInline(curr->renderer())->verticalPositionFromCache(firstLine); + if (box->renderer()->isText()) + return box->parent()->logicalTop(); + + RenderBoxModelObject* renderer = box->boxModelObject(); + ASSERT(renderer->isInline()); + if (!renderer->isInline()) + return 0; + + // This method determines the vertical position for inline elements. + if (firstLine && !renderer->document()->usesFirstLineRules()) + firstLine = false; + + // Check the cache. + bool isRenderInline = renderer->isRenderInline(); + if (isRenderInline && !firstLine) { + int verticalPosition = verticalPositionCache.get(renderer, baselineType); + if (verticalPosition != PositionUndefined) + return verticalPosition; + } + + int verticalPosition = 0; + EVerticalAlign verticalAlign = renderer->style()->verticalAlign(); + if (verticalAlign == TOP) + verticalPosition = PositionTop; + else if (verticalAlign == BOTTOM) + verticalPosition = PositionBottom; + else { + RenderObject* parent = renderer->parent(); + if (parent->isRenderInline() && parent->style()->verticalAlign() != TOP && parent->style()->verticalAlign() != BOTTOM) + verticalPosition = box->parent()->logicalTop(); + + if (verticalAlign != BASELINE) { + const Font& font = parent->style(firstLine)->font(); + int fontSize = font.pixelSize(); + + LineDirectionMode lineDirection = parent->style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine; + + if (verticalAlign == SUB) + verticalPosition += fontSize / 5 + 1; + else if (verticalAlign == SUPER) + verticalPosition -= fontSize / 3 + 1; + else if (verticalAlign == TEXT_TOP) + verticalPosition += renderer->baselinePosition(baselineType, firstLine, lineDirection) - font.ascent(baselineType); + else if (verticalAlign == MIDDLE) + verticalPosition += -static_cast<int>(font.xHeight() / 2) - renderer->lineHeight(firstLine, lineDirection) / 2 + renderer->baselinePosition(baselineType, firstLine, lineDirection); + else if (verticalAlign == TEXT_BOTTOM) { + verticalPosition += font.descent(baselineType); + // lineHeight - baselinePosition is always 0 for replaced elements (except inline blocks), so don't bother wasting time in that case. + if (!renderer->isReplaced() || renderer->isInlineBlockOrInlineTable()) + verticalPosition -= (renderer->lineHeight(firstLine, lineDirection) - renderer->baselinePosition(baselineType, firstLine, lineDirection)); + } else if (verticalAlign == BASELINE_MIDDLE) + verticalPosition += -renderer->lineHeight(firstLine, lineDirection) / 2 + renderer->baselinePosition(baselineType, firstLine, lineDirection); + else if (verticalAlign == LENGTH) + verticalPosition -= renderer->style()->verticalAlignLength().calcValue(renderer->lineHeight(firstLine, lineDirection)); + } + } + + // Store the cached value. + if (isRenderInline && !firstLine) + verticalPositionCache.set(renderer, baselineType, verticalPosition); + + return verticalPosition; } void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom, - int& maxAscent, int& maxDescent, bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap) + int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent, + bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, + FontBaseline baselineType, VerticalPositionCache& verticalPositionCache) { + // The primary purpose of this function is to compute the maximal ascent and descent values for + // a line. + // + // The maxAscent value represents the distance of the highest point of any box (including line-height) from + // the root box's baseline. The maxDescent value represents the distance of the lowest point of any box + // (also including line-height) from the root box baseline. These values can be negative. + // + // A secondary purpose of this function is to store the offset of very box's baseline from the root box's + // baseline. This information is cached in the logicalTop() of every box. We're effectively just using + // the logicalTop() as scratch space. if (isRootInlineBox()) { // Examine our root box. int height = lineHeight(); - int baseline = baselinePosition(); + int baseline = baselinePosition(baselineType); if (hasTextChildren() || strictMode) { int ascent = baseline; int descent = height - ascent; - if (maxAscent < ascent) + if (maxAscent < ascent || !setMaxAscent) { maxAscent = ascent; - if (maxDescent < descent) + setMaxAscent = true; + } + if (maxDescent < descent || !setMaxDescent) { maxDescent = descent; + setMaxDescent = true; + } } } @@ -418,7 +529,18 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi continue; // Positioned placeholders don't affect calculations. bool isInlineFlow = curr->isInlineFlowBox(); - + + // Because a box can be positioned such that it ends up fully above or fully below the + // root line box, we only consider it to affect the maxAscent and maxDescent values if some + // part of the box (EXCLUDING line-height) is above (for ascent) or below (for descent) the root box's baseline. + bool affectsAscent = false; + bool affectsDescent = false; + + // The verticalPositionForBox function returns the distance between the child box's baseline + // and the root box's baseline. The value is negative if the child box's baseline is above the + // root box's baseline, and it is positive if the child box's baseline is below the root box's baseline. + curr->setLogicalTop(verticalPositionForBox(curr, baselineType, m_firstLine, verticalPositionCache)); + int lineHeight; int baseline; Vector<const SimpleFontData*>* usedFonts = 0; @@ -427,39 +549,45 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi usedFonts = it == textBoxDataMap.end() ? 0 : &it->second.first; } - if (usedFonts) { + if (usedFonts && curr->renderer()->style(m_firstLine)->lineHeight().isNegative()) { usedFonts->append(curr->renderer()->style(m_firstLine)->font().primaryFont()); Length parentLineHeight = curr->renderer()->parent()->style()->lineHeight(); - if (parentLineHeight.isNegative()) { - int baselineToBottom = 0; - baseline = 0; - for (size_t i = 0; i < usedFonts->size(); ++i) { - int halfLeading = (usedFonts->at(i)->lineSpacing() - usedFonts->at(i)->ascent() - usedFonts->at(i)->descent()) / 2; - baseline = max(baseline, halfLeading + usedFonts->at(i)->ascent()); - baselineToBottom = max(baselineToBottom, usedFonts->at(i)->lineSpacing() - usedFonts->at(i)->ascent() - usedFonts->at(i)->descent() - halfLeading); - } - lineHeight = baseline + baselineToBottom; - } else if (parentLineHeight.isPercent()) { - lineHeight = parentLineHeight.calcMinValue(curr->renderer()->style()->fontSize()); - baseline = 0; - for (size_t i = 0; i < usedFonts->size(); ++i) { - int halfLeading = (lineHeight - usedFonts->at(i)->ascent() - usedFonts->at(i)->descent()) / 2; - baseline = max(baseline, halfLeading + usedFonts->at(i)->ascent()); - } - } else { - lineHeight = parentLineHeight.value(); - baseline = 0; - for (size_t i = 0; i < usedFonts->size(); ++i) { - int halfLeading = (lineHeight - usedFonts->at(i)->ascent() - usedFonts->at(i)->descent()) / 2; - baseline = max(baseline, halfLeading + usedFonts->at(i)->ascent()); + bool baselineSet = false; + baseline = 0; + int baselineToBottom = 0; + for (size_t i = 0; i < usedFonts->size(); ++i) { + int halfLeading = (usedFonts->at(i)->lineSpacing() - usedFonts->at(i)->height()) / 2; + int usedFontAscent = halfLeading + usedFonts->at(i)->ascent(baselineType); + int usedFontDescent = usedFonts->at(i)->lineSpacing() - usedFontAscent; + if (!baselineSet) { + baselineSet = true; + baseline = usedFontAscent; + baselineToBottom = usedFontDescent; + } else { + baseline = max(baseline, usedFontAscent); + baselineToBottom = max(baselineToBottom, usedFontDescent); } } + lineHeight = baseline + baselineToBottom; } else { lineHeight = curr->lineHeight(); - baseline = curr->baselinePosition(); + baseline = curr->baselinePosition(baselineType); + if (curr->isText() || isInlineFlow) { + // Examine the font box for inline flows and text boxes to see if any part of it is above the baseline. + // If the top of our font box relative to the root box baseline is above the root box baseline, then + // we are contributing to the maxAscent value. + affectsAscent = curr->renderer()->style(m_firstLine)->font().ascent(baselineType) - curr->logicalTop() > 0; + + // Descent is similar. If any part of our font box is below the root box's baseline, then + // we contribute to the maxDescent value. + affectsDescent = curr->renderer()->style(m_firstLine)->font().descent(baselineType) + curr->logicalTop() > 0; + } else { + // Replaced elements always affect both the ascent and descent. + affectsAscent = true; + affectsDescent = true; + } } - curr->setLogicalTop(verticalPositionForBox(curr, m_firstLine)); if (curr->logicalTop() == PositionTop) { if (maxPositionTop < lineHeight) maxPositionTop = lineHeight; @@ -467,23 +595,35 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi if (maxPositionBottom < lineHeight) maxPositionBottom = lineHeight; } else if ((!isInlineFlow || static_cast<InlineFlowBox*>(curr)->hasTextChildren()) || curr->boxModelObject()->hasInlineDirectionBordersOrPadding() || strictMode) { + // Note that these values can be negative. Even though we only affect the maxAscent and maxDescent values + // if our box (excluding line-height) was above (for ascent) or below (for descent) the root baseline, once you factor in line-height + // the final box can end up being fully above or fully below the root box's baseline! This is ok, but what it + // means is that ascent and descent (including leading), can end up being negative. The setMaxAscent and + // setMaxDescent booleans are used to ensure that we're willing to initially set maxAscent/Descent to negative + // values. int ascent = baseline - curr->logicalTop(); int descent = lineHeight - ascent; - if (maxAscent < ascent) + if (affectsAscent && (maxAscent < ascent || !setMaxAscent)) { maxAscent = ascent; - if (maxDescent < descent) + setMaxAscent = true; + } + if (affectsDescent && (maxDescent < descent || !setMaxDescent)) { maxDescent = descent; + setMaxDescent = true; + } } if (curr->isInlineFlowBox()) - static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode, textBoxDataMap); + static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, + setMaxAscent, setMaxDescent, strictMode, textBoxDataMap, + baselineType, verticalPositionCache); } } -void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop) +void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop, FontBaseline baselineType) { if (isRootInlineBox()) - setLogicalTop(top + maxAscent - baselinePosition()); // Place our root box. + setLogicalTop(top + maxAscent - baselinePosition(baselineType)); // Place our root box. for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer()->isPositioned()) @@ -493,7 +633,7 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs // line-height). bool isInlineFlow = curr->isInlineFlowBox(); if (isInlineFlow) - static_cast<InlineFlowBox*>(curr)->placeBoxesInBlockDirection(top, maxHeight, maxAscent, strictMode, lineTop, lineBottom, setLineTop); + static_cast<InlineFlowBox*>(curr)->placeBoxesInBlockDirection(top, maxHeight, maxAscent, strictMode, lineTop, lineBottom, setLineTop, baselineType); bool childAffectsTopBottomPos = true; if (curr->logicalTop() == PositionTop) @@ -503,14 +643,14 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs else { if ((isInlineFlow && !static_cast<InlineFlowBox*>(curr)->hasTextChildren()) && !curr->boxModelObject()->hasInlineDirectionBordersOrPadding() && !strictMode) childAffectsTopBottomPos = false; - int posAdjust = maxAscent - curr->baselinePosition(); + int posAdjust = maxAscent - curr->baselinePosition(baselineType); curr->setLogicalTop(curr->logicalTop() + top + posAdjust); } int newLogicalTop = curr->logicalTop(); if (curr->isText() || curr->isInlineFlowBox()) { const Font& font = curr->renderer()->style(m_firstLine)->font(); - newLogicalTop += curr->baselinePosition() - font.ascent(); + newLogicalTop += curr->baselinePosition(baselineType) - font.ascent(baselineType); if (curr->isInlineFlowBox()) { RenderBoxModelObject* boxObject = toRenderBoxModelObject(curr->renderer()); newLogicalTop -= boxObject->style(m_firstLine)->isHorizontalWritingMode() ? boxObject->borderTop() + boxObject->paddingTop() : @@ -536,7 +676,7 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs if (isRootInlineBox()) { const Font& font = renderer()->style(m_firstLine)->font(); - setLogicalTop(logicalTop() + baselinePosition() - font.ascent()); + setLogicalTop(logicalTop() + baselinePosition(baselineType) - font.ascent(baselineType)); if (hasTextChildren() || strictMode) { if (!setLineTop) { diff --git a/WebCore/rendering/InlineFlowBox.h b/WebCore/rendering/InlineFlowBox.h index be6dfd2..e3127af 100644 --- a/WebCore/rendering/InlineFlowBox.h +++ b/WebCore/rendering/InlineFlowBox.h @@ -30,6 +30,7 @@ class HitTestRequest; class HitTestResult; class InlineTextBox; class RenderLineBoxList; +class VerticalPositionCache; typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap; @@ -155,13 +156,15 @@ public: bool onEndChain(RenderObject* endObject); int placeBoxesInInlineDirection(int logicalLeft, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&); void computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom, - int& maxAscent, int& maxDescent, bool strictMode, GlyphOverflowAndFallbackFontsMap&); + int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent, + bool strictMode, GlyphOverflowAndFallbackFontsMap&, FontBaseline, VerticalPositionCache&); void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom); - void placeBoxesInBlockDirection(int logicalTop, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop); + void placeBoxesInBlockDirection(int logicalTop, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop, FontBaseline); void flipLinesInBlockDirection(int lineTop, int lineBottom); void computeBlockDirectionOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap&); - + bool requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap&) const; + void removeChild(InlineBox* child); virtual RenderObject::SelectionState selectionState(); diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 9c96cc6..575bdf2 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -43,11 +43,11 @@ using namespace std; namespace WebCore { -int InlineTextBox::baselinePosition() const +int InlineTextBox::baselinePosition(FontBaseline baselineType) const { if (!isText() || !parent()) return 0; - return parent()->baselinePosition(); + return parent()->baselinePosition(baselineType); } int InlineTextBox::lineHeight() const @@ -171,9 +171,7 @@ IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos) int width = isHorizontal() ? logicalWidth : selHeight; int height = isHorizontal() ? selHeight : logicalWidth; - IntRect result = IntRect(topPoint, IntSize(width, height)); - flipForWritingMode(result); - return result; + return IntRect(topPoint, IntSize(width, height)); } void InlineTextBox::deleteLine(RenderArena* arena) diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h index e72d625..bc2219b 100644 --- a/WebCore/rendering/InlineTextBox.h +++ b/WebCore/rendering/InlineTextBox.h @@ -70,7 +70,7 @@ public: static inline bool compareByStart(const InlineTextBox* first, const InlineTextBox* second) { return first->start() < second->start(); } - virtual int baselinePosition() const; + virtual int baselinePosition(FontBaseline) const; virtual int lineHeight() const; private: diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp index adaac03..1af1b80 100644 --- a/WebCore/rendering/MediaControlElements.cpp +++ b/WebCore/rendering/MediaControlElements.cpp @@ -166,7 +166,7 @@ bool MediaControlElement::rendererIsNeeded(RenderStyle* style) { ASSERT(document()->page()); - return HTMLDivElement::rendererIsNeeded(style) && parent() && parent()->renderer() + return HTMLDivElement::rendererIsNeeded(style) && parentNode() && parentNode()->renderer() && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), m_mediaElement)); } @@ -183,12 +183,12 @@ void MediaControlElement::attach() return; renderer->setStyle(style.get()); setRenderer(renderer); - if (parent() && parent()->renderer()) { + if (parentNode() && parentNode()->renderer()) { // Find next sibling with a renderer to determine where to insert. Node* sibling = nextSibling(); while (sibling && !sibling->renderer()) sibling = sibling->nextSibling(); - parent()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0); + parentNode()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0); } ContainerNode::attach(); } @@ -202,7 +202,7 @@ void MediaControlElement::updateStyle() if (!style) return; - bool needsRenderer = rendererIsNeeded(style.get()) && parent() && parent()->renderer(); + bool needsRenderer = rendererIsNeeded(style.get()) && parentNode() && parentNode()->renderer(); if (renderer() && !needsRenderer) detach(); else if (!renderer() && needsRenderer) @@ -416,7 +416,7 @@ bool MediaControlInputElement::rendererIsNeeded(RenderStyle* style) { ASSERT(document()->page()); - return HTMLInputElement::rendererIsNeeded(style) && parent() && parent()->renderer() + return HTMLInputElement::rendererIsNeeded(style) && parentNode() && parentNode()->renderer() && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), mediaElement())); } @@ -434,12 +434,12 @@ void MediaControlInputElement::attach() return; renderer->setStyle(style.get()); setRenderer(renderer); - if (parent() && parent()->renderer()) { + if (parentNode() && parentNode()->renderer()) { // Find next sibling with a renderer to determine where to insert. Node* sibling = nextSibling(); while (sibling && !sibling->renderer()) sibling = sibling->nextSibling(); - parent()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0); + parentNode()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0); } ContainerNode::attach(); } @@ -453,7 +453,7 @@ void MediaControlInputElement::updateStyle() if (!style) return; - bool needsRenderer = rendererIsNeeded(style.get()) && parent() && parent()->renderer(); + bool needsRenderer = rendererIsNeeded(style.get()) && parentNode() && parentNode()->renderer(); if (renderer() && !needsRenderer) detach(); else if (!renderer() && needsRenderer) diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index a43fea9..aadc1d4 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -931,11 +931,9 @@ static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObje if (prev && prev->firstChild() && prev->firstChild()->isInline() && prev->firstChild()->isRunIn()) return false; -#if ENABLE(RUBY) if ((prev && (prev->isRubyRun() || prev->isRubyBase())) || (next && (next->isRubyRun() || next->isRubyBase()))) return false; -#endif if (!prev || !next) return true; @@ -1164,7 +1162,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight) colInfo->clearForcedBreaks(); } - LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection(), pageHeight, pageHeightChanged, colInfo); + LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode(), pageHeight, pageHeightChanged, colInfo); // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track // our current maximal positive and negative margins. These values are used when we @@ -1997,7 +1995,7 @@ bool RenderBlock::layoutOnlyPositionedObjects() if (!posChildNeedsLayout() || normalChildNeedsLayout() || selfNeedsLayout()) return false; - LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection()); + LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode()); if (needsPositionedMovementLayout()) { tryLayoutDoingPositionedMovementOnly(); @@ -2583,8 +2581,9 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty) if (RenderLayer* layer = enclosingLayer()) { gapRectsBounds.move(IntSize(-tx, -ty)); if (!hasLayer()) { - FloatRect localBounds(gapRectsBounds); - gapRectsBounds = localToContainerQuad(localBounds, layer->renderer()).enclosingBoundingBox(); + IntRect localBounds(gapRectsBounds); + flipForWritingMode(localBounds); + gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox(); gapRectsBounds.move(layer->scrolledContentOffset()); } layer->addBlockSelectionGapsBounds(gapRectsBounds); @@ -3978,8 +3977,12 @@ void RenderBlock::addIntrudingFloats(RenderBlock* prev, int logicalLeftOffset, i // above. |logicalLeftOffset| will equal the margin in this case, so it's already been taken // into account. Only apply this code if prev is the parent, since otherwise the left margin // will get applied twice. - if (prev != parent()) - floatingObj->setLeft(floatingObj->left() + (style()->isHorizontalWritingMode() ? prev->marginLeft() : prev->marginTop())); + if (prev != parent()) { + if (style()->isHorizontalWritingMode()) + floatingObj->setLeft(floatingObj->left() + prev->marginLeft()); + else + floatingObj->setTop(floatingObj->top() + prev->marginTop()); + } floatingObj->m_shouldPaint = false; // We are not in the direct inheritance chain for this float. We will never paint it. floatingObj->m_renderer = r->m_renderer; @@ -4150,7 +4153,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) { IntRect boundsRect(tx, ty, width(), height()); if (visibleToHitTesting() && boundsRect.intersects(result.rectForPoint(_x, _y))) { - updateHitTestResult(result, IntPoint(_x - tx, _y - ty)); + updateHitTestResult(result, flipForWritingMode(IntPoint(_x - tx, _y - ty))); if (!result.addNodeToRectBasedTestResult(node(), _x, _y, boundsRect)) return true; } @@ -4174,8 +4177,8 @@ bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& re for (it.toLast(); (floatingObject = it.current()); --it) { if (floatingObject->m_shouldPaint && !floatingObject->m_renderer->hasSelfPaintingLayer()) { int xOffset = floatingObject->left() + floatingObject->m_renderer->marginLeft() - floatingObject->m_renderer->x(); - int yOffset = floatingObject->top() + floatingObject->m_renderer->marginTop() - floatingObject->m_renderer->y(); - IntPoint childPoint= flipForWritingMode(floatingObject->m_renderer, IntPoint(tx + xOffset, ty + yOffset), ParentToChildFlippingAdjustment); + int yOffset = floatingObject->top() + floatingObject->m_renderer->marginTop() - floatingObject->m_renderer->y(); + IntPoint childPoint = flipForWritingMode(floatingObject->m_renderer, IntPoint(tx + xOffset, ty + yOffset), ParentToChildFlippingAdjustment); if (floatingObject->m_renderer->hitTest(request, result, IntPoint(x, y), childPoint.x(), childPoint.y())) { updateHitTestResult(result, IntPoint(x - childPoint.x(), y - childPoint.y())); return true; @@ -4278,8 +4281,9 @@ Position RenderBlock::positionForRenderer(RenderObject* renderer, bool start) co // FIXME: This function should go on RenderObject as an instance method. Then // all cases in which positionForPoint recurs could call this instead to // prevent crossing editable boundaries. This would require many tests. -static VisiblePosition positionForPointRespectingEditingBoundaries(RenderBox* parent, RenderBox* child, const IntPoint& pointInParentCoordinates) +static VisiblePosition positionForPointRespectingEditingBoundaries(RenderBlock* parent, RenderBox* child, const IntPoint& pointInParentCoordinates) { + // FIXME: This is wrong if the child's writing-mode is different from the parent's. IntPoint pointInChildCoordinates(pointInParentCoordinates - child->location()); // If this is an anonymous renderer, we just recur normally @@ -4297,14 +4301,15 @@ static VisiblePosition positionForPointRespectingEditingBoundaries(RenderBox* pa if (!ancestor || ancestor->node()->isContentEditable() == childNode->isContentEditable()) return child->positionForPoint(pointInChildCoordinates); - // Otherwise return before or after the child, depending on if the click was left or right of the child - int childMidX = child->width() / 2; - if (pointInChildCoordinates.x() < childMidX) + // Otherwise return before or after the child, depending on if the click was to the logical left or logical right of the child + int childMiddle = parent->logicalWidthForChild(child) / 2; + int logicalLeft = parent->style()->isHorizontalWritingMode() ? pointInChildCoordinates.x() : pointInChildCoordinates.y(); + if (logicalLeft < childMiddle) return ancestor->createVisiblePosition(childNode->nodeIndex(), DOWNSTREAM); return ancestor->createVisiblePosition(childNode->nodeIndex() + 1, UPSTREAM); } -VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& pointInContents) +VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& pointInLogicalContents) { ASSERT(childrenInline()); @@ -4323,8 +4328,8 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& lastRootBoxWithChildren = root; // check if this root line box is located at this y coordinate - if (pointInContents.y() < root->selectionBottom()) { - closestBox = root->closestLeafChildForXPos(pointInContents.x()); + if (pointInLogicalContents.y() < root->selectionBottom()) { + closestBox = root->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x()); if (closestBox) break; } @@ -4334,17 +4339,22 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& if (!moveCaretToBoundary && !closestBox && lastRootBoxWithChildren) { // y coordinate is below last root line box, pretend we hit it - closestBox = lastRootBoxWithChildren->closestLeafChildForXPos(pointInContents.x()); + closestBox = lastRootBoxWithChildren->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x()); } if (closestBox) { - if (moveCaretToBoundary && pointInContents.y() < firstRootBoxWithChildren->selectionTop()) { + if (moveCaretToBoundary && pointInLogicalContents.y() < firstRootBoxWithChildren->selectionTop()) { // y coordinate is above first root line box, so return the start of the first return VisiblePosition(positionForBox(firstRootBoxWithChildren->firstLeafChild(), true), DOWNSTREAM); } - // pass the box a y position that is inside it - return closestBox->renderer()->positionForPoint(IntPoint(pointInContents.x(), closestBox->m_y)); + // pass the box a top position that is inside it + IntPoint point(pointInLogicalContents.x(), closestBox->logicalTop()); + if (!style()->isHorizontalWritingMode()) + point = point.transposedPoint(); + if (closestBox->renderer()->isReplaced()) + return positionForPointRespectingEditingBoundaries(this, toRenderBox(closestBox->renderer()), point); + return closestBox->renderer()->positionForPoint(point); } if (lastRootBoxWithChildren) { @@ -4370,9 +4380,13 @@ VisiblePosition RenderBlock::positionForPoint(const IntPoint& point) return RenderBox::positionForPoint(point); if (isReplaced()) { - if (point.y() < 0 || (point.y() < height() && point.x() < 0)) + // FIXME: This seems wrong when the object's writing-mode doesn't match the line's writing-mode. + int pointLogicalLeft = style()->isHorizontalWritingMode() ? point.x() : point.y(); + int pointLogicalTop = style()->isHorizontalWritingMode() ? point.y() : point.x(); + + if (pointLogicalTop < 0 || (pointLogicalTop < logicalHeight() && pointLogicalLeft < 0)) return createVisiblePosition(caretMinOffset(), DOWNSTREAM); - if (point.y() >= height() || (point.y() >= 0 && point.x() >= width())) + if (pointLogicalTop >= logicalHeight() || (pointLogicalTop >= 0 && pointLogicalLeft >= logicalWidth())) return createVisiblePosition(caretMaxOffset(), DOWNSTREAM); } @@ -4380,11 +4394,14 @@ VisiblePosition RenderBlock::positionForPoint(const IntPoint& point) int contentsY = point.y(); offsetForContents(contentsX, contentsY); IntPoint pointInContents(contentsX, contentsY); + IntPoint pointInLogicalContents(pointInContents); + if (!style()->isHorizontalWritingMode()) + pointInLogicalContents = pointInLogicalContents.transposedPoint(); if (childrenInline()) - return positionForPointWithInlineChildren(pointInContents); + return positionForPointWithInlineChildren(pointInLogicalContents); - if (lastChildBox() && contentsY > lastChildBox()->y()) { + if (lastChildBox() && pointInContents.y() > lastChildBox()->logicalTop()) { for (RenderBox* childBox = lastChildBox(); childBox; childBox = childBox->previousSiblingBox()) { if (isChildHitTestCandidate(childBox)) return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents); @@ -4392,7 +4409,7 @@ VisiblePosition RenderBlock::positionForPoint(const IntPoint& point) } else { for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) { // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3). - if (isChildHitTestCandidate(childBox) && contentsY < childBox->frameRect().bottom()) + if (isChildHitTestCandidate(childBox) && pointInContents.y() < childBox->logicalBottom()) return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents); } } @@ -5255,7 +5272,7 @@ int RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction, LinePos return m_lineHeight; } -int RenderBlock::baselinePosition(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +int RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const { // Inline blocks are replaced elements. Otherwise, just pass off to // the base class. If we're being queried as though we're the root line @@ -5276,28 +5293,29 @@ int RenderBlock::baselinePosition(bool firstLine, LineDirectionMode direction, L // vertically (e.g., an overflow:hidden block that has had scrollTop moved) or if the baseline is outside // of our content box. bool ignoreBaseline = (layer() && (layer()->marquee() || (direction == HorizontalLine ? (layer()->verticalScrollbar() || layer()->scrollYOffset() != 0) - : (layer()->horizontalScrollbar() || layer()->scrollXOffset() != 0)))) || isWritingModeRoot(); + : (layer()->horizontalScrollbar() || layer()->scrollXOffset() != 0)))) || (isWritingModeRoot() && !isRubyRun()); + int baselinePos = ignoreBaseline ? -1 : lastLineBoxBaseline(); int bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth(); if (baselinePos != -1 && baselinePos <= bottomOfContent) return direction == HorizontalLine ? marginTop() + baselinePos : marginRight() + baselinePos; - return RenderBox::baselinePosition(firstLine, direction, linePositionMode); + return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode); } const Font& f = style(firstLine)->font(); - return f.ascent() + (lineHeight(firstLine, direction, linePositionMode) - f.height()) / 2; + return f.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - f.height()) / 2; } int RenderBlock::firstLineBoxBaseline() const { - if (!isBlockFlow() || isWritingModeRoot()) + if (!isBlockFlow() || (isWritingModeRoot() && !isRubyRun())) return -1; if (childrenInline()) { if (firstLineBox()) - return firstLineBox()->logicalTop() + style(true)->font().ascent(); + return firstLineBox()->logicalTop() + style(true)->font().ascent(firstRootBox()->baselineType()); else return -1; } @@ -5316,7 +5334,7 @@ int RenderBlock::firstLineBoxBaseline() const int RenderBlock::lastLineBoxBaseline() const { - if (!isBlockFlow() || isWritingModeRoot()) + if (!isBlockFlow() || (isWritingModeRoot() && !isRubyRun())) return -1; LineDirectionMode lineDirection = style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine; @@ -5327,7 +5345,7 @@ int RenderBlock::lastLineBoxBaseline() const return f.ascent() + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - f.height()) / 2 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight()); } if (lastLineBox()) - return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox())->font().ascent(); + return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox())->font().ascent(lastRootBox()->baselineType()); return -1; } else { bool haveNormalFlowChild = false; diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index 1cc89c0..645c0ec 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -58,7 +58,7 @@ public: // These two functions are overridden for inline-block. virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; - virtual int baselinePosition(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; RenderLineBoxList* lineBoxes() { return &m_lineBoxes; } const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; } @@ -458,7 +458,7 @@ private: RootInlineBox* constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool firstLine, bool lastLine, RenderObject* endObject); InlineFlowBox* createLineBoxes(RenderObject*, bool firstLine); void computeInlineDirectionPositionsForLine(RootInlineBox*, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&); - void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&); + void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&); void deleteEllipsisLineBoxes(); void checkLinesForTextOverflow(); void addOverflowFromInlineChildren(); diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp index e843110..b6dc39f 100644 --- a/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/WebCore/rendering/RenderBlockLineLayout.cpp @@ -35,6 +35,7 @@ #include "RenderView.h" #include "Settings.h" #include "TrailingFloatsRootInlineBox.h" +#include "VerticalPositionCache.h" #include "break_lines.h" #include <wtf/AlwaysInline.h> #include <wtf/RefCountedLeakCounter.h> @@ -477,9 +478,10 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, lineBox->placeBoxesInInlineDirection(logicalLeft, needsWordSpacing, textBoxDataMap); } -void RenderBlock::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap) +void RenderBlock::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, + VerticalPositionCache& verticalPositionCache) { - setLogicalHeight(lineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap)); + setLogicalHeight(lineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache)); lineBox->setBlockLogicalHeight(logicalHeight()); // Now make sure we place replaced render objects correctly. @@ -639,6 +641,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica if (fullLayout || o->selfNeedsLayout()) dirtyLineBoxesForRenderer(o, fullLayout); o->setNeedsLayout(false); +<<<<<<< HEAD #ifdef ANDROID_LAYOUT if (doTextWrap && !hasTextToWrap && o->isText()) { Node* node = o->node(); @@ -661,6 +664,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica #endif if (!o->isText()) toRenderInline(o)->invalidateVerticalPosition(); // FIXME: Should do better here and not always invalidate everything. +======= +>>>>>>> webkit.org at r72274 } o = bidiNext(this, o, 0, false, &endOfInline); } @@ -783,6 +788,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica bool isLineEmpty = true; bool paginated = view()->layoutState() && view()->layoutState()->isPaginated(); + VerticalPositionCache verticalPositionCache; + while (!end.atEnd()) { // FIXME: Is this check necessary before the first iteration or can it be moved to the end? if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineLogicalTop, repaintLogicalBottom, repaintLogicalTop))) @@ -883,7 +890,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica computeInlineDirectionPositionsForLine(lineBox, firstLine, resolver.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap); // Now position our text runs vertically. - computeBlockDirectionPositionsForLine(lineBox, resolver.firstRun(), textBoxDataMap); + computeBlockDirectionPositionsForLine(lineBox, resolver.firstRun(), textBoxDataMap, verticalPositionCache); #if ENABLE(SVG) // SVG text layout code computes vertical & horizontal positions on its own. @@ -1013,7 +1020,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica m_lineBoxes.appendLineBox(trailingFloatsLineBox); trailingFloatsLineBox->setConstructed(); GlyphOverflowAndFallbackFontsMap textBoxDataMap; - trailingFloatsLineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap); + VerticalPositionCache verticalPositionCache; + trailingFloatsLineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache); trailingFloatsLineBox->setBlockDirectionOverflowPositions(logicalHeight(), bottomLayoutOverflow, logicalHeight(), bottomVisualOverflow); trailingFloatsLineBox->setBlockLogicalHeight(logicalHeight()); } @@ -2162,66 +2170,38 @@ void RenderBlock::addOverflowFromInlineChildren() int RenderBlock::beforeSideVisibleOverflowForLine(RootInlineBox* line) const { - switch (style()->writingMode()) { - case TopToBottomWritingMode: + // Overflow is in the block's coordinate space, which means it isn't purely physical. For flipped blocks (rl and bt), + // we continue to use top and left overflow even though physically it's bottom and right. + if (style()->isHorizontalWritingMode()) return line->topVisibleOverflow(); - case LeftToRightWritingMode: - return line->leftVisibleOverflow(); - case RightToLeftWritingMode: - return line->rightVisibleOverflow(); - case BottomToTopWritingMode: - return line->bottomVisibleOverflow(); - } - ASSERT_NOT_REACHED(); - return line->topVisibleOverflow(); + return line->leftVisibleOverflow(); } int RenderBlock::afterSideVisibleOverflowForLine(RootInlineBox* line) const { - switch (style()->writingMode()) { - case TopToBottomWritingMode: + // Overflow is in the block's coordinate space, which means it isn't purely physical. For flipped blocks (rl and bt), + // we continue to use bottom and right overflow even though physically it's top and left. + if (style()->isHorizontalWritingMode()) return line->bottomVisibleOverflow(); - case LeftToRightWritingMode: - return line->rightVisibleOverflow(); - case RightToLeftWritingMode: - return line->leftVisibleOverflow(); - case BottomToTopWritingMode: - return line->topVisibleOverflow(); - } - ASSERT_NOT_REACHED(); - return line->bottomVisibleOverflow(); + return line->rightVisibleOverflow(); } int RenderBlock::beforeSideLayoutOverflowForLine(RootInlineBox* line) const { - switch (style()->writingMode()) { - case TopToBottomWritingMode: + // Overflow is in the block's coordinate space, which means it isn't purely physical. For flipped blocks (rl and bt), + // we continue to use top and left overflow even though physically it's bottom and right. + if (style()->isHorizontalWritingMode()) return line->topLayoutOverflow(); - case LeftToRightWritingMode: - return line->leftLayoutOverflow(); - case RightToLeftWritingMode: - return line->rightLayoutOverflow(); - case BottomToTopWritingMode: - return line->bottomLayoutOverflow(); - } - ASSERT_NOT_REACHED(); - return line->topLayoutOverflow(); + return line->leftLayoutOverflow(); } int RenderBlock::afterSideLayoutOverflowForLine(RootInlineBox* line) const { - switch (style()->writingMode()) { - case TopToBottomWritingMode: + // Overflow is in the block's coordinate space, which means it isn't purely physical. For flipped blocks (rl and bt), + // we continue to use bottom and right overflow even though physically it's top and left. + if (style()->isHorizontalWritingMode()) return line->bottomLayoutOverflow(); - case LeftToRightWritingMode: - return line->rightLayoutOverflow(); - case RightToLeftWritingMode: - return line->leftLayoutOverflow(); - case BottomToTopWritingMode: - return line->topLayoutOverflow(); - } - ASSERT_NOT_REACHED(); - return line->bottomLayoutOverflow(); + return line->rightLayoutOverflow(); } void RenderBlock::deleteEllipsisLineBoxes() diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index fc617c4..41e2cd5 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -297,15 +297,13 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the // new zoomed coordinate space. if (hasOverflowClip() && oldStyle && style() && oldStyle->effectiveZoom() != style()->effectiveZoom()) { - int left = scrollLeft(); - if (left) { + if (int left = layer()->scrollXOffset()) { left = (left / oldStyle->effectiveZoom()) * style()->effectiveZoom(); - setScrollLeft(left); + layer()->scrollToXOffset(left); } - int top = scrollTop(); - if (top) { + if (int top = layer()->scrollYOffset()) { top = (top / oldStyle->effectiveZoom()) * style()->effectiveZoom(); - setScrollTop(top); + layer()->scrollToYOffset(top); } } @@ -387,7 +385,7 @@ void RenderBox::layout() return; } - LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y())); + LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), style()->isFlippedBlocksWritingMode()); while (child) { child->layoutIfNeeded(); ASSERT(!child->needsLayout()); @@ -1183,7 +1181,7 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed |= isFixedPos; IntSize containerOffset = offsetFromContainer(o, roundedIntPoint(transformState.mappedPoint())); - + bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (useTransforms && shouldUseTransformFromContainer(o)) { TransformationMatrix t; @@ -1243,9 +1241,11 @@ IntSize RenderBox::offsetFromContainer(RenderObject* o, const IntPoint& point) c offset += relativePositionOffset(); if (!isInline() || isReplaced()) { - if (style()->position() != AbsolutePosition && style()->position() != FixedPosition) + if (style()->position() != AbsolutePosition && style()->position() != FixedPosition) { o->adjustForColumns(offset, IntPoint(point.x() + x(), point.y() + y())); - offset.expand(x(), y()); + offset += locationOffsetIncludingFlipping(); + } else + offset += locationOffset(); } if (o->hasOverflowClip()) @@ -1338,12 +1338,21 @@ IntRect RenderBox::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintCo r.inflate(v->maximalOutlineSize()); } } + computeRectForRepaint(repaintContainer, r); return r; } void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed) { + // The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space. + // Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more appropriate + // offset corner for the enclosing container). This allows for a fully RL or BT document to repaint + // properly even during layout, since the rect remains flipped all the way until the end. + // + // RenderView::computeRectForRepaint then converts the rect to physical coordinates. We also convert to + // physical when we hit a repaintContainer boundary. Therefore the final rect returned is always in the + // physical coordinate space of the repaintContainer. if (RenderView* v = view()) { // LayoutState is only valid for root-relative repainting if (v->layoutStateEnabled() && !repaintContainer) { @@ -1366,14 +1375,19 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In if (hasReflection()) rect.unite(reflectedRect(rect)); - if (repaintContainer == this) + if (repaintContainer == this) { + if (repaintContainer->style()->isFlippedBlocksWritingMode()) + flipForWritingMode(rect); return; + } bool containerSkipped; RenderObject* o = container(repaintContainer, &containerSkipped); if (!o) return; + if (isWritingModeRoot() && !isPositioned()) + flipForWritingMode(rect); IntPoint topLeft = rect.location(); topLeft.move(x(), y()); @@ -1433,10 +1447,7 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In rect.move(-containerOffset); return; } - - if (o->isBox()) - toRenderBox(o)->flipForWritingMode(rect); - + o->computeRectForRepaint(repaintContainer, rect, fixed); } @@ -3164,7 +3175,7 @@ bool RenderBox::shrinkToAvoidFloats() const bool RenderBox::avoidsFloats() const { - return isReplaced() || hasOverflowClip() || isHR() || isWritingModeRoot(); + return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot(); } void RenderBox::addShadowOverflow() @@ -3249,10 +3260,14 @@ int RenderBox::lineHeight(bool /*firstLine*/, LineDirectionMode direction, LineP return 0; } -int RenderBox::baselinePosition(bool /*firstLine*/, LineDirectionMode direction, LinePositionMode /*linePositionMode*/) const +int RenderBox::baselinePosition(FontBaseline baselineType, bool /*firstLine*/, LineDirectionMode direction, LinePositionMode /*linePositionMode*/) const { - if (isReplaced()) - return direction == HorizontalLine ? m_marginTop + height() + m_marginBottom : m_marginRight + width() + m_marginLeft; + if (isReplaced()) { + int result = direction == HorizontalLine ? m_marginTop + height() + m_marginBottom : m_marginRight + width() + m_marginLeft; + if (baselineType == AlphabeticBaseline) + return result; + return result - result / 2; + } return 0; } @@ -3272,7 +3287,7 @@ void RenderBox::blockDirectionOverflow(bool isLineHorizontal, int& logicalTopLay } } -IntPoint RenderBox::flipForWritingMode(RenderBox* child, const IntPoint& point, FlippingAdjustment adjustment) +IntPoint RenderBox::flipForWritingMode(const RenderBox* child, const IntPoint& point, FlippingAdjustment adjustment) const { if (!style()->isFlippedBlocksWritingMode()) return point; @@ -3284,7 +3299,7 @@ IntPoint RenderBox::flipForWritingMode(RenderBox* child, const IntPoint& point, return IntPoint(point.x() + width() - child->width() - child->x() - (adjustment == ParentToChildFlippingAdjustment ? child->x() : 0), point.y()); } -void RenderBox::flipForWritingMode(IntRect& rect) +void RenderBox::flipForWritingMode(IntRect& rect) const { if (!style()->isFlippedBlocksWritingMode()) return; @@ -3295,35 +3310,35 @@ void RenderBox::flipForWritingMode(IntRect& rect) rect.setX(width() - rect.right()); } -int RenderBox::flipForWritingMode(int position) +int RenderBox::flipForWritingMode(int position) const { if (!style()->isFlippedBlocksWritingMode()) return position; return logicalHeight() - position; } -IntPoint RenderBox::flipForWritingMode(const IntPoint& position) +IntPoint RenderBox::flipForWritingMode(const IntPoint& position) const { if (!style()->isFlippedBlocksWritingMode()) return position; return style()->isHorizontalWritingMode() ? IntPoint(position.x(), height() - position.y()) : IntPoint(width() - position.x(), position.y()); } -IntSize RenderBox::flipForWritingMode(const IntSize& offset) +IntSize RenderBox::flipForWritingMode(const IntSize& offset) const { if (!style()->isFlippedBlocksWritingMode()) return offset; return style()->isHorizontalWritingMode() ? IntSize(offset.width(), height() - offset.height()) : IntSize(width() - offset.width(), offset.height()); } -IntSize RenderBox::locationOffsetIncludingFlipping() +IntSize RenderBox::locationOffsetIncludingFlipping() const { if (!parent() || !parent()->isBox()) return locationOffset(); - RenderBox* parent = parentBox(); - IntPoint localPoint = parent->flipForWritingMode(this, location(), ChildToParentFlippingAdjustment); - return IntSize(localPoint.x(), localPoint.y()); + IntRect rect(frameRect()); + parentBox()->flipForWritingMode(rect); + return IntSize(rect.x(), rect.y()); } } // namespace WebCore diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index ac96bb7..091796b 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -378,15 +378,15 @@ public: bool isWritingModeRoot() const { return !parent() || parent()->style()->writingMode() != style()->writingMode(); } virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; - virtual int baselinePosition(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; enum FlippingAdjustment { ChildToParentFlippingAdjustment, ParentToChildFlippingAdjustment }; - IntPoint flipForWritingMode(RenderBox* child, const IntPoint&, FlippingAdjustment); - int flipForWritingMode(int position); - IntPoint flipForWritingMode(const IntPoint&); - IntSize flipForWritingMode(const IntSize&); - void flipForWritingMode(IntRect&); - IntSize locationOffsetIncludingFlipping(); + IntPoint flipForWritingMode(const RenderBox* child, const IntPoint&, FlippingAdjustment) const; + int flipForWritingMode(int position) const; // The offset is in the block direction (y for horizontal writing modes, x for vertical writing modes). + IntPoint flipForWritingMode(const IntPoint&) const; + IntSize flipForWritingMode(const IntSize&) const; + void flipForWritingMode(IntRect&) const; + IntSize locationOffsetIncludingFlipping() const; #ifdef ANDROID_LAYOUT int getVisibleWidth() const { return m_visibleWidth; } diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp index ae89e0a..1580b49 100644 --- a/WebCore/rendering/RenderBoxModelObject.cpp +++ b/WebCore/rendering/RenderBoxModelObject.cpp @@ -845,53 +845,6 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil destRect.intersect(IntRect(tx, ty, w, h)); } -int RenderBoxModelObject::verticalPosition(bool firstLine) const -{ - // This method determines the vertical position for inline elements. - ASSERT(isInline()); - if (!isInline()) - return 0; - - int vpos = 0; - EVerticalAlign va = style()->verticalAlign(); - if (va == TOP) - vpos = PositionTop; - else if (va == BOTTOM) - vpos = PositionBottom; - else { - bool checkParent = parent()->isRenderInline() && parent()->style()->verticalAlign() != TOP && parent()->style()->verticalAlign() != BOTTOM; - vpos = checkParent ? toRenderInline(parent())->verticalPositionFromCache(firstLine) : 0; - // don't allow elements nested inside text-top to have a different valignment. - if (va == BASELINE) - return vpos; - - const Font& f = parent()->style(firstLine)->font(); - int fontsize = f.pixelSize(); - - LineDirectionMode lineDirection = parent()->style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine; - - if (va == SUB) - vpos += fontsize / 5 + 1; - else if (va == SUPER) - vpos -= fontsize / 3 + 1; - else if (va == TEXT_TOP) - vpos += baselinePosition(firstLine, lineDirection) - f.ascent(); - else if (va == MIDDLE) - vpos += -static_cast<int>(f.xHeight() / 2) - lineHeight(firstLine, lineDirection) / 2 + baselinePosition(firstLine, lineDirection); - else if (va == TEXT_BOTTOM) { - vpos += f.descent(); - // lineHeight - baselinePosition is always 0 for replaced elements (except inline blocks), so don't bother wasting time in that case. - if (!isReplaced() || style()->display() == INLINE_BLOCK) - vpos -= (lineHeight(firstLine, lineDirection) - baselinePosition(firstLine, lineDirection)); - } else if (va == BASELINE_MIDDLE) - vpos += -lineHeight(firstLine, lineDirection) / 2 + baselinePosition(firstLine, lineDirection); - else if (va == LENGTH) - vpos -= style()->verticalAlignLength().calcValue(lineHeight(firstLine, lineDirection)); - } - - return vpos; -} - bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style, const NinePieceImage& ninePieceImage, CompositeOperator op) { diff --git a/WebCore/rendering/RenderBoxModelObject.h b/WebCore/rendering/RenderBoxModelObject.h index 121601f..f502424 100644 --- a/WebCore/rendering/RenderBoxModelObject.h +++ b/WebCore/rendering/RenderBoxModelObject.h @@ -28,11 +28,6 @@ namespace WebCore { -// Values for vertical alignment. -const int PositionTop = -0x7fffffff; -const int PositionBottom = 0x7fffffff; -const int PositionUndefined = 0x80000000; - // Modes for some of the line-related functions. enum LinePositionMode { PositionOnContainingLine, PositionOfInteriorLineBoxes }; enum LineDirectionMode { HorizontalLine, VerticalLine }; @@ -113,13 +108,10 @@ public: bool paintNinePieceImage(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver); void paintBoxShadow(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true); void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, InlineFlowBox* = 0, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0); - - // The difference between this inline's baseline position and the line's baseline position. - int verticalPosition(bool firstLine) const; // Overridden by subclasses to determine line height and baseline position. virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0; - virtual int baselinePosition(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0; // Called by RenderObject::destroy() (and RenderWidget::destroy()) and is the only way layers should ever be destroyed void destroyLayer(); diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index 3da8530..82bd1fa 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -231,7 +231,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty) RenderButton* buttonRenderer = toRenderButton(m_button->renderer()); int textY = buttonRenderer->absoluteBoundingBoxRect().y() + buttonRenderer->marginTop() + buttonRenderer->borderTop() + buttonRenderer->paddingTop() - + buttonRenderer->baselinePosition(true, HorizontalLine, PositionOnContainingLine); + + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); paintInfo.context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace()); diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp index d4dc75a..841442b 100644 --- a/WebCore/rendering/RenderFlexibleBox.cpp +++ b/WebCore/rendering/RenderFlexibleBox.cpp @@ -214,7 +214,7 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int /*pageHeight FIXM return; LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); - LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasTransform() || hasReflection()); + LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode()); int previousWidth = width(); int previousHeight = height(); diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index d21c1ea..48f21f1 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -61,6 +61,7 @@ using namespace HTMLNames; RenderImage::RenderImage(Node* node) : RenderReplaced(node, IntSize(0, 0)) + , m_needsToSetSizeForAltText(false) { updateAltText(); @@ -89,34 +90,35 @@ static const unsigned short paddingHeight = 4; static const int maxAltTextWidth = 1024; static const int maxAltTextHeight = 256; +IntSize RenderImage::imageSizeForError(CachedImage* newImage) const +{ + ASSERT_ARG(newImage, newImage); + ASSERT_ARG(newImage, newImage->image()); + + // imageSize() returns 0 for the error image. We need the true size of the + // error image, so we have to get it by grabbing image() directly. + return IntSize(paddingWidth + newImage->image()->width() * style()->effectiveZoom(), paddingHeight + newImage->image()->height() * style()->effectiveZoom()); +} + // Sets the image height and width to fit the alt text. Returns true if the // image size changed. bool RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */) { - int imageWidth = 0; - int imageHeight = 0; - - // If we'll be displaying either text or an image, add a little padding. - if (!m_altText.isEmpty() || newImage) { - imageWidth = paddingWidth; - imageHeight = paddingHeight; - } - - if (newImage && newImage->image()) { - // imageSize() returns 0 for the error image. We need the true size of the - // error image, so we have to get it by grabbing image() directly. - imageWidth += newImage->image()->width() * style()->effectiveZoom(); - imageHeight += newImage->image()->height() * style()->effectiveZoom(); + IntSize imageSize; + if (newImage && newImage->image()) + imageSize = imageSizeForError(newImage); + else if (!m_altText.isEmpty() || newImage) { + // If we'll be displaying either text or an image, add a little padding. + imageSize = IntSize(paddingWidth, paddingHeight); } - + // we have an alt and the user meant it (its not a text we invented) if (!m_altText.isEmpty()) { const Font& font = style()->font(); - imageWidth = max(imageWidth, min(font.width(TextRun(m_altText.characters(), m_altText.length())), maxAltTextWidth)); - imageHeight = max(imageHeight, min(font.height(), maxAltTextHeight)); + IntSize textSize(min(font.width(TextRun(m_altText.characters(), m_altText.length())), maxAltTextWidth), min(font.height(), maxAltTextHeight)); + imageSize = imageSize.expandedTo(textSize); } - - IntSize imageSize = IntSize(imageWidth, imageHeight); + if (imageSize == intrinsicSize()) return false; @@ -124,6 +126,16 @@ bool RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */) return true; } +void RenderImage::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderReplaced::styleDidChange(diff, oldStyle); + if (m_needsToSetSizeForAltText) { + if (!m_altText.isEmpty() && setImageSizeForAltText(m_imageResource->cachedImage())) + imageDimensionsChanged(true /* imageSizeChanged */); + m_needsToSetSizeForAltText = false; + } +} + void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect) { if (documentBeingDestroyed()) @@ -141,12 +153,25 @@ void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect) bool imageSizeChanged = false; // Set image dimensions, taking into account the size of the alt text. - if (m_imageResource->errorOccurred()) + if (m_imageResource->errorOccurred()) { + if (!m_altText.isEmpty() && document()->isPendingStyleRecalc()) { + ASSERT(node()); + if (node()) { + m_needsToSetSizeForAltText = true; + node()->setNeedsStyleRecalc(SyntheticStyleChange); + } + return; + } imageSizeChanged = setImageSizeForAltText(m_imageResource->cachedImage()); + } + + imageDimensionsChanged(imageSizeChanged, rect); +} +void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* rect) +{ bool shouldRepaint = true; - // Image dimensions have been changed, see what needs to be done if (m_imageResource->imageSize(style()->effectiveZoom()) != intrinsicSize() || imageSizeChanged) { if (!m_imageResource->errorOccurred()) setIntrinsicSize(m_imageResource->imageSize(style()->effectiveZoom())); diff --git a/WebCore/rendering/RenderImage.h b/WebCore/rendering/RenderImage.h index 308c863..86f5621 100644 --- a/WebCore/rendering/RenderImage.h +++ b/WebCore/rendering/RenderImage.h @@ -52,6 +52,8 @@ public: void highQualityRepaintTimerFired(Timer<RenderImage>*); protected: + virtual void styleDidChange(StyleDifference, const RenderStyle*); + virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); virtual void paintIntoRect(GraphicsContext*, const IntRect&); @@ -83,13 +85,16 @@ private: virtual int computeReplacedLogicalWidth(bool includeMaxWidth = true) const; virtual int computeReplacedLogicalHeight() const; + IntSize imageSizeForError(CachedImage*) const; + void imageDimensionsChanged(bool imageSizeChanged, const IntRect* = 0); + int calcAspectRatioLogicalWidth() const; int calcAspectRatioLogicalHeight() const; -private: // Text to display as long as the image isn't available. String m_altText; OwnPtr<RenderImageResource> m_imageResource; + bool m_needsToSetSizeForAltText; friend class RenderImageScaleObserver; }; diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index 1a792e7..8f828f9 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -48,7 +48,6 @@ RenderInline::RenderInline(Node* node) : RenderBoxModelObject(node) , m_continuation(0) , m_lineHeight(-1) - , m_verticalPosition(PositionUndefined) { setChildrenInline(true); } @@ -628,7 +627,6 @@ IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repain } IntRect r(-ow + left, -ow + top, boundingBox.width() + ow * 2, boundingBox.height() + ow * 2); - cb->flipForWritingMode(r); if (cb->hasColumns()) cb->adjustRectForColumns(r); @@ -904,23 +902,10 @@ int RenderInline::lineHeight(bool firstLine, LineDirectionMode /*direction*/, Li return m_lineHeight; } -int RenderInline::baselinePosition(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const { const Font& f = style(firstLine)->font(); - return f.ascent() + (lineHeight(firstLine, direction, linePositionMode) - f.height()) / 2; -} - -int RenderInline::verticalPositionFromCache(bool firstLine) const -{ - if (firstLine) // We're only really a first-line style if the document actually uses first-line rules. - firstLine = document()->usesFirstLineRules(); - int vpos = m_verticalPosition; - if (m_verticalPosition == PositionUndefined || firstLine) { - vpos = verticalPosition(firstLine); - if (!firstLine) - m_verticalPosition = vpos; - } - return vpos; + return f.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - f.height()) / 2; } IntSize RenderInline::relativePositionedInlineOffset(const RenderBox* child) const diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h index 1eb32ff..399a167 100644 --- a/WebCore/rendering/RenderInline.h +++ b/WebCore/rendering/RenderInline.h @@ -77,9 +77,6 @@ public: virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); void paintOutline(GraphicsContext*, int tx, int ty); - int verticalPositionFromCache(bool firstLine) const; - void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; } - protected: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); @@ -134,7 +131,7 @@ private: virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); } virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; - virtual int baselinePosition(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; virtual void childBecameNonInline(RenderObject* child); @@ -159,7 +156,6 @@ private: RenderBoxModelObject* m_continuation; // Can be either a block or an inline. <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as its continuation but the // <b> will just have an inline as its continuation. mutable int m_lineHeight; - mutable int m_verticalPosition; }; inline RenderInline* toRenderInline(RenderObject* object) diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 2f1032f..12360c8 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -3970,8 +3970,15 @@ void showLayerTree(const WebCore::RenderLayer* layer) return; if (WebCore::Frame* frame = layer->renderer()->frame()) { - WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass); + WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState); fprintf(stderr, "%s\n", output.utf8().data()); } } + +void showLayerTree(const WebCore::RenderObject* renderer) +{ + if (!renderer) + return; + showLayerTree(renderer->enclosingLayer()); +} #endif diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h index 060c7c6..27d2b31 100644 --- a/WebCore/rendering/RenderLayer.h +++ b/WebCore/rendering/RenderLayer.h @@ -704,7 +704,8 @@ private: #ifndef NDEBUG // Outside the WebCore namespace for ease of invocation from gdb. -void showLayerTree(const WebCore::RenderLayer* layer); +void showLayerTree(const WebCore::RenderLayer*); +void showLayerTree(const WebCore::RenderObject*); #endif #endif // RenderLayer_h diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 6f8dbc8..517a6d2 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -1152,7 +1152,7 @@ bool RenderLayerBacking::showRepaintCounter() const bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes) { bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity); - bool hasTransform = keyframes.containsProperty(CSSPropertyWebkitTransform); + bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform); if (!hasOpacity && !hasTransform) return false; diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp index 532c551..5717871 100644 --- a/WebCore/rendering/RenderListBox.cpp +++ b/WebCore/rendering/RenderListBox.cpp @@ -238,9 +238,9 @@ void RenderListBox::computeLogicalHeight() } } -int RenderListBox::baselinePosition(bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const +int RenderListBox::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const { - return RenderBox::baselinePosition(firstLine, lineDirection, linePositionMode) - baselineAdjustment; + return RenderBox::baselinePosition(baselineType, firstLine, lineDirection, linePositionMode) - baselineAdjustment; } IntRect RenderListBox::itemBoundingBoxRect(int tx, int ty, int index) diff --git a/WebCore/rendering/RenderListBox.h b/WebCore/rendering/RenderListBox.h index 072fc91..69acb57 100644 --- a/WebCore/rendering/RenderListBox.h +++ b/WebCore/rendering/RenderListBox.h @@ -71,7 +71,7 @@ private: virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); virtual void computePreferredLogicalWidths(); - virtual int baselinePosition(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; virtual void computeLogicalHeight(); virtual void layout(); diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp index 1f600fe..2b64f04 100644 --- a/WebCore/rendering/RenderListItem.cpp +++ b/WebCore/rendering/RenderListItem.cpp @@ -161,7 +161,7 @@ static RenderObject* getParentOfFirstLineBox(RenderBlock* curr, RenderObject* ma if (currChild->isFloating() || currChild->isPositioned()) continue; - if (currChild->isTable() || !currChild->isRenderBlock()) + if (currChild->isTable() || !currChild->isRenderBlock() || (currChild->isBox() && toRenderBox(currChild)->isWritingModeRoot())) break; if (curr->isListItem() && inQuirksMode && currChild->node() && @@ -246,39 +246,39 @@ void RenderListItem::layout() void RenderListItem::positionListMarker() { if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_marker->inlineBoxWrapper()) { - int markerOldX = m_marker->x(); - int yOffset = 0; - int xOffset = 0; + int markerOldLogicalLeft = m_marker->logicalLeft(); + int blockOffset = 0; + int lineOffset = 0; for (RenderBox* o = m_marker->parentBox(); o != this; o = o->parentBox()) { - yOffset += o->y(); - xOffset += o->x(); + blockOffset += o->logicalTop(); + lineOffset += o->logicalLeft(); } bool adjustOverflow = false; - int markerXPos; + int markerLogicalLeft; RootInlineBox* root = m_marker->inlineBoxWrapper()->root(); // FIXME: Inline flows in the line box hierarchy that have self-painting layers should act as cutoff points // and really shouldn't keep propagating overflow up. This won't really break anything other than repainting // not being as tight as it could be though. if (style()->isLeftToRightDirection()) { - int leftLineOffset = logicalLeftOffsetForLine(yOffset, logicalLeftOffsetForLine(yOffset, false), false); - markerXPos = leftLineOffset - xOffset - paddingLeft() - borderLeft() + m_marker->marginLeft(); - m_marker->inlineBoxWrapper()->adjustPosition(markerXPos - markerOldX, 0); + int leftLineOffset = logicalLeftOffsetForLine(blockOffset, logicalLeftOffsetForLine(blockOffset, false), false); + markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - borderStart() + m_marker->marginStart(); + m_marker->inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft); for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { - if (markerXPos < box->leftLayoutOverflow()) { - box->setInlineDirectionOverflowPositions(markerXPos, box->rightLayoutOverflow(), box->leftVisualOverflow(), box->rightVisualOverflow()); + if (markerLogicalLeft < box->logicalLeftLayoutOverflow()) { + box->setInlineDirectionOverflowPositions(markerLogicalLeft, box->logicalRightLayoutOverflow(), box->logicalLeftVisualOverflow(), box->logicalRightVisualOverflow()); if (box == root) adjustOverflow = true; } } } else { - int rightLineOffset = logicalRightOffsetForLine(yOffset, logicalRightOffsetForLine(yOffset, false), false); - markerXPos = rightLineOffset - xOffset + paddingRight() + borderRight() + m_marker->marginLeft(); - m_marker->inlineBoxWrapper()->adjustPosition(markerXPos - markerOldX, 0); + int rightLineOffset = logicalRightOffsetForLine(blockOffset, logicalRightOffsetForLine(blockOffset, false), false); + markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + m_marker->marginEnd(); + m_marker->inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft); for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { - if (markerXPos + m_marker->width() > box->rightLayoutOverflow()) { - box->setInlineDirectionOverflowPositions(box->leftLayoutOverflow(), markerXPos + m_marker->width(), box->leftVisualOverflow(), box->rightVisualOverflow()); + if (markerLogicalLeft + m_marker->logicalWidth() > box->logicalRightLayoutOverflow()) { + box->setInlineDirectionOverflowPositions(box->logicalLeftLayoutOverflow(), markerLogicalLeft + m_marker->logicalWidth(), box->logicalLeftVisualOverflow(), box->logicalRightVisualOverflow()); if (box == root) adjustOverflow = true; } @@ -286,7 +286,9 @@ void RenderListItem::positionListMarker() } if (adjustOverflow) { - IntRect markerRect(markerXPos + xOffset, yOffset, m_marker->width(), m_marker->height()); + IntRect markerRect(markerLogicalLeft + lineOffset, blockOffset, m_marker->width(), m_marker->height()); + if (!style()->isHorizontalWritingMode()) + markerRect = markerRect.transposedRect(); RenderBox* o = m_marker; do { o = o->parentBox(); @@ -300,7 +302,7 @@ void RenderListItem::positionListMarker() void RenderListItem::paint(PaintInfo& paintInfo, int tx, int ty) { - if (!height()) + if (!logicalHeight()) return; RenderBlock::paint(paintInfo, tx, ty); diff --git a/WebCore/rendering/RenderListMarker.cpp b/WebCore/rendering/RenderListMarker.cpp index ab5da61..2f33afb 100644 --- a/WebCore/rendering/RenderListMarker.cpp +++ b/WebCore/rendering/RenderListMarker.cpp @@ -1086,9 +1086,12 @@ IntRect RenderListMarker::localSelectionRect() { InlineBox* box = inlineBoxWrapper(); if (!box) - return IntRect(); - RootInlineBox* root = box->root(); - return IntRect(x(), root->selectionTop() - y(), width(), root->selectionHeight()); + return IntRect(0, 0, width(), height()); + RootInlineBox* root = m_inlineBoxWrapper->root(); + int newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop(); + if (root->block()->style()->isHorizontalWritingMode()) + return IntRect(0, newLogicalTop, width(), root->selectionHeight()); + return IntRect(newLogicalTop, 0, root->selectionHeight(), height()); } void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) @@ -1099,16 +1102,18 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) if (style()->visibility() != VISIBLE) return; - IntRect marker = getRelativeMarkerRect(); - marker.move(tx, ty); - - IntRect box(tx + x(), ty + y(), width(), height()); + IntPoint boxOrigin(tx + x(), ty + y()); + IntRect overflowRect(visibleOverflowRect()); + overflowRect.move(boxOrigin.x(), boxOrigin.y()); + overflowRect.inflate(maximalOutlineSize(paintInfo.phase)); - if (box.y() > paintInfo.rect.bottom() || box.y() + box.height() < paintInfo.rect.y()) + if (!paintInfo.rect.intersects(overflowRect)) return; - if (hasBoxDecorations()) - paintBoxDecorations(paintInfo, box.x(), box.y()); + IntRect box(boxOrigin, IntSize(width(), height())); + + IntRect marker = getRelativeMarkerRect(); + marker.move(boxOrigin.x(), boxOrigin.y()); GraphicsContext* context = paintInfo.context; @@ -1117,10 +1122,10 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled()) paintCustomHighlight(tx, ty, style()->highlight(), true); #endif - context->drawImage(m_image->image(this, marker.size()), style()->colorSpace(), marker.location()); + context->drawImage(m_image->image(this, marker.size()), style()->colorSpace(), marker); if (selectionState() != SelectionNone) { IntRect selRect = localSelectionRect(); - selRect.move(tx, ty); + selRect.move(boxOrigin.x(), boxOrigin.y()); context->fillRect(selRect, selectionBackgroundColor(), style()->colorSpace()); } return; @@ -1134,7 +1139,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) if (selectionState() != SelectionNone) { IntRect selRect = localSelectionRect(); - selRect.move(tx, ty); + selRect.move(boxOrigin.x(), boxOrigin.y()); context->fillRect(selRect, selectionBackgroundColor(), style()->colorSpace()); } @@ -1146,10 +1151,6 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) EListStyleType type = style()->listStyleType(); switch (type) { - case Asterisks: - case Footnotes: - context->drawText(style()->font(), TextRun(m_text), marker.location()); - return; case Disc: context->drawEllipse(marker); return; @@ -1235,6 +1236,8 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) case UpperNorwegian: case UpperRoman: case Urdu: + case Asterisks: + case Footnotes: break; } if (m_text.isEmpty()) @@ -1242,32 +1245,51 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) TextRun textRun(m_text); - // Text is not arbitrary. We can judge whether it's RTL from the first character, - // and we only need to handle the direction RightToLeft for now. - bool textNeedsReversing = direction(m_text[0]) == RightToLeft; - Vector<UChar> reversedText; - if (textNeedsReversing) { - int length = m_text.length(); - reversedText.grow(length); - for (int i = 0; i < length; ++i) - reversedText[length - i - 1] = m_text[i]; - textRun = TextRun(reversedText.data(), length); + if (!style()->isHorizontalWritingMode()) { + marker.move(-boxOrigin.x(), -boxOrigin.y()); + marker = marker.transposedRect(); + marker.move(box.x(), box.y() - logicalHeight()); + context->save(); + context->translate(marker.x(), marker.bottom()); + context->rotate(static_cast<float>(deg2rad(90.))); + context->translate(-marker.x(), -marker.bottom()); } - const Font& font = style()->font(); - const UChar suffix = listMarkerSuffix(type, m_listItem->value()); - if (style()->isLeftToRightDirection()) { - int width = font.width(textRun); - context->drawText(style()->font(), textRun, marker.location()); - UChar suffixSpace[2] = { suffix, ' ' }; - context->drawText(style()->font(), TextRun(suffixSpace, 2), marker.location() + IntSize(width, 0)); - } else { - UChar spaceSuffix[2] = { ' ', suffix }; - TextRun spaceSuffixRun(spaceSuffix, 2); - int width = font.width(spaceSuffixRun); - context->drawText(style()->font(), spaceSuffixRun, marker.location()); - context->drawText(style()->font(), textRun, marker.location() + IntSize(width, 0)); + IntPoint textOrigin = IntPoint(marker.x(), marker.y() + style()->font().ascent()); + + if (type == Asterisks || type == Footnotes) + context->drawText(style()->font(), textRun, textOrigin); + else { + // Text is not arbitrary. We can judge whether it's RTL from the first character, + // and we only need to handle the direction RightToLeft for now. + bool textNeedsReversing = direction(m_text[0]) == RightToLeft; + Vector<UChar> reversedText; + if (textNeedsReversing) { + int length = m_text.length(); + reversedText.grow(length); + for (int i = 0; i < length; ++i) + reversedText[length - i - 1] = m_text[i]; + textRun = TextRun(reversedText.data(), length); + } + + const Font& font = style()->font(); + const UChar suffix = listMarkerSuffix(type, m_listItem->value()); + if (style()->isLeftToRightDirection()) { + int width = font.width(textRun); + context->drawText(style()->font(), textRun, textOrigin); + UChar suffixSpace[2] = { suffix, ' ' }; + context->drawText(style()->font(), TextRun(suffixSpace, 2), textOrigin + IntSize(width, 0)); + } else { + UChar spaceSuffix[2] = { ' ', suffix }; + TextRun spaceSuffixRun(spaceSuffix, 2); + int width = font.width(spaceSuffixRun); + context->drawText(style()->font(), spaceSuffixRun, textOrigin); + context->drawText(style()->font(), textRun, textOrigin + IntSize(width, 0)); + } } + + if (!style()->isHorizontalWritingMode()) + context->restore(); } void RenderListMarker::layout() @@ -1278,18 +1300,19 @@ void RenderListMarker::layout() setWidth(m_image->imageSize(this, style()->effectiveZoom()).width()); setHeight(m_image->imageSize(this, style()->effectiveZoom()).height()); } else { - setWidth(minPreferredLogicalWidth()); - setHeight(style()->font().height()); + setLogicalWidth(minPreferredLogicalWidth()); + setLogicalHeight(style()->font().height()); } - m_marginLeft = m_marginRight = 0; + setMarginStart(0); + setMarginEnd(0); - Length leftMargin = style()->marginLeft(); - Length rightMargin = style()->marginRight(); - if (leftMargin.isFixed()) - m_marginLeft = leftMargin.value(); - if (rightMargin.isFixed()) - m_marginRight = rightMargin.value(); + Length startMargin = style()->marginStart(); + Length endMargin = style()->marginEnd(); + if (startMargin.isFixed()) + setMarginStart(startMargin.value()); + if (endMargin.isFixed()) + setMarginEnd(endMargin.value()); setNeedsLayout(false); } @@ -1319,13 +1342,14 @@ void RenderListMarker::computePreferredLogicalWidths() // until we support the CSS3 marker pseudoclass to allow control over the width and height of the marker box. int bulletWidth = font.ascent() / 2; m_image->setImageContainerSize(IntSize(bulletWidth, bulletWidth)); - m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = m_image->imageSize(this, style()->effectiveZoom()).width(); + IntSize imageSize = m_image->imageSize(this, style()->effectiveZoom()); + m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = style()->isHorizontalWritingMode() ? imageSize.width() : imageSize.height(); setPreferredLogicalWidthsDirty(false); updateMargins(); return; } - int width = 0; + int logicalWidth = 0; EListStyleType type = style()->listStyleType(); switch (type) { case NoneListStyle: @@ -1333,13 +1357,13 @@ void RenderListMarker::computePreferredLogicalWidths() case Asterisks: case Footnotes: m_text = listMarkerText(type, m_listItem->value()); - width = font.width(m_text); // no suffix for these types + logicalWidth = font.width(m_text); // no suffix for these types break; case Circle: case Disc: case Square: m_text = listMarkerText(type, 0); // value is ignored for these types - width = (font.ascent() * 2 / 3 + 1) / 2 + 2; + logicalWidth = (font.ascent() * 2 / 3 + 1) / 2 + 2; break; case Afar: case Amharic: @@ -1416,18 +1440,18 @@ void RenderListMarker::computePreferredLogicalWidths() case Urdu: m_text = listMarkerText(type, m_listItem->value()); if (m_text.isEmpty()) - width = 0; + logicalWidth = 0; else { int itemWidth = font.width(m_text); UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' }; int suffixSpaceWidth = font.width(TextRun(suffixSpace, 2)); - width = itemWidth + suffixSpaceWidth; + logicalWidth = itemWidth + suffixSpaceWidth; } break; } - m_minPreferredLogicalWidth = width; - m_maxPreferredLogicalWidth = width; + m_minPreferredLogicalWidth = logicalWidth; + m_maxPreferredLogicalWidth = logicalWidth; setPreferredLogicalWidthsDirty(false); @@ -1438,26 +1462,18 @@ void RenderListMarker::updateMargins() { const Font& font = style()->font(); - int marginLeft = 0; - int marginRight = 0; + int marginStart = 0; + int marginEnd = 0; if (isInside()) { - if (isImage()) { - if (style()->isLeftToRightDirection()) - marginRight = cMarkerPadding; - else - marginLeft = cMarkerPadding; - } else switch (style()->listStyleType()) { + if (isImage()) + marginEnd = cMarkerPadding; + else switch (style()->listStyleType()) { case Disc: case Circle: case Square: - if (style()->isLeftToRightDirection()) { - marginLeft = -1; - marginRight = font.ascent() - minPreferredLogicalWidth() + 1; - } else { - marginLeft = font.ascent() - minPreferredLogicalWidth() + 1; - marginRight = -1; - } + marginStart = -1; + marginEnd = font.ascent() - minPreferredLogicalWidth() + 1; break; default: break; @@ -1465,44 +1481,46 @@ void RenderListMarker::updateMargins() } else { if (style()->isLeftToRightDirection()) { if (isImage()) - marginLeft = -minPreferredLogicalWidth() - cMarkerPadding; + marginStart = -minPreferredLogicalWidth() - cMarkerPadding; else { int offset = font.ascent() * 2 / 3; switch (style()->listStyleType()) { case Disc: case Circle: case Square: - marginLeft = -offset - cMarkerPadding - 1; + marginStart = -offset - cMarkerPadding - 1; break; case NoneListStyle: break; default: - marginLeft = m_text.isEmpty() ? 0 : -minPreferredLogicalWidth() - offset / 2; + marginStart = m_text.isEmpty() ? 0 : -minPreferredLogicalWidth() - offset / 2; } } + marginEnd = -marginStart - minPreferredLogicalWidth(); } else { if (isImage()) - marginLeft = cMarkerPadding; + marginEnd = cMarkerPadding; else { int offset = font.ascent() * 2 / 3; switch (style()->listStyleType()) { case Disc: case Circle: case Square: - marginLeft = offset + cMarkerPadding + 1 - minPreferredLogicalWidth(); + marginEnd = offset + cMarkerPadding + 1 - minPreferredLogicalWidth(); break; case NoneListStyle: break; default: - marginLeft = m_text.isEmpty() ? 0 : offset / 2; + marginEnd = m_text.isEmpty() ? 0 : offset / 2; } } + marginStart = -marginEnd - minPreferredLogicalWidth(); } - marginRight = -marginLeft - minPreferredLogicalWidth(); + } - style()->setMarginLeft(Length(marginLeft, Fixed)); - style()->setMarginRight(Length(marginRight, Fixed)); + style()->setMarginStart(Length(marginStart, Fixed)); + style()->setMarginEnd(Length(marginEnd, Fixed)); } int RenderListMarker::lineHeight(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const @@ -1512,11 +1530,11 @@ int RenderListMarker::lineHeight(bool firstLine, LineDirectionMode direction, Li return RenderBox::lineHeight(firstLine, direction, linePositionMode); } -int RenderListMarker::baselinePosition(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +int RenderListMarker::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const { if (!isImage()) - return m_listItem->baselinePosition(firstLine, direction, PositionOfInteriorLineBoxes); - return RenderBox::baselinePosition(firstLine, direction, linePositionMode); + return m_listItem->baselinePosition(baselineType, firstLine, direction, PositionOfInteriorLineBoxes); + return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode); } String RenderListMarker::suffix() const @@ -1546,14 +1564,16 @@ bool RenderListMarker::isInside() const IntRect RenderListMarker::getRelativeMarkerRect() { if (isImage()) - return IntRect(x(), y(), m_image->imageSize(this, style()->effectiveZoom()).width(), m_image->imageSize(this, style()->effectiveZoom()).height()); - + return IntRect(0, 0, m_image->imageSize(this, style()->effectiveZoom()).width(), m_image->imageSize(this, style()->effectiveZoom()).height()); + + IntRect relativeRect; EListStyleType type = style()->listStyleType(); switch (type) { case Asterisks: case Footnotes: { const Font& font = style()->font(); - return IntRect(x(), y() + font.ascent(), font.width(m_text), font.height()); + relativeRect = IntRect(0, 0, font.width(m_text), font.height()); + break; } case Disc: case Circle: @@ -1562,7 +1582,8 @@ IntRect RenderListMarker::getRelativeMarkerRect() const Font& font = style()->font(); int ascent = font.ascent(); int bulletWidth = (ascent * 2 / 3 + 1) / 2; - return IntRect(x() + 1, y() + 3 * (ascent - ascent * 2 / 3) / 2, bulletWidth, bulletWidth); + relativeRect = IntRect(1, 3 * (ascent - ascent * 2 / 3) / 2, bulletWidth, bulletWidth); + break; } case NoneListStyle: return IntRect(); @@ -1645,10 +1666,15 @@ IntRect RenderListMarker::getRelativeMarkerRect() int itemWidth = font.width(m_text); UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' }; int suffixSpaceWidth = font.width(TextRun(suffixSpace, 2)); - return IntRect(x(), y() + font.ascent(), itemWidth + suffixSpaceWidth, font.height()); + relativeRect = IntRect(0, 0, itemWidth + suffixSpaceWidth, font.height()); + } + + if (!style()->isHorizontalWritingMode()) { + relativeRect = relativeRect.transposedRect(); + relativeRect.setX(width() - relativeRect.x() - relativeRect.width()); } - return IntRect(); + return relativeRect; } void RenderListMarker::setSelectionState(SelectionState state) diff --git a/WebCore/rendering/RenderListMarker.h b/WebCore/rendering/RenderListMarker.h index fe025c3..d23e674 100644 --- a/WebCore/rendering/RenderListMarker.h +++ b/WebCore/rendering/RenderListMarker.h @@ -59,7 +59,7 @@ private: virtual InlineBox* createInlineBox(); virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; - virtual int baselinePosition(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; bool isImage() const; bool isText() const { return !isImage(); } diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp index a88903f..5ad661f 100644 --- a/WebCore/rendering/RenderMenuList.cpp +++ b/WebCore/rendering/RenderMenuList.cpp @@ -419,7 +419,7 @@ PopupMenuStyle RenderMenuList::itemStyle(unsigned listIndex) const Element* element = listItems[listIndex]; RenderStyle* style = element->renderStyle() ? element->renderStyle() : element->computedStyle(); - return style ? PopupMenuStyle(style->visitedDependentColor(CSSPropertyColor), itemBackgroundColor(listIndex), style->font(), style->visibility() == VISIBLE, style->textIndent(), style->direction()) : menuStyle(); + return style ? PopupMenuStyle(style->visitedDependentColor(CSSPropertyColor), itemBackgroundColor(listIndex), style->font(), style->visibility() == VISIBLE, style->display() == NONE, style->textIndent(), style->direction()) : menuStyle(); } Color RenderMenuList::itemBackgroundColor(unsigned listIndex) const @@ -449,7 +449,7 @@ Color RenderMenuList::itemBackgroundColor(unsigned listIndex) const PopupMenuStyle RenderMenuList::menuStyle() const { RenderStyle* s = m_innerBlock ? m_innerBlock->style() : style(); - return PopupMenuStyle(s->visitedDependentColor(CSSPropertyColor), s->visitedDependentColor(CSSPropertyBackgroundColor), s->font(), s->visibility() == VISIBLE, s->textIndent(), s->direction()); + return PopupMenuStyle(s->visitedDependentColor(CSSPropertyColor), s->visitedDependentColor(CSSPropertyBackgroundColor), s->font(), s->visibility() == VISIBLE, s->display() == NONE, s->textIndent(), s->direction()); } HostWindow* RenderMenuList::hostWindow() const diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h index 7faa372..2c99b1e 100644 --- a/WebCore/rendering/RenderMenuList.h +++ b/WebCore/rendering/RenderMenuList.h @@ -137,7 +137,7 @@ private: }; inline RenderMenuList* toRenderMenuList(RenderObject* object) -{ +{ ASSERT(!object || object->isMenuList()); return static_cast<RenderMenuList*>(object); } diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index b04d455..503b0a3 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -120,7 +120,6 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) return image; } -#if ENABLE(RUBY) if (node->hasTagName(rubyTag)) { if (style->display() == INLINE) return new (arena) RenderRubyAsInline(node); @@ -130,7 +129,6 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) // treat <rt> as ruby text ONLY if it still has its default treatment of block if (node->hasTagName(rtTag) && style->display() == BLOCK) return new (arena) RenderRubyText(node); -#endif switch (style->display()) { case NONE: @@ -260,6 +258,15 @@ bool RenderObject::isHR() const return node() && node()->hasTagName(hrTag); } +bool RenderObject::isLegend() const +{ + return node() && (node()->hasTagName(legendTag) +#if ENABLE(WML) + || node()->hasTagName(WMLNames::insertedLegendTag) +#endif + ); +} + bool RenderObject::isHTMLMarquee() const { return node() && node()->renderer() == this && node()->hasTagName(marqueeTag); diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index 9c29ce1..bfc62fe 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -266,12 +266,12 @@ public: virtual bool isRenderPart() const { return false; } virtual bool isRenderView() const { return false; } virtual bool isReplica() const { return false; } -#if ENABLE(RUBY) + virtual bool isRuby() const { return false; } virtual bool isRubyBase() const { return false; } virtual bool isRubyRun() const { return false; } virtual bool isRubyText() const { return false; } -#endif + virtual bool isSlider() const { return false; } virtual bool isTable() const { return false; } virtual bool isTableCell() const { return false; } @@ -288,6 +288,7 @@ public: bool isRoot() const { return document()->documentElement() == m_node; } bool isBody() const; bool isHR() const; + bool isLegend() const; bool isHTMLMarquee() const; @@ -314,6 +315,7 @@ public: // to add SVG renderer methods to RenderObject with an ASSERT_NOT_REACHED() default implementation. virtual bool isSVGRoot() const { return false; } virtual bool isSVGContainer() const { return false; } + virtual bool isSVGViewportContainer() const { return false; } virtual bool isSVGGradientStop() const { return false; } virtual bool isSVGHiddenContainer() const { return false; } virtual bool isSVGPath() const { return false; } diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp index a087038..b1a7711 100644 --- a/WebCore/rendering/RenderReplaced.cpp +++ b/WebCore/rendering/RenderReplaced.cpp @@ -284,17 +284,20 @@ VisiblePosition RenderReplaced::positionForPoint(const IntPoint& point) RootInlineBox* root = box->root(); - int top = root->lineTop(); - int bottom = root->nextRootBox() ? root->nextRootBox()->lineTop() : root->lineBottom(); + int top = root->selectionTop(); + int bottom = root->selectionBottom(); - if (point.y() + y() < top) + int blockDirectionPosition = box->isHorizontal() ? point.y() + y() : point.x() + x(); + int lineDirectionPosition = box->isHorizontal() ? point.x() + x() : point.y() + y(); + + if (blockDirectionPosition < top) return createVisiblePosition(caretMinOffset(), DOWNSTREAM); // coordinates are above - if (point.y() + y() >= bottom) + if (blockDirectionPosition >= bottom) return createVisiblePosition(caretMaxOffset(), DOWNSTREAM); // coordinates are below if (node()) { - if (point.x() <= width() / 2) + if (lineDirectionPosition <= box->logicalLeft() + (box->logicalWidth() / 2)) return createVisiblePosition(0, DOWNSTREAM); return createVisiblePosition(1, DOWNSTREAM); } @@ -326,25 +329,22 @@ IntRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const if (!m_inlineBoxWrapper) // We're a block-level replaced element. Just return our own dimensions. return IntRect(0, 0, width(), height()); - - RenderBlock* cb = containingBlock(); - if (!cb) - return IntRect(); RootInlineBox* root = m_inlineBoxWrapper->root(); - return IntRect(0, root->selectionTop() - y(), width(), root->selectionHeight()); + int newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop(); + if (root->block()->style()->isHorizontalWritingMode()) + return IntRect(0, newLogicalTop, width(), root->selectionHeight()); + return IntRect(newLogicalTop, 0, root->selectionHeight(), height()); } void RenderReplaced::setSelectionState(SelectionState s) { - RenderBox::setSelectionState(s); + RenderBox::setSelectionState(s); // The selection state for our containing block hierarchy is updated by the base class call. if (m_inlineBoxWrapper) { RootInlineBox* line = m_inlineBoxWrapper->root(); if (line) line->setHasSelectedChildren(isSelected()); } - - containingBlock()->setSelectionState(s); } bool RenderReplaced::isSelected() const diff --git a/WebCore/rendering/RenderReplaced.h b/WebCore/rendering/RenderReplaced.h index fbc5151..d6ebba6 100644 --- a/WebCore/rendering/RenderReplaced.h +++ b/WebCore/rendering/RenderReplaced.h @@ -53,7 +53,7 @@ protected: virtual void paint(PaintInfo&, int tx, int ty); bool shouldPaint(PaintInfo&, int& tx, int& ty); - IntRect localSelectionRect(bool checkWhetherSelected = true) const; + IntRect localSelectionRect(bool checkWhetherSelected = true) const; // This is in local coordinates, but it's a physical rect (so the top left corner is physical top left). private: virtual const char* renderName() const { return "RenderReplaced"; } diff --git a/WebCore/rendering/RenderRuby.cpp b/WebCore/rendering/RenderRuby.cpp index 7e19a79..1c5cfaf 100644 --- a/WebCore/rendering/RenderRuby.cpp +++ b/WebCore/rendering/RenderRuby.cpp @@ -30,7 +30,6 @@ #include "config.h" -#if ENABLE(RUBY) #include "RenderRuby.h" #include "RenderRubyRun.h" @@ -203,5 +202,3 @@ void RenderRubyAsBlock::removeChild(RenderObject* child) } } // namespace WebCore - -#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRuby.h b/WebCore/rendering/RenderRuby.h index a5dafe9..49a84d8 100644 --- a/WebCore/rendering/RenderRuby.h +++ b/WebCore/rendering/RenderRuby.h @@ -31,8 +31,6 @@ #ifndef RenderRuby_h #define RenderRuby_h -#if ENABLE(RUBY) - #include "RenderBlock.h" #include "RenderInline.h" @@ -86,6 +84,4 @@ private: } // namespace WebCore -#endif - #endif // RenderRuby_h diff --git a/WebCore/rendering/RenderRubyBase.cpp b/WebCore/rendering/RenderRubyBase.cpp index 967a054..83399a1 100644 --- a/WebCore/rendering/RenderRubyBase.cpp +++ b/WebCore/rendering/RenderRubyBase.cpp @@ -30,7 +30,6 @@ #include "config.h" -#if ENABLE(RUBY) #include "RenderRubyBase.h" namespace WebCore { @@ -184,5 +183,3 @@ void RenderRubyBase::mergeBlockChildren(RenderRubyBase* toBase, RenderObject* fr } } // namespace WebCore - -#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRubyBase.h b/WebCore/rendering/RenderRubyBase.h index 29c4858..c029bd5 100644 --- a/WebCore/rendering/RenderRubyBase.h +++ b/WebCore/rendering/RenderRubyBase.h @@ -31,8 +31,6 @@ #ifndef RenderRubyBase_h #define RenderRubyBase_h -#if ENABLE(RUBY) - #include "RenderBlock.h" namespace WebCore { @@ -62,6 +60,4 @@ private: } // namespace WebCore -#endif - #endif // RenderRubyBase_h diff --git a/WebCore/rendering/RenderRubyRun.cpp b/WebCore/rendering/RenderRubyRun.cpp index d48646b..a83a3e2 100644 --- a/WebCore/rendering/RenderRubyRun.cpp +++ b/WebCore/rendering/RenderRubyRun.cpp @@ -30,7 +30,6 @@ #include "config.h" -#if ENABLE(RUBY) #include "RenderRubyRun.h" #include "RenderRubyBase.h" @@ -221,10 +220,17 @@ RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(parentRuby->style()); newStyle->setDisplay(INLINE_BLOCK); + if (parentRuby->style()->isFlippedLinesWritingMode()) { + // Ruby text is always in the line direction, so invert our block flow relative to the parent to + // ensure that the Ruby ends up on the correct side. + if (parentRuby->style()->isHorizontalWritingMode()) + newStyle->setWritingMode(TopToBottomWritingMode); + else + newStyle->setWritingMode(RightToLeftWritingMode); + } + rr->setStyle(newStyle.release()); return rr; } } // namespace WebCore - -#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRubyRun.h b/WebCore/rendering/RenderRubyRun.h index acf359b..222ddb6 100644 --- a/WebCore/rendering/RenderRubyRun.h +++ b/WebCore/rendering/RenderRubyRun.h @@ -31,8 +31,6 @@ #ifndef RenderRubyRun_h #define RenderRubyRun_h -#if ENABLE(RUBY) - #include "RenderBlock.h" namespace WebCore { @@ -80,6 +78,4 @@ private: } // namespace WebCore -#endif - #endif // RenderRubyRun_h diff --git a/WebCore/rendering/RenderRubyText.cpp b/WebCore/rendering/RenderRubyText.cpp index 12e8fea..14cf7fc 100644 --- a/WebCore/rendering/RenderRubyText.cpp +++ b/WebCore/rendering/RenderRubyText.cpp @@ -30,7 +30,6 @@ #include "config.h" -#if ENABLE(RUBY) #include "RenderRubyText.h" namespace WebCore { @@ -50,5 +49,3 @@ bool RenderRubyText::isChildAllowed(RenderObject* child, RenderStyle*) const } } // namespace WebCore - -#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRubyText.h b/WebCore/rendering/RenderRubyText.h index 865d179..e475914 100644 --- a/WebCore/rendering/RenderRubyText.h +++ b/WebCore/rendering/RenderRubyText.h @@ -31,8 +31,6 @@ #ifndef RenderRubyText_h #define RenderRubyText_h -#if ENABLE(RUBY) - #include "RenderBlock.h" namespace WebCore { @@ -51,6 +49,4 @@ public: } // namespace WebCore -#endif - #endif // RenderRubyText_h diff --git a/WebCore/rendering/RenderSVGGradientStop.cpp b/WebCore/rendering/RenderSVGGradientStop.cpp index a5e5808..094fc7f 100644 --- a/WebCore/rendering/RenderSVGGradientStop.cpp +++ b/WebCore/rendering/RenderSVGGradientStop.cpp @@ -72,7 +72,7 @@ void RenderSVGGradientStop::layout() SVGGradientElement* RenderSVGGradientStop::gradientElement() const { - ContainerNode* parentNode = node()->parent(); + ContainerNode* parentNode = node()->parentNode(); if (parentNode->hasTagName(linearGradientTag) || parentNode->hasTagName(radialGradientTag)) return static_cast<SVGGradientElement*>(parentNode); return 0; diff --git a/WebCore/rendering/RenderSVGViewportContainer.h b/WebCore/rendering/RenderSVGViewportContainer.h index 63c336c..5373ca8 100644 --- a/WebCore/rendering/RenderSVGViewportContainer.h +++ b/WebCore/rendering/RenderSVGViewportContainer.h @@ -36,6 +36,7 @@ public: private: virtual bool isSVGContainer() const { return true; } + virtual bool isSVGViewportContainer() const { return true; } virtual const char* renderName() const { return "RenderSVGViewportContainer"; } AffineTransform viewportTransform() const; diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index 35d72f4..d680bc7 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -159,8 +159,9 @@ RenderSlider::~RenderSlider() m_thumb->detach(); } -int RenderSlider::baselinePosition(bool /*firstLine*/, LineDirectionMode, LinePositionMode) const +int RenderSlider::baselinePosition(FontBaseline, bool /*firstLine*/, LineDirectionMode, LinePositionMode) const { + // FIXME: Patch this function for writing-mode. return height() + marginTop(); } @@ -285,7 +286,7 @@ void RenderSlider::layout() if (oldSize != size()) thumb->setChildNeedsLayout(true, false); - LayoutStateMaintainer statePusher(view(), this, size()); + LayoutStateMaintainer statePusher(view(), this, size(), style()->isFlippedBlocksWritingMode()); IntRect oldThumbRect = thumb->frameRect(); diff --git a/WebCore/rendering/RenderSlider.h b/WebCore/rendering/RenderSlider.h index fa743de..03779a3 100644 --- a/WebCore/rendering/RenderSlider.h +++ b/WebCore/rendering/RenderSlider.h @@ -42,7 +42,7 @@ namespace WebCore { virtual const char* renderName() const { return "RenderSlider"; } virtual bool isSlider() const { return true; } - virtual int baselinePosition(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; virtual void computePreferredLogicalWidths(); virtual void layout(); virtual void updateFromElement(); diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index d158284..de10680 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -268,7 +268,7 @@ void RenderTable::layout() recalcSectionsIfNeeded(); LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); - LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y())); + LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), style()->isFlippedBlocksWritingMode()); setLogicalHeight(0); m_overflow.clear(); @@ -1211,10 +1211,12 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu // Check kids first. if (!hasOverflowClip() || overflowClipRect(tx, ty).intersects(result.rectForPoint(xPos, yPos))) { for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { - if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption) && - child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) { - updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); - return true; + if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption)) { + IntPoint childPoint = flipForWritingMode(toRenderBox(child), IntPoint(tx, ty), ParentToChildFlippingAdjustment); + if (child->nodeAtPoint(request, result, xPos, yPos, childPoint.x(), childPoint.y(), action)) { + updateHitTestResult(result, IntPoint(xPos - childPoint.x(), yPos - childPoint.y())); + return true; + } } } } @@ -1222,7 +1224,7 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu // Check our bounds next. IntRect boundsRect = IntRect(tx, ty, width(), height()); if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && boundsRect.intersects(result.rectForPoint(xPos, yPos))) { - updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); + updateHitTestResult(result, flipForWritingMode(IntPoint(xPos - tx, yPos - ty))); if (!result.addNodeToRectBasedTestResult(node(), xPos, yPos, boundsRect)) return true; } diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index 3ba185a..801a362 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -299,19 +299,15 @@ void RenderTableCell::computeRectForRepaint(RenderBoxModelObject* repaintContain RenderBlock::computeRectForRepaint(repaintContainer, r, fixed); } -int RenderTableCell::baselinePosition(bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const +int RenderTableCell::baselinePosition() const { - // FIXME: This function still needs to be patched for writing-mode. - if (linePositionMode == PositionOfInteriorLineBoxes) - return RenderBlock::baselinePosition(firstLine, lineDirection, linePositionMode); - // <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>: The baseline of a cell is the baseline of // the first in-flow line box in the cell, or the first in-flow table-row in the cell, whichever comes first. If there // is no such line box or table-row, the baseline is the bottom of content edge of the cell box. int firstLineBaseline = firstLineBoxBaseline(); if (firstLineBaseline != -1) return firstLineBaseline; - return paddingTop() + borderTop() + contentHeight(); + return paddingBefore() + borderBefore() + contentLogicalHeight(); } void RenderTableCell::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h index 15e6bab..281c226 100644 --- a/WebCore/rendering/RenderTableCell.h +++ b/WebCore/rendering/RenderTableCell.h @@ -98,7 +98,7 @@ public: void paintBackgroundsBehindCell(PaintInfo&, int tx, int ty, RenderObject* backgroundObject); - virtual int baselinePosition(bool firstLine = false, LineDirectionMode = HorizontalLine, LinePositionMode = PositionOnContainingLine) const; + int baselinePosition() const; void setIntrinsicPaddingBefore(int p) { m_intrinsicPaddingBefore = p; } void setIntrinsicPaddingAfter(int p) { m_intrinsicPaddingAfter = p; } diff --git a/WebCore/rendering/RenderTableRow.cpp b/WebCore/rendering/RenderTableRow.cpp index 2166ef2..98544a6 100644 --- a/WebCore/rendering/RenderTableRow.cpp +++ b/WebCore/rendering/RenderTableRow.cpp @@ -115,7 +115,7 @@ void RenderTableRow::layout() ASSERT(needsLayout()); // Table rows do not add translation. - LayoutStateMaintainer statePusher(view(), this, IntSize()); + LayoutStateMaintainer statePusher(view(), this, IntSize(), style()->isFlippedBlocksWritingMode()); bool paginated = view()->layoutState()->isPaginated(); @@ -175,9 +175,12 @@ bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& r // at the moment (a demoted inline <form> for example). If we ever implement a // table-specific hit-test method (which we should do for performance reasons anyway), // then we can remove this check. - if (child->isTableCell() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) { - updateHitTestResult(result, IntPoint(x - tx, y - ty)); - return true; + if (child->isTableCell() && !toRenderBox(child)->hasSelfPaintingLayer()) { + IntPoint cellPoint = flipForWritingMode(toRenderTableCell(child), IntPoint(tx, ty), ParentToChildFlippingAdjustment); + if (child->nodeAtPoint(request, result, x, y, cellPoint.x(), cellPoint.y(), action)) { + updateHitTestResult(result, IntPoint(x - cellPoint.x(), y - cellPoint.y())); + return true; + } } } diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index e07461f..30620d2 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -430,7 +430,7 @@ void RenderTableSection::layout() { ASSERT(needsLayout()); - LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y())); + LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), style()->isFlippedBlocksWritingMode()); for (RenderObject* child = children()->firstChild(); child; child = child->nextSibling()) { if (child->isTableRow()) { child->layoutIfNeeded(); @@ -571,7 +571,7 @@ int RenderTableSection::layoutRows(int toAdd) int vspacing = table()->vBorderSpacing(); int nEffCols = table()->numEffCols(); - LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y())); + LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), style()->isFlippedBlocksWritingMode()); for (int r = 0; r < totalRows; r++) { // Set the row's x/y position and width/height. @@ -1327,36 +1327,44 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul // at the moment (a demoted inline <form> for example). If we ever implement a // table-specific hit-test method (which we should do for performance reasons anyway), // then we can remove this check. - if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) { - updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); - return true; + if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer()) { + IntPoint childPoint = flipForWritingMode(toRenderBox(child), IntPoint(tx, ty), ParentToChildFlippingAdjustment); + if (child->nodeAtPoint(request, result, xPos, yPos, childPoint.x(), childPoint.y(), action)) { + updateHitTestResult(result, IntPoint(xPos - childPoint.x(), yPos - childPoint.y())); + return true; + } } } return false; } - int relativeY = yPos - ty; - // leftrow corresponds to the first row that starts after the y mouse position - unsigned leftrow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), relativeY) - m_rowPos.begin(); - if (leftrow == m_rowPos.size()) + IntPoint location = IntPoint(xPos - tx, yPos - ty); + if (style()->isFlippedBlocksWritingMode()) { + if (style()->isHorizontalWritingMode()) + location.setY(height() - location.y()); + else + location.setX(width() - location.x()); + } + + int offsetInColumnDirection = style()->isHorizontalWritingMode() ? location.y() : location.x(); + // Find the first row that starts after offsetInColumnDirection. + unsigned nextRow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), offsetInColumnDirection) - m_rowPos.begin(); + if (nextRow == m_rowPos.size()) return false; - // Grab the last row that starts before the y mouse position. - if (leftrow > 0) - --leftrow; + // Now set hitRow to the index of the hit row, or 0. + unsigned hitRow = nextRow > 0 ? nextRow - 1 : 0; Vector<int>& columnPos = table()->columnPositions(); - bool rtl = !style()->isLeftToRightDirection(); - int relativeX = xPos - tx; - if (rtl) - relativeX = columnPos[columnPos.size() - 1] - relativeX; + int offsetInRowDirection = style()->isHorizontalWritingMode() ? location.x() : location.y(); + if (!style()->isLeftToRightDirection()) + offsetInRowDirection = columnPos[columnPos.size() - 1] - offsetInRowDirection; - unsigned leftcol = std::lower_bound(columnPos.begin(), columnPos.end(), relativeX) - columnPos.begin(); - if (leftcol == columnPos.size()) + unsigned nextColumn = std::lower_bound(columnPos.begin(), columnPos.end(), offsetInRowDirection) - columnPos.begin(); + if (nextColumn == columnPos.size()) return false; - if (leftcol > 0) - --leftcol; + unsigned hitColumn = nextColumn > 0 ? nextColumn - 1 : 0; - CellStruct& current = cellAt(leftrow, leftcol); + CellStruct& current = cellAt(hitRow, hitColumn); // If the cell is empty, there's nothing to do if (!current.hasCells()) @@ -1364,8 +1372,9 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul for (int i = current.cells.size() - 1; i >= 0; --i) { RenderTableCell* cell = current.cells[i]; - if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) { - updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); + IntPoint cellPoint = flipForWritingMode(cell, IntPoint(tx, ty), ParentToChildFlippingAdjustment); + if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, xPos, yPos, cellPoint.x(), cellPoint.y(), action)) { + updateHitTestResult(result, IntPoint(xPos - cellPoint.x(), yPos - cellPoint.y())); return true; } } diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index aa362b3..7635d07 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -59,6 +59,9 @@ static void makeCapitalized(String* string, UChar previous) unsigned length = string->length(); const UChar* characters = string->characters(); + if (length >= numeric_limits<unsigned>::max()) + CRASH(); + StringBuffer stringWithPrevious(length + 1); stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous; for (unsigned i = 1; i < length + 1; i++) { @@ -422,13 +425,13 @@ VisiblePosition RenderText::positionForPoint(const IntPoint& point) int pointBlockDirection = firstTextBox()->isHorizontal() ? point.y() : point.x(); // FIXME: We should be able to roll these special cases into the general cases in the loop below. - if (firstTextBox() && pointBlockDirection < firstTextBox()->root()->lineBottom() && pointLineDirection < firstTextBox()->logicalLeft()) { + if (firstTextBox() && pointBlockDirection < firstTextBox()->root()->selectionBottom() && pointLineDirection < firstTextBox()->logicalLeft()) { // at the y coordinate of the first line or above // and the x coordinate is to the left of the first text box left edge offset = firstTextBox()->offsetForPosition(pointLineDirection); return createVisiblePosition(offset + firstTextBox()->start(), DOWNSTREAM); } - if (lastTextBox() && pointBlockDirection >= lastTextBox()->root()->lineTop() && pointLineDirection >= lastTextBox()->logicalRight()) { + if (lastTextBox() && pointBlockDirection >= lastTextBox()->root()->selectionTop() && pointLineDirection >= lastTextBox()->logicalRight()) { // at the y coordinate of the last line or below // and the x coordinate is to the right of the last text box right edge offset = lastTextBox()->offsetForPosition(pointLineDirection); @@ -437,8 +440,11 @@ VisiblePosition RenderText::positionForPoint(const IntPoint& point) InlineTextBox* lastBoxAbove = 0; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { - if (pointBlockDirection >= box->root()->lineTop()) { - int bottom = box->root()->nextRootBox() ? box->root()->nextRootBox()->lineTop() : box->root()->lineBottom(); + RootInlineBox* rootBox = box->root(); + if (pointBlockDirection >= rootBox->selectionTop()) { + int bottom = rootBox->selectionBottom(); + if (rootBox->nextRootBox()) + bottom = min(bottom, rootBox->nextRootBox()->lineTop()); if (pointBlockDirection < bottom) { offset = box->offsetForPosition(pointLineDirection); @@ -481,8 +487,8 @@ IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* e InlineTextBox* box = static_cast<InlineTextBox*>(inlineBox); - int height = box->root()->lineBottom() - box->root()->lineTop(); - int top = box->root()->lineTop(); + int height = box->root()->selectionHeight(); + int top = box->root()->selectionTop(); int left = box->positionForOffset(caretOffset); diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index e81dfb9..9b9e51a 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -30,6 +30,7 @@ #include "Frame.h" #include "HTMLBRElement.h" #include "HTMLFormControlElement.h" +#include "HTMLInputElement.h" #include "HTMLNames.h" #include "HitTestResult.h" #include "RenderLayer.h" @@ -256,6 +257,22 @@ void setSelectionRange(Node* node, int start, int end) frame->selection()->setSelection(newSelection); } +bool RenderTextControl::isSelectableElement(Node* node) const +{ + if (!node || !m_innerText) + return false; + + if (node->rootEditableElement() == m_innerText) + return true; + + if (!m_innerText->contains(node)) + return false; + + Node* shadowAncestor = node->shadowAncestorNode(); + return shadowAncestor && (shadowAncestor->hasTagName(textareaTag) + || (shadowAncestor->hasTagName(inputTag) && static_cast<HTMLInputElement*>(shadowAncestor)->isTextField())); +} + PassRefPtr<Range> RenderTextControl::selection(int start, int end) const { if (!m_innerText) @@ -284,7 +301,7 @@ VisiblePosition RenderTextControl::visiblePositionForIndex(int index) const int RenderTextControl::indexForVisiblePosition(const VisiblePosition& pos) const { Position indexPosition = pos.deepEquivalent(); - if (!indexPosition.node() || indexPosition.node()->rootEditableElement() != m_innerText) + if (!isSelectableElement(indexPosition.node())) return 0; ExceptionCode ec = 0; RefPtr<Range> range = Range::create(document()); @@ -561,14 +578,52 @@ void RenderTextControl::updatePlaceholderVisibility(bool placeholderShouldBeVisi { bool oldPlaceholderVisible = m_placeholderVisible; m_placeholderVisible = placeholderShouldBeVisible; - if (oldPlaceholderVisible != m_placeholderVisible || placeholderValueChanged) { - // Sets the inner text style to the normal style or :placeholder style. - setInnerTextStyle(createInnerTextStyle(textBaseStyle())); + if (oldPlaceholderVisible != m_placeholderVisible || placeholderValueChanged) + repaint(); +} - // updateFromElement() of the subclasses updates the text content - // to the element's value(), placeholder(), or the empty string. - updateFromElement(); +void RenderTextControl::paintPlaceholder(PaintInfo& paintInfo, int tx, int ty) +{ + if (style()->visibility() != VISIBLE) + return; + + IntRect clipRect(tx + borderLeft(), ty + borderTop(), width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop()); + if (clipRect.isEmpty()) + return; + + paintInfo.context->save(); + + paintInfo.context->clip(clipRect); + + RefPtr<RenderStyle> placeholderStyle = getCachedPseudoStyle(INPUT_PLACEHOLDER); + if (!placeholderStyle) + placeholderStyle = style(); + + paintInfo.context->setFillColor(placeholderStyle->visitedDependentColor(CSSPropertyColor), placeholderStyle->colorSpace()); + + String placeholderText = static_cast<HTMLTextFormControlElement*>(node())->strippedPlaceholder(); + TextRun textRun(placeholderText.characters(), placeholderText.length(), 0, 0, 0, !placeholderStyle->isLeftToRightDirection(), placeholderStyle->unicodeBidi() == Override, false, false); + + RenderBox* textRenderer = innerTextElement() ? innerTextElement()->renderBox() : 0; + if (textRenderer) { + IntPoint textPoint; + textPoint.setY(ty + borderTop() + paddingTop() + textRenderer->paddingTop() + placeholderStyle->font().ascent()); + if (placeholderStyle->isLeftToRightDirection()) + textPoint.setX(tx + textBlockInsetLeft()); + else + textPoint.setX(tx + width() - textBlockInsetRight() - style()->font().width(textRun)); + + paintInfo.context->drawBidiText(placeholderStyle->font(), textRun, textPoint); } + paintInfo.context->restore(); +} + +void RenderTextControl::paintObject(PaintInfo& paintInfo, int tx, int ty) +{ + if (m_placeholderVisible && paintInfo.phase == PaintPhaseForeground) + paintPlaceholder(paintInfo, tx, ty); + + RenderBlock::paintObject(paintInfo, tx, ty); } } // namespace WebCore diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h index 0060973..4b1d6e3 100644 --- a/WebCore/rendering/RenderTextControl.h +++ b/WebCore/rendering/RenderTextControl.h @@ -96,6 +96,7 @@ private: virtual bool canHaveChildren() const { return false; } virtual bool avoidsFloats() const { return true; } void setInnerTextStyle(PassRefPtr<RenderStyle>); + virtual void paintObject(PaintInfo&, int tx, int ty); virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); @@ -107,6 +108,12 @@ private: bool hasVisibleTextArea() const; friend void setSelectionRange(Node*, int start, int end); + bool isSelectableElement(Node*) const; + + virtual int textBlockInsetLeft() const = 0; + virtual int textBlockInsetRight() const = 0; + + void paintPlaceholder(PaintInfo&, int tx, int ty); bool m_wasChangedSinceLastChangeEvent; bool m_lastChangeWasUserEdit; diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp index 2c93164..eaa7eca 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.cpp +++ b/WebCore/rendering/RenderTextControlMultiLine.cpp @@ -55,8 +55,6 @@ void RenderTextControlMultiLine::subtreeHasChanged() if (!node()->focused()) return; - node()->dispatchEvent(Event::create(eventNames().inputEvent, true, false)); - if (Frame* frame = this->frame()) frame->editor()->textDidChangeInTextArea(textArea); } @@ -66,10 +64,7 @@ bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitT if (!RenderTextControl::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction)) return false; - bool resultIsTextValueOrPlaceholder - = (!m_placeholderVisible && result.innerNode() == innerTextElement()) - || (m_placeholderVisible && result.innerNode()->isDescendantOf(innerTextElement())); - if (result.innerNode() == node() || resultIsTextValueOrPlaceholder) + if (result.innerNode() == node() || result.innerNode() == innerTextElement()) hitInnerTextElement(result, x, y, tx, ty); return true; @@ -102,9 +97,9 @@ void RenderTextControlMultiLine::adjustControlHeightBasedOnLineHeight(int lineHe setHeight(height() + lineHeight * static_cast<HTMLTextAreaElement*>(node())->rows()); } -int RenderTextControlMultiLine::baselinePosition(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +int RenderTextControlMultiLine::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const { - return RenderBox::baselinePosition(firstLine, direction, linePositionMode); + return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode); } void RenderTextControlMultiLine::updateFromElement() @@ -112,11 +107,7 @@ void RenderTextControlMultiLine::updateFromElement() createSubtreeIfNeeded(0); RenderTextControl::updateFromElement(); - HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(node()); - if (m_placeholderVisible) - setInnerTextValue(textArea->strippedPlaceholder()); - else - setInnerTextValue(textArea->value()); + setInnerTextValue(static_cast<HTMLTextAreaElement*>(node())->value()); } void RenderTextControlMultiLine::cacheSelection(int start, int end) @@ -126,16 +117,8 @@ void RenderTextControlMultiLine::cacheSelection(int start, int end) PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const RenderStyle* startStyle) const { - RefPtr<RenderStyle> textBlockStyle; - if (m_placeholderVisible) { - if (RenderStyle* pseudoStyle = getCachedPseudoStyle(INPUT_PLACEHOLDER)) - textBlockStyle = RenderStyle::clone(pseudoStyle); - } - if (!textBlockStyle) { - textBlockStyle = RenderStyle::create(); - textBlockStyle->inheritFrom(startStyle); - } - + RefPtr<RenderStyle> textBlockStyle = RenderStyle::create(); + textBlockStyle->inheritFrom(startStyle); adjustInnerTextStyle(startStyle, textBlockStyle.get()); textBlockStyle->setDisplay(BLOCK); @@ -146,5 +129,25 @@ RenderStyle* RenderTextControlMultiLine::textBaseStyle() const { return style(); } + +int RenderTextControlMultiLine::textBlockInsetLeft() const +{ + int inset = borderLeft() + paddingLeft(); + if (HTMLElement* innerText = innerTextElement()) { + if (RenderBox* innerTextRenderer = innerText->renderBox()) + inset += innerTextRenderer->paddingLeft(); + } + return inset; +} + +int RenderTextControlMultiLine::textBlockInsetRight() const +{ + int inset = borderRight() + paddingRight(); + if (HTMLElement* innerText = innerTextElement()) { + if (RenderBox* innerTextRenderer = innerText->renderBox()) + inset += innerTextRenderer->paddingRight(); + } + return inset; +} } diff --git a/WebCore/rendering/RenderTextControlMultiLine.h b/WebCore/rendering/RenderTextControlMultiLine.h index e061e89..6dc2032 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.h +++ b/WebCore/rendering/RenderTextControlMultiLine.h @@ -43,13 +43,15 @@ private: virtual float getAvgCharWidth(AtomicString family); virtual int preferredContentWidth(float charWidth) const; virtual void adjustControlHeightBasedOnLineHeight(int lineHeight); - virtual int baselinePosition(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; + virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; virtual void updateFromElement(); virtual void cacheSelection(int start, int end); virtual RenderStyle* textBaseStyle() const; virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const; + virtual int textBlockInsetLeft() const; + virtual int textBlockInsetRight() const; }; inline RenderTextControlMultiLine* toRenderTextControlMultiLine(RenderObject* object) diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index ea03c61..da85863 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -401,7 +401,7 @@ void RenderTextControlSingleLine::forwardEvent(Event* event) m_resultsButton->defaultEventHandler(event); else if (m_cancelButton && localPoint.x() > textRight) m_cancelButton->defaultEventHandler(event); - else if (m_innerSpinButton && localPoint.x() > textRight && localPoint.x() < textRight + m_innerSpinButton->renderBox()->width()) + else if (m_innerSpinButton && localPoint.x() > textRight && m_innerSpinButton->renderBox() && localPoint.x() < textRight + m_innerSpinButton->renderBox()->width()) m_innerSpinButton->defaultEventHandler(event); else if (m_outerSpinButton && localPoint.x() > textRight) m_outerSpinButton->defaultEventHandler(event); @@ -678,25 +678,14 @@ void RenderTextControlSingleLine::updateFromElement() if (m_cancelButton) updateCancelButtonVisibility(); - if (m_placeholderVisible) { - // node() must be an HTMLInputElement. WMLInputElement doesn't support placeholder. - ASSERT(node()->isHTMLElement()); - ExceptionCode ec = 0; - innerTextElement()->setInnerText(static_cast<HTMLInputElement*>(node())->strippedPlaceholder(), ec); - ASSERT(!ec); - } else { - if (!inputElement()->suggestedValue().isNull()) - setInnerTextValue(inputElement()->suggestedValue()); - else { - bool shouldUpdateValue = true; - if (node()->isHTMLElement()) { - // For HTMLInputElement, update the renderer value if the element - // supports placeholder or the formControlValueMatchesRenderer() - // flag is false. It protects an unacceptable renderer value from - // being overwritten with the DOM value. - shouldUpdateValue = static_cast<HTMLTextFormControlElement*>(node())->supportsPlaceholder() || !static_cast<HTMLInputElement*>(node())->formControlValueMatchesRenderer(); - } - if (shouldUpdateValue) + if (!inputElement()->suggestedValue().isNull()) + setInnerTextValue(inputElement()->suggestedValue()); + else { + if (node()->hasTagName(inputTag)) { + // For HTMLInputElement, update the renderer value if the formControlValueMatchesRenderer() + // flag is false. It protects an unacceptable renderer value from + // being overwritten with the DOM value. + if (!static_cast<HTMLInputElement*>(node())->formControlValueMatchesRenderer()) setInnerTextValue(inputElement()->value()); } } @@ -712,16 +701,8 @@ void RenderTextControlSingleLine::cacheSelection(int start, int end) PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const { - RefPtr<RenderStyle> textBlockStyle; - if (m_placeholderVisible) { - if (RenderStyle* pseudoStyle = getCachedPseudoStyle(INPUT_PLACEHOLDER)) - textBlockStyle = RenderStyle::clone(pseudoStyle); - } - if (!textBlockStyle) { - textBlockStyle = RenderStyle::create(); - textBlockStyle->inheritFrom(startStyle); - } - + RefPtr<RenderStyle> textBlockStyle = RenderStyle::create(); + textBlockStyle->inheritFrom(startStyle); adjustInnerTextStyle(startStyle, textBlockStyle.get()); textBlockStyle->setWhiteSpace(PRE); @@ -744,13 +725,6 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const textBlockStyle->setPaddingLeft(Length(1, Fixed)); textBlockStyle->setPaddingRight(Length(1, Fixed)); - // When the placeholder is going to be displayed, temporarily override the text security to be "none". - // After this, updateFromElement will immediately update the text displayed. - // When the placeholder is no longer visible, updatePlaceholderVisiblity will reset the style, - // and the text security mode will be set back to the computed value correctly. - if (m_placeholderVisible) - textBlockStyle->setTextSecurity(TSNONE); - return textBlockStyle.release(); } @@ -956,7 +930,7 @@ PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const PopupMenuStyle RenderTextControlSingleLine::menuStyle() const { - return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, style()->textIndent(), style()->direction()); + return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, style()->display() == NONE, style()->textIndent(), style()->direction()); } int RenderTextControlSingleLine::clientInsetLeft() const @@ -1116,4 +1090,24 @@ InputElement* RenderTextControlSingleLine::inputElement() const return toInputElement(static_cast<Element*>(node())); } +int RenderTextControlSingleLine::textBlockInsetLeft() const +{ + int inset = borderLeft() + clientPaddingLeft(); + if (HTMLElement* innerText = innerTextElement()) { + if (RenderBox* innerTextRenderer = innerText->renderBox()) + inset += innerTextRenderer->paddingLeft(); + } + return inset; +} + +int RenderTextControlSingleLine::textBlockInsetRight() const +{ + int inset = borderRight() + clientPaddingRight(); + if (HTMLElement* innerText = innerTextElement()) { + if (RenderBox* innerTextRenderer = innerText->renderBox()) + inset += innerTextRenderer->paddingRight(); + } + return inset; +} + } diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index 0deb063..26987fd 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -143,6 +143,9 @@ private: InputElement* inputElement() const; + virtual int textBlockInsetLeft() const; + virtual int textBlockInsetRight() const; + bool m_searchPopupIsVisible; bool m_shouldDrawCapsLockIndicator; @@ -161,7 +164,7 @@ private: }; inline RenderTextControlSingleLine* toRenderTextControlSingleLine(RenderObject* object) -{ +{ ASSERT(!object || object->isTextField()); return static_cast<RenderTextControlSingleLine*>(object); } diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index ec36b7e..f93cd55 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -413,6 +413,41 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o, } } } + + if (behavior & RenderAsTextShowLayoutState) { + bool needsLayout = o.selfNeedsLayout() || o.needsPositionedMovementLayout() || o.posChildNeedsLayout() || o.normalChildNeedsLayout(); + if (needsLayout) + ts << " (needs layout:"; + + bool havePrevious = false; + if (o.selfNeedsLayout()) { + ts << " self"; + havePrevious = true; + } + + if (o.needsPositionedMovementLayout()) { + if (havePrevious) + ts << ","; + havePrevious = true; + ts << " positioned movement"; + } + + if (o.normalChildNeedsLayout()) { + if (havePrevious) + ts << ","; + havePrevious = true; + ts << " child"; + } + + if (o.posChildNeedsLayout()) { + if (havePrevious) + ts << ","; + ts << " positioned child"; + } + + if (needsLayout) + ts << ")"; + } #if PLATFORM(QT) // Print attributes of embedded QWidgets. E.g. when the WebCore::Widget @@ -691,7 +726,8 @@ String externalRepresentation(Frame* frame, RenderAsTextBehavior behavior) printContext.begin(frame->contentRenderer()->width()); } - frame->document()->updateLayout(); + if (!(behavior & RenderAsTextDontUpdateLayout)) + frame->document()->updateLayout(); RenderObject* o = frame->contentRenderer(); if (!o) diff --git a/WebCore/rendering/RenderTreeAsText.h b/WebCore/rendering/RenderTreeAsText.h index 59a0abb..4c8b145 100644 --- a/WebCore/rendering/RenderTreeAsText.h +++ b/WebCore/rendering/RenderTreeAsText.h @@ -48,7 +48,9 @@ enum RenderAsTextBehaviorFlags { RenderAsTextShowCompositedLayers = 1 << 2, // Show which layers are composited. RenderAsTextShowAddresses = 1 << 3, // Show layer and renderer addresses. RenderAsTextShowIDAndClass = 1 << 4, // Show id and class attributes - RenderAsTextPrintingMode = 1 << 5 // Dump the tree in printing mode. + RenderAsTextPrintingMode = 1 << 5, // Dump the tree in printing mode. + RenderAsTextDontUpdateLayout = 1 << 6, // Don't update layout, to make it safe to call showLayerTree() from the debugger inside layout or painting code. + RenderAsTextShowLayoutState = 1 << 7 // Print the various 'needs layout' bits on renderers. }; typedef unsigned RenderAsTextBehavior; diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp index 3349403..2885f15 100644 --- a/WebCore/rendering/RenderView.cpp +++ b/WebCore/rendering/RenderView.cpp @@ -307,11 +307,6 @@ void RenderView::repaintRectangleInViewAndCompositedLayers(const IntRect& ur, bo repaintViewRectangle(ur, immediate); #if USE(ACCELERATED_COMPOSITING) - // If we're a frame, repaintViewRectangle will have repainted via a RenderObject in the - // parent document. - if (document()->ownerElement()) - return; - if (compositor()->inCompositingMode()) compositor()->repaintCompositedLayersAbsoluteRect(ur); #endif @@ -326,6 +321,7 @@ void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, I if (printing()) return; +<<<<<<< HEAD #ifdef ANDROID_FIXED_ELEMENTS #if ENABLE(COMPOSITED_FIXED_ELEMENTS) const Settings * settings = document()->settings(); @@ -335,6 +331,17 @@ void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, I if (false) #endif #endif +======= + if (style()->isFlippedBlocksWritingMode()) { + // We have to flip by hand since the view's logical height has not been determined. We + // can use the viewport width and height. + if (style()->isHorizontalWritingMode()) + rect.setY(viewHeight() - rect.bottom()); + else + rect.setX(viewWidth() - rect.right()); + } + +>>>>>>> webkit.org at r72274 if (fixed && m_frameView) rect.move(m_frameView->scrollX(), m_frameView->scrollY()); diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp index 3e5b6c7..cdc6525 100644 --- a/WebCore/rendering/RootInlineBox.cpp +++ b/WebCore/rendering/RootInlineBox.cpp @@ -47,6 +47,7 @@ RootInlineBox::RootInlineBox(RenderBlock* block) , m_lineBottom(0) , m_paginationStrut(0) , m_blockLogicalHeight(0) + , m_baselineType(AlphabeticBaseline) { setIsHorizontal(block->style()->isHorizontalWritingMode()); } @@ -214,7 +215,7 @@ void RootInlineBox::childRemoved(InlineBox* box) } } -int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAndFallbackFontsMap& textBoxDataMap) +int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache) { #if ENABLE(SVG) // SVG will handle vertical alignment on its own. @@ -226,11 +227,16 @@ int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAn int maxPositionBottom = 0; int maxAscent = 0; int maxDescent = 0; + bool setMaxAscent = false; + bool setMaxDescent = false; // Figure out if we're in no-quirks mode. bool noQuirksMode = renderer()->document()->inNoQuirksMode(); - computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, noQuirksMode, textBoxDataMap); + m_baselineType = requiresIdeographicBaseline(textBoxDataMap) ? IdeographicBaseline : AlphabeticBaseline; + + computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, setMaxAscent, setMaxDescent, noQuirksMode, + textBoxDataMap, m_baselineType, verticalPositionCache); if (maxAscent + maxDescent < max(maxPositionTop, maxPositionBottom)) adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom); @@ -239,7 +245,7 @@ int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAn int lineTop = heightOfBlock; int lineBottom = heightOfBlock; bool setLineTop = false; - placeBoxesInBlockDirection(heightOfBlock, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom, setLineTop); + placeBoxesInBlockDirection(heightOfBlock, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom, setLineTop, m_baselineType); computeBlockDirectionOverflow(lineTop, lineBottom, noQuirksMode, textBoxDataMap); setLineTopBottomPositions(lineTop, lineBottom); @@ -403,7 +409,7 @@ static bool isEditableLeaf(InlineBox* leaf) return leaf && leaf->renderer() && leaf->renderer()->node() && leaf->renderer()->node()->isContentEditable(); } -InlineBox* RootInlineBox::closestLeafChildForXPos(int x, bool onlyEditableLeaves) +InlineBox* RootInlineBox::closestLeafChildForLogicalLeftPosition(int leftPosition, bool onlyEditableLeaves) { InlineBox* firstLeaf = firstLeafChild(); InlineBox* lastLeaf = lastLeafChild(); @@ -411,13 +417,13 @@ InlineBox* RootInlineBox::closestLeafChildForXPos(int x, bool onlyEditableLeaves return firstLeaf; // Avoid returning a list marker when possible. - if (x <= firstLeaf->m_x && !firstLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(firstLeaf))) - // The x coordinate is less or equal to left edge of the firstLeaf. + if (leftPosition <= firstLeaf->logicalLeft() && !firstLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(firstLeaf))) + // The leftPosition coordinate is less or equal to left edge of the firstLeaf. // Return it. return firstLeaf; - if (x >= lastLeaf->m_x + lastLeaf->m_logicalWidth && !lastLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(lastLeaf))) - // The x coordinate is greater or equal to right edge of the lastLeaf. + if (leftPosition >= lastLeaf->logicalRight() && !lastLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(lastLeaf))) + // The leftPosition coordinate is greater or equal to right edge of the lastLeaf. // Return it. return lastLeaf; @@ -425,7 +431,7 @@ InlineBox* RootInlineBox::closestLeafChildForXPos(int x, bool onlyEditableLeaves for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) { if (!leaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(leaf))) { closestLeaf = leaf; - if (x < leaf->m_x + leaf->m_logicalWidth) + if (leftPosition < leaf->logicalRight()) // The x coordinate is less than the right edge of the box. // Return it. return leaf; diff --git a/WebCore/rendering/RootInlineBox.h b/WebCore/rendering/RootInlineBox.h index f13d00f..851b4b1 100644 --- a/WebCore/rendering/RootInlineBox.h +++ b/WebCore/rendering/RootInlineBox.h @@ -57,7 +57,7 @@ public: int selectionBottom() const; int selectionHeight() const { return max(0, selectionBottom() - selectionTop()); } - int alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAndFallbackFontsMap&); + int alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&); void setLineTopBottomPositions(int top, int bottom); virtual RenderLineBoxList* rendererLineBoxes() const; @@ -88,7 +88,7 @@ public: virtual void clearTruncation(); - virtual int baselinePosition() const { return boxModelObject()->baselinePosition(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); } + virtual int baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); } virtual int lineHeight() const { return boxModelObject()->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); } #if PLATFORM(MAC) @@ -110,7 +110,7 @@ public: RenderBlock* block() const; - InlineBox* closestLeafChildForXPos(int x, bool onlyEditableLeaves = false); + InlineBox* closestLeafChildForLogicalLeftPosition(int, bool onlyEditableLeaves = false); Vector<RenderBox*>& floats() { @@ -125,6 +125,8 @@ public: virtual void extractLineBoxFromRenderObject(); virtual void attachLineBoxToRenderObject(); virtual void removeLineBoxFromRenderObject(); + + FontBaseline baselineType() const { return m_baselineType; } private: bool hasEllipsisBox() const { return m_hasEllipsisBoxOrHyphen; } @@ -148,6 +150,9 @@ private: // The logical height of the block at the end of this line. This is where the next line starts. int m_blockLogicalHeight; + // Whether or not this line uses alphabetic or ideographic baselines by default. + FontBaseline m_baselineType; + WTF::Unicode::Direction m_lineBreakBidiStatusEor : 5; WTF::Unicode::Direction m_lineBreakBidiStatusLastStrong : 5; WTF::Unicode::Direction m_lineBreakBidiStatusLast : 5; diff --git a/WebCore/rendering/SVGImageBufferTools.cpp b/WebCore/rendering/SVGImageBufferTools.cpp index 903aa21..20f45b1 100644 --- a/WebCore/rendering/SVGImageBufferTools.cpp +++ b/WebCore/rendering/SVGImageBufferTools.cpp @@ -81,10 +81,8 @@ void SVGImageBufferTools::renderSubtreeToImageBuffer(ImageBuffer* image, RenderO PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, 0, 0, 0); - // FIXME: isSVGContainer returns true for RenderSVGViewportContainer, so if this is ever - // called with one of those, we will read from the wrong offset in an object due to a bad cast. RenderSVGContainer* svgContainer = 0; - if (item && item->isSVGContainer()) + if (item && item->isSVGContainer() && !item->isSVGViewportContainer()) svgContainer = toRenderSVGContainer(item); bool drawsContents = svgContainer ? svgContainer->drawsContents() : false; diff --git a/WebCore/rendering/ShadowElement.cpp b/WebCore/rendering/ShadowElement.cpp index c52ce17..cea3164 100644 --- a/WebCore/rendering/ShadowElement.cpp +++ b/WebCore/rendering/ShadowElement.cpp @@ -45,7 +45,7 @@ void ShadowBlockElement::layoutAsPart(const IntRect& partRect) RenderBox* selfRenderer = toRenderBox(renderer()); IntRect oldRect = selfRenderer->frameRect(); - LayoutStateMaintainer statePusher(parentRenderer->view(), parentRenderer, parentRenderer->size()); + LayoutStateMaintainer statePusher(parentRenderer->view(), parentRenderer, parentRenderer->size(), parentRenderer->style()->isFlippedBlocksWritingMode()); if (oldRect.size() != partRect.size()) selfRenderer->setChildNeedsLayout(true, false); diff --git a/WebCore/rendering/ShadowElement.h b/WebCore/rendering/ShadowElement.h index 04db62b..f5668ef 100644 --- a/WebCore/rendering/ShadowElement.h +++ b/WebCore/rendering/ShadowElement.h @@ -43,13 +43,13 @@ protected: { } - HTMLElement* shadowParent() const { return m_shadowParent; } + HTMLElement* shadowParent() const { return m_shadowParent.get(); } private: virtual bool isShadowNode() const { return true; } - virtual ContainerNode* shadowParentNode() { return m_shadowParent; } + virtual ContainerNode* shadowParentNode() { return m_shadowParent.get(); } - HTMLElement* m_shadowParent; + RefPtr<HTMLElement> m_shadowParent; }; class ShadowBlockElement : public ShadowElement<HTMLDivElement> { diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp index 6495d04..fba523e 100644 --- a/WebCore/rendering/TextControlInnerElements.cpp +++ b/WebCore/rendering/TextControlInnerElements.cpp @@ -51,23 +51,11 @@ public: RenderTextControlInnerBlock(Node* node, bool isMultiLine) : RenderBlock(node), m_multiLine(isMultiLine) { } private: - virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); virtual VisiblePosition positionForPoint(const IntPoint&); bool m_multiLine; }; -bool RenderTextControlInnerBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) -{ - RenderObject* renderer = node()->shadowAncestorNode()->renderer(); - - bool placeholderIsVisible = false; - if (renderer->isTextField()) - placeholderIsVisible = toRenderTextControlSingleLine(renderer)->placeholderIsVisible(); - - return RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, placeholderIsVisible ? HitTestBlockBackground : hitTestAction); -} - VisiblePosition RenderTextControlInnerBlock::positionForPoint(const IntPoint& point) { IntPoint contentsPoint(point); @@ -154,7 +142,7 @@ void TextControlInnerTextElement::defaultEventHandler(Event* event) if (shadowAncestor && shadowAncestor != this) shadowAncestor->defaultEventHandler(event); } - if (event->defaultHandled()) + if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); } diff --git a/WebCore/rendering/TextControlInnerElements.h b/WebCore/rendering/TextControlInnerElements.h index 61c9dba..51c9aff 100644 --- a/WebCore/rendering/TextControlInnerElements.h +++ b/WebCore/rendering/TextControlInnerElements.h @@ -47,12 +47,12 @@ protected: private: virtual bool isMouseFocusable() const { return false; } - virtual bool isShadowNode() const { return m_shadowParent; } - virtual ContainerNode* shadowParentNode() { return m_shadowParent; } + virtual bool isShadowNode() const { return m_shadowParent.get(); } + virtual ContainerNode* shadowParentNode() { return m_shadowParent.get(); } virtual bool isSpellCheckingEnabled() const; void setShadowParentNode(HTMLElement* shadowParent) { m_shadowParent = shadowParent; } - HTMLElement* m_shadowParent; + RefPtr<HTMLElement> m_shadowParent; }; class TextControlInnerTextElement : public TextControlInnerElement { diff --git a/WebCore/rendering/VerticalPositionCache.h b/WebCore/rendering/VerticalPositionCache.h new file mode 100644 index 0000000..4deaef5 --- /dev/null +++ b/WebCore/rendering/VerticalPositionCache.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VerticalPositionCache_h +#define VerticalPositionCache_h + +#include "FontBaseline.h" +#include <wtf/HashMap.h> + +namespace WebCore { + +class RenderObject; + +// Values for vertical alignment. +const int PositionTop = -0x7fffffff; +const int PositionBottom = 0x7fffffff; +const int PositionUndefined = 0x80000000; + +class VerticalPositionCache : public Noncopyable { +public: + VerticalPositionCache() + { } + + int get(RenderObject* renderer, FontBaseline baselineType) const + { + const HashMap<RenderObject*, int>& mapToCheck = baselineType == AlphabeticBaseline ? m_alphabeticPositions : m_ideographicPositions; + const HashMap<RenderObject*, int>::const_iterator it = mapToCheck.find(renderer); + if (it == mapToCheck.end()) + return PositionUndefined; + return it->second; + } + + void set(RenderObject* renderer, FontBaseline baselineType, int position) + { + if (baselineType == AlphabeticBaseline) + m_alphabeticPositions.set(renderer, position); + else + m_ideographicPositions.set(renderer, position); + } + +private: + HashMap<RenderObject*, int> m_alphabeticPositions; + HashMap<RenderObject*, int> m_ideographicPositions; +}; + +} // namespace WebCore + +#endif // VerticalPositionCache_h diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index a6e7d59..0ea3673 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -1332,6 +1332,36 @@ Length RenderStyle::marginEndUsing(const RenderStyle* otherStyle) const return otherStyle->isLeftToRightDirection() ? marginBottom() : marginTop(); } +void RenderStyle::setMarginStart(Length margin) +{ + if (isHorizontalWritingMode()) { + if (isLeftToRightDirection()) + setMarginLeft(margin); + else + setMarginRight(margin); + } else { + if (isLeftToRightDirection()) + setMarginTop(margin); + else + setMarginBottom(margin); + } +} + +void RenderStyle::setMarginEnd(Length margin) +{ + if (isHorizontalWritingMode()) { + if (isLeftToRightDirection()) + setMarginRight(margin); + else + setMarginLeft(margin); + } else { + if (isLeftToRightDirection()) + setMarginBottom(margin); + else + setMarginTop(margin); + } +} + Length RenderStyle::paddingBefore() const { switch (writingMode()) { diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index 75dc58f..c206acd 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -985,6 +985,8 @@ public: void setMarginBottom(Length v) { SET_VAR(surround, margin.m_bottom, v) } void setMarginLeft(Length v) { SET_VAR(surround, margin.m_left, v) } void setMarginRight(Length v) { SET_VAR(surround, margin.m_right, v) } + void setMarginStart(Length); + void setMarginEnd(Length); void resetPadding() { SET_VAR(surround, padding, LengthBox(Auto)) } void setPaddingBox(const LengthBox& b) { SET_VAR(surround, padding, b) } diff --git a/WebCore/rendering/svg/SVGInlineTextBox.cpp b/WebCore/rendering/svg/SVGInlineTextBox.cpp index 699d788..d1f660a 100644 --- a/WebCore/rendering/svg/SVGInlineTextBox.cpp +++ b/WebCore/rendering/svg/SVGInlineTextBox.cpp @@ -588,7 +588,7 @@ IntRect SVGInlineTextBox::calculateBoundaries() const RenderStyle* style = textRenderer->style(); ASSERT(style); - int baseline = baselinePosition(); + int baseline = baselinePosition(AlphabeticBaseline); int heightDifference = baseline - style->font().ascent(); unsigned textFragmentsSize = m_textFragments.size(); |